44#if defined(INFIX_OS_WINDOWS)
54#if defined(INFIX_OS_MACOS)
56#include <libkern/OSCacheControl.h>
59#if defined(INFIX_ENV_POSIX) && !defined(INFIX_OS_WINDOWS)
60#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
61#define MAP_ANON MAP_ANONYMOUS
63static pthread_mutex_t g_dwarf_mutex = PTHREAD_MUTEX_INITIALIZER;
66#if defined(INFIX_OS_WINDOWS) && defined(INFIX_ARCH_X64)
69#define UWOP_PUSH_NONVOL 0
70#define UWOP_ALLOC_LARGE 1
71#define UWOP_ALLOC_SMALL 2
72#define UWOP_SET_FPREG 3
75typedef struct _UNWIND_CODE {
81typedef struct _UNWIND_INFO {
84 uint8_t SizeOfPrologue;
86 uint8_t FrameRegister : 4;
87 uint8_t FrameOffset : 4;
88 UNWIND_CODE UnwindCode[1];
92#define INFIX_SEH_METADATA_SIZE 256
93#elif defined(INFIX_OS_WINDOWS) && defined(INFIX_ARCH_AARCH64)
95typedef struct _UNWIND_INFO_ARM64 {
96 uint32_t FunctionLength : 18;
100 uint32_t EpilogueCount : 5;
101 uint32_t CodeWords : 5;
104#define INFIX_SEH_METADATA_SIZE 256
106#define INFIX_SEH_METADATA_SIZE 0
110#if defined(INFIX_OS_MACOS)
125typedef const struct __CFString * CFStringRef;
126typedef const void * CFTypeRef;
127typedef struct __SecTask * SecTaskRef;
128typedef struct __CFError * CFErrorRef;
129#define kCFStringEncodingUTF8 0x08000100
132 void (*CFRelease)(CFTypeRef);
133 bool (*CFBooleanGetValue)(CFTypeRef boolean);
134 CFStringRef (*CFStringCreateWithCString)(CFTypeRef allocator,
const char * cStr, uint32_t encoding);
135 CFTypeRef kCFAllocatorDefault;
136 SecTaskRef (*SecTaskCreateFromSelf)(CFTypeRef allocator);
137 CFTypeRef (*SecTaskCopyValueForEntitlement)(SecTaskRef task, CFStringRef entitlement, CFErrorRef * error);
138 void (*pthread_jit_write_protect_np)(
int enabled);
139 void (*sys_icache_invalidate)(
void *
start,
size_t len);
148static void initialize_macos_apis(
void) {
150 void * cf = dlopen(
"/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", RTLD_LAZY);
151 void * sec = dlopen(
"/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY);
154 g_macos_apis.pthread_jit_write_protect_np = dlsym(RTLD_DEFAULT,
"pthread_jit_write_protect_np");
155 g_macos_apis.sys_icache_invalidate = dlsym(RTLD_DEFAULT,
"sys_icache_invalidate");
158 INFIX_DEBUG_PRINTF(
"Warning: Could not dlopen macOS frameworks. JIT security features will be degraded.");
165 g_macos_apis.CFRelease = dlsym(cf,
"CFRelease");
166 g_macos_apis.CFBooleanGetValue = dlsym(cf,
"CFBooleanGetValue");
167 g_macos_apis.CFStringCreateWithCString = dlsym(cf,
"CFStringCreateWithCString");
168 void ** pAlloc = (
void **)dlsym(cf,
"kCFAllocatorDefault");
170 g_macos_apis.kCFAllocatorDefault = *pAlloc;
171 g_macos_apis.SecTaskCreateFromSelf = dlsym(sec,
"SecTaskCreateFromSelf");
172 g_macos_apis.SecTaskCopyValueForEntitlement = dlsym(sec,
"SecTaskCopyValueForEntitlement");
181static bool has_jit_entitlement(
void) {
183 static pthread_once_t init_once = PTHREAD_ONCE_INIT;
184 pthread_once(&init_once, initialize_macos_apis);
187 if (!g_macos_apis.pthread_jit_write_protect_np)
190 if (!g_macos_apis.SecTaskCopyValueForEntitlement || !g_macos_apis.CFStringCreateWithCString)
193 SecTaskRef task = g_macos_apis.SecTaskCreateFromSelf(g_macos_apis.kCFAllocatorDefault);
196 CFStringRef key = g_macos_apis.CFStringCreateWithCString(
197 g_macos_apis.kCFAllocatorDefault,
"com.apple.security.cs.allow-jit", kCFStringEncodingUTF8);
198 CFTypeRef value =
nullptr;
201 value = g_macos_apis.SecTaskCopyValueForEntitlement(task, key,
nullptr);
202 g_macos_apis.CFRelease(key);
204 g_macos_apis.CFRelease(task);
207 if (g_macos_apis.CFBooleanGetValue && g_macos_apis.CFBooleanGetValue(value))
209 g_macos_apis.CFRelease(value);
215#if !defined(INFIX_OS_WINDOWS) && !defined(INFIX_OS_MACOS) && !defined(INFIX_OS_ANDROID) && !defined(INFIX_OS_OPENBSD)
218#if defined(INFIX_OS_LINUX) && defined(_GNU_SOURCE)
219#include <sys/syscall.h>
232#if defined(INFIX_OS_LINUX) && defined(MFD_CLOEXEC)
235 int linux_fd = memfd_create(
"infix_jit", MFD_CLOEXEC);
241#if defined(__FreeBSD__) && defined(SHM_ANON)
243 int bsd_fd = shm_open(SHM_ANON, O_RDWR | O_CREAT | O_EXCL, 0600);
250 uint64_t random_val = 0;
253 int rand_fd = open(
"/dev/urandom", O_RDONLY);
256 ssize_t bytes_read = read(rand_fd, &random_val,
sizeof(random_val));
258 if (bytes_read !=
sizeof(random_val))
261 snprintf(shm_name,
sizeof(shm_name),
"/infix-jit-%d-%llx", getpid(), (
unsigned long long)random_val);
263 int fd = shm_open(shm_name, O_RDWR | O_CREAT | O_EXCL, 0600);
266 shm_unlink(shm_name);
281#if defined(INFIX_OS_WINDOWS)
283 .
rx_ptr =
nullptr, .rw_ptr =
nullptr, .size = 0, .handle =
nullptr, .seh_registration =
nullptr};
290#if defined(INFIX_OS_WINDOWS)
295 void * code = VirtualAlloc(
nullptr, total_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
296 if (code ==
nullptr) {
303#elif defined(INFIX_OS_MACOS) || defined(INFIX_OS_ANDROID) || defined(INFIX_OS_OPENBSD) || defined(INFIX_OS_DRAGONFLY)
305 void * code = MAP_FAILED;
307 int flags = MAP_PRIVATE | MAP_ANON;
308#if defined(INFIX_OS_MACOS)
310 static bool g_use_secure_jit_path =
false;
311 static bool g_checked_jit_support =
false;
312 if (!g_checked_jit_support) {
313 g_use_secure_jit_path = has_jit_entitlement();
315 g_use_secure_jit_path ?
"yes" :
"no",
316 g_use_secure_jit_path ?
"secure (MAP_JIT)" :
"legacy (mprotect)");
317 g_checked_jit_support =
true;
320 if (g_use_secure_jit_path)
323 code = mmap(
nullptr, size, PROT_READ | PROT_WRITE, flags, -1, 0);
324#if defined(INFIX_OS_MACOS)
325 if (code != MAP_FAILED && g_use_secure_jit_path) {
327 g_macos_apis.pthread_jit_write_protect_np(0);
331 if (code == MAP_FAILED) {
332 int fd = open(
"/dev/zero", O_RDWR);
334 code = mmap(
nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
338 if (code == MAP_FAILED) {
352 if (ftruncate(exec.
shm_fd, size) != 0) {
360 exec.
rw_ptr = mmap(
nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, exec.
shm_fd, 0);
362 exec.
rx_ptr = mmap(
nullptr, size, PROT_READ | PROT_EXEC, MAP_SHARED, exec.
shm_fd, 0);
364 if (exec.
rw_ptr == MAP_FAILED || exec.
rx_ptr == MAP_FAILED) {
366 if (exec.
rw_ptr != MAP_FAILED)
367 munmap(exec.
rw_ptr, size);
368 if (exec.
rx_ptr != MAP_FAILED)
369 munmap(exec.
rx_ptr, size);
372 return (
infix_executable_t){.rx_ptr =
nullptr, .rw_ptr =
nullptr, .size = 0, .shm_fd = -1};
386#if defined(INFIX_OS_WINDOWS)
397static EXCEPTION_DISPOSITION _infix_seh_personality_routine(PEXCEPTION_RECORD ExceptionRecord,
398 void * EstablisherFrame,
400 void * DispatcherContext) {
401 PDISPATCHER_CONTEXT dc = (PDISPATCHER_CONTEXT)DispatcherContext;
404 if (ExceptionRecord->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND))
405 return ExceptionContinueSearch;
412 uint32_t epilogue_offset = *(uint32_t *)dc->HandlerData;
413 void * target_ip = (
void *)(dc->ImageBase + epilogue_offset);
416 RtlUnwind(EstablisherFrame, target_ip, ExceptionRecord,
nullptr);
418 return ExceptionContinueSearch;
421#if defined(INFIX_ARCH_X64)
425 uint32_t prologue_size,
426 uint32_t epilogue_offset) {
428 uint8_t * metadata_base = (uint8_t *)exec->
rw_ptr + exec->
size;
431 RUNTIME_FUNCTION * rf = (RUNTIME_FUNCTION *)
_infix_align_up((
size_t)metadata_base, 4);
434 UNWIND_INFO * ui = (UNWIND_INFO *)
_infix_align_up((
size_t)(rf + 1), 2);
439 ui->Flags |= UNW_FLAG_EHANDLER;
440 ui->FrameRegister = 5;
442 ui->SizeOfPrologue = (uint8_t)prologue_size;
446 ui->CountOfCodes = 4;
447 ui->UnwindCode[0].CodeOffset = 6;
448 ui->UnwindCode[0].UnwindOp = UWOP_SET_FPREG;
449 ui->UnwindCode[0].OpInfo = 0;
451 ui->UnwindCode[1].CodeOffset = 3;
452 ui->UnwindCode[1].UnwindOp = UWOP_PUSH_NONVOL;
453 ui->UnwindCode[1].OpInfo = 7;
455 ui->UnwindCode[2].CodeOffset = 2;
456 ui->UnwindCode[2].UnwindOp = UWOP_PUSH_NONVOL;
457 ui->UnwindCode[2].OpInfo = 6;
459 ui->UnwindCode[3].CodeOffset = 1;
460 ui->UnwindCode[3].UnwindOp = UWOP_PUSH_NONVOL;
461 ui->UnwindCode[3].OpInfo = 5;
465 ui->CountOfCodes = 6;
467 ui->UnwindCode[0].CodeOffset = 12;
468 ui->UnwindCode[0].UnwindOp = UWOP_SET_FPREG;
469 ui->UnwindCode[0].OpInfo = 0;
471 ui->UnwindCode[1].CodeOffset = 9;
472 ui->UnwindCode[1].UnwindOp = UWOP_PUSH_NONVOL;
473 ui->UnwindCode[1].OpInfo = 15;
475 ui->UnwindCode[2].CodeOffset = 7;
476 ui->UnwindCode[2].UnwindOp = UWOP_PUSH_NONVOL;
477 ui->UnwindCode[2].OpInfo = 14;
479 ui->UnwindCode[3].CodeOffset = 5;
480 ui->UnwindCode[3].UnwindOp = UWOP_PUSH_NONVOL;
481 ui->UnwindCode[3].OpInfo = 13;
483 ui->UnwindCode[4].CodeOffset = 3;
484 ui->UnwindCode[4].UnwindOp = UWOP_PUSH_NONVOL;
485 ui->UnwindCode[4].OpInfo = 12;
487 ui->UnwindCode[5].CodeOffset = 1;
488 ui->UnwindCode[5].UnwindOp = UWOP_PUSH_NONVOL;
489 ui->UnwindCode[5].OpInfo = 5;
494 uint32_t * eh_field_ptr = (uint32_t *)&ui->UnwindCode[(ui->CountOfCodes + 1) & ~1];
497 uint8_t * stub = (uint8_t *)
_infix_align_up((
size_t)(eh_field_ptr + 2), 16);
501 *(uint64_t *)(stub + 2) = (uint64_t)_infix_seh_personality_routine;
506 DWORD64 base_address = (DWORD64)exec->rx_ptr & ~0xFFFF;
507 DWORD rva_offset = (DWORD)((uint8_t *)exec->rx_ptr - (uint8_t *)base_address);
509 rf->BeginAddress = rva_offset;
511 rf->EndAddress = rva_offset + (DWORD)exec->size;
512 rf->UnwindData = rva_offset + (DWORD)((uint8_t *)ui - (uint8_t *)exec->rx_ptr);
514 if (ui->Flags & UNW_FLAG_EHANDLER) {
516 eh_field_ptr[0] = rva_offset + (uint32_t)(stub - (uint8_t *)exec->rx_ptr);
518 eh_field_ptr[1] = epilogue_offset;
521 if (RtlAddFunctionTable(rf, 1, base_address)) {
522 exec->seh_registration = rf;
524 "Registered SEH PDATA at %p (XDATA at %p, Stub at %p) for JIT code at %p", rf, ui, stub, exec->rx_ptr);
527 fprintf(stderr,
"infix: RtlAddFunctionTable failed! GetLastError=%lu\n", GetLastError());
530#elif defined(INFIX_ARCH_AARCH64)
534 uint32_t prologue_size,
535 uint32_t epilogue_offset) {
536 uint8_t * metadata_base = (uint8_t *)exec->
rw_ptr + exec->
size;
540 RUNTIME_FUNCTION * rf = (RUNTIME_FUNCTION *)
_infix_align_up((
size_t)metadata_base, 4);
543 UNWIND_INFO_ARM64 * ui = (UNWIND_INFO_ARM64 *)
_infix_align_up((
size_t)(rf + 2), 4);
546 ui->FunctionLength = (uint32_t)(exec->size / 4);
550 ui->EpilogueCount = 1;
552 uint8_t * unwind_codes = (uint8_t *)(ui + 1);
553 uint32_t code_idx = 0;
558 unwind_codes[code_idx++] = 0xE1;
559 unwind_codes[code_idx++] = 0xC8;
560 unwind_codes[code_idx++] = 0xE4;
565 unwind_codes[code_idx++] = 0xE1;
566 unwind_codes[code_idx++] = 0xD4;
567 unwind_codes[code_idx++] = 0xD2;
568 unwind_codes[code_idx++] = 0xC8;
569 unwind_codes[code_idx++] = 0xE4;
572 ui->CodeWords = (code_idx + 3) / 4;
578 uint32_t * epilogue_scopes = (uint32_t *)(ui + 1);
580 epilogue_scopes[0] = (epilogue_offset / 4);
582 uint8_t * unwind_codes_ptr = (uint8_t *)(epilogue_scopes + ui->EpilogueCount);
588 uint32_t * handler_info_ptr = (uint32_t *)(unwind_codes_ptr + ui->CodeWords * 4);
590 uint8_t * stub = (uint8_t *)
_infix_align_up((
size_t)(handler_info_ptr + 2), 16);
596 *(uint32_t *)stub = 0x58000049;
597 *(uint32_t *)(stub + 4) = 0xD61F0120;
598 *(uint64_t *)(stub + 8) = (uint64_t)_infix_seh_personality_routine;
600 DWORD64 base_address = (DWORD64)exec->rx_ptr & ~0xFFFF;
601 DWORD rva_offset = (DWORD)((uint8_t *)exec->rx_ptr - (uint8_t *)base_address);
603 rf[0].BeginAddress = rva_offset;
604 rf[0].UnwindData = rva_offset + (DWORD)((uint8_t *)ui - (uint8_t *)exec->rx_ptr);
607 rf[1].BeginAddress = rva_offset + (DWORD)exec->size;
608 rf[1].UnwindData = 0;
613 handler_info_ptr[0] = rva_offset + (uint32_t)(stub - (uint8_t *)exec->rx_ptr);
614 handler_info_ptr[1] = epilogue_offset;
617 if (RtlAddFunctionTable(rf, 2, base_address)) {
618 exec->seh_registration = rf;
620 "Registered SEH PDATA at %p (XDATA at %p, Stub at %p) for JIT code at %p", rf, ui, stub, exec->rx_ptr);
623 fprintf(stderr,
"infix: RtlAddFunctionTable failed! GetLastError=%lu\n", GetLastError());
629#if defined(INFIX_OS_LINUX) && defined(INFIX_ARCH_X64)
640 const size_t cie_size = 32;
641 const size_t fde_size = 64;
642 const size_t total_size = cie_size + fde_size + 4;
652 *(uint32_t *)
p = (uint32_t)(cie_size - 4);
668 while ((
size_t)(
p - eh) < cie_size)
672 uint8_t * fde_start = eh + cie_size;
674 *(uint32_t *)
p = (uint32_t)(fde_size - 4);
676 *(uint32_t *)
p = (uint32_t)(
p - eh);
681 *(uint64_t *)
p = (uint64_t)exec->
size;
727 while ((
size_t)(
p - eh) < (cie_size + fde_size))
731 extern void __register_frame(
void *);
732 pthread_mutex_lock(&g_dwarf_mutex);
733 __register_frame(eh);
734 pthread_mutex_unlock(&g_dwarf_mutex);
739#elif defined(INFIX_OS_LINUX) && defined(INFIX_ARCH_AARCH64)
750 const size_t cie_size = 32;
751 const size_t fde_size = 64;
752 const size_t total_size = cie_size + fde_size + 4;
762 *(uint32_t *)
p = (uint32_t)(cie_size - 4);
777 while ((
size_t)(
p - eh) < cie_size)
781 uint8_t * fde_start = eh + cie_size;
783 *(uint32_t *)
p = (uint32_t)(fde_size - 4);
785 *(uint32_t *)
p = (uint32_t)(
p - eh);
790 *(uint64_t *)
p = (uint64_t)exec->
size;
836 while ((
size_t)(
p - eh) < (cie_size + fde_size))
841 extern void __register_frame(
void *);
842 pthread_mutex_lock(&g_dwarf_mutex);
843 __register_frame(eh);
844 pthread_mutex_unlock(&g_dwarf_mutex);
866#if defined(INFIX_OS_WINDOWS)
867#if defined(INFIX_ARCH_X64) || defined(INFIX_ARCH_AARCH64)
868 if (exec.seh_registration)
869 RtlDeleteFunctionTable((PRUNTIME_FUNCTION)exec.seh_registration);
873 if (!VirtualProtect(exec.
rw_ptr, exec.
size, PAGE_NOACCESS, &(DWORD){0}))
874 INFIX_DEBUG_PRINTF(
"WARNING: VirtualProtect failed to set PAGE_NOACCESS guard page.");
875 VirtualFree(exec.
rw_ptr, 0, MEM_RELEASE);
877#elif defined(INFIX_OS_MACOS)
885#elif defined(INFIX_OS_ANDROID) || defined(INFIX_OS_OPENBSD) || defined(INFIX_OS_DRAGONFLY)
894 extern void __deregister_frame(
void *);
895 pthread_mutex_lock(&g_dwarf_mutex);
897 pthread_mutex_unlock(&g_dwarf_mutex);
932 if (exec->
rw_ptr ==
nullptr || exec->
size == 0)
939#if defined(INFIX_COMPILER_MSVC)
941 FlushInstructionCache(GetCurrentProcess(), exec->
rw_ptr, exec->
size);
942#elif defined(INFIX_OS_MACOS)
944 if (g_macos_apis.sys_icache_invalidate)
945 g_macos_apis.sys_icache_invalidate(exec->
rw_ptr, exec->
size);
947 __builtin___clear_cache((
char *)exec->
rw_ptr, (
char *)exec->
rw_ptr + exec->
size);
948#elif defined(INFIX_ARCH_AARCH64)
954 __asm__ __volatile__(
"mrs %0, ctr_el0" :
"=r"(ctr_el0));
957 uintptr_t d_line_size = 4 << ((ctr_el0 >> 16) & 0xf);
958 for (uintptr_t addr =
start & ~(d_line_size - 1); addr <
end; addr += d_line_size)
959 __asm__ __volatile__(
"dc cvau, %0" ::
"r"(addr) :
"memory");
960 __asm__ __volatile__(
"dsb ish" :::
"memory");
963 uintptr_t i_line_size = 4 << (ctr_el0 & 0xf);
964 for (uintptr_t addr =
start & ~(i_line_size - 1); addr <
end; addr += i_line_size)
965 __asm__ __volatile__(
"ic ivau, %0" ::
"r"(addr) :
"memory");
966 __asm__ __volatile__(
"dsb ish\n\tisb" :::
"memory");
969 __builtin___clear_cache((
char *)exec->
rw_ptr, (
char *)exec->
rw_ptr + exec->
size);
973#if defined(INFIX_OS_WINDOWS)
975#if defined(INFIX_ARCH_X64)
976 _infix_register_seh_windows_x64(exec, category, prologue_size, epilogue_offset);
977#elif defined(INFIX_ARCH_AARCH64)
978 _infix_register_seh_windows_arm64(exec, category, prologue_size, epilogue_offset);
985#elif defined(INFIX_OS_MACOS)
986 static bool g_use_secure_jit_path =
false;
987 static bool g_checked_jit_support =
false;
988 if (!g_checked_jit_support) {
989 g_use_secure_jit_path = has_jit_entitlement();
990 g_checked_jit_support =
true;
993 if (g_use_secure_jit_path && g_macos_apis.pthread_jit_write_protect_np) {
995 g_macos_apis.pthread_jit_write_protect_np(1);
999 result = (mprotect(exec->
rw_ptr, exec->
size, PROT_READ | PROT_EXEC) == 0);
1003#elif defined(INFIX_OS_ANDROID) || defined(INFIX_OS_OPENBSD) || defined(INFIX_OS_DRAGONFLY)
1005 result = (mprotect(exec->
rw_ptr, exec->
size, PROT_READ | PROT_EXEC) == 0);
1011#if defined(INFIX_OS_LINUX) && defined(INFIX_ARCH_X64)
1012 _infix_register_eh_frame_linux_x64(exec, category);
1013#elif defined(INFIX_OS_LINUX) && defined(INFIX_ARCH_AARCH64)
1014 _infix_register_eh_frame_arm64(exec, category);
1049#if defined(INFIX_OS_WINDOWS)
1050 prot.
rw_ptr = VirtualAlloc(
nullptr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
1054#if defined(MAP_ANON)
1055 prot.
rw_ptr = mmap(
nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1057 int fd = open(
"/dev/zero", O_RDWR);
1059 prot.
rw_ptr = MAP_FAILED;
1061 prot.
rw_ptr = mmap(
nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
1065 if (prot.
rw_ptr == MAP_FAILED) {
1082#if defined(INFIX_OS_WINDOWS)
1083 VirtualFree(prot.
rw_ptr, 0, MEM_RELEASE);
1102 bool result =
false;
1103#if defined(INFIX_OS_WINDOWS)
1104 result = VirtualProtect(prot.
rw_ptr, prot.
size, PAGE_READONLY, &(DWORD){0});
1108 result = (mprotect(prot.
rw_ptr, prot.
size, PROT_READ) == 0);
1139 INFIX_DEBUG_PRINTF(
"Dispatching reverse call. Context: %p, User Fn: %p, ret=%p, args=%p",
1143 (
void *)args_array);
1145 for (
size_t i = 0; i < context->
num_args; i++) {
1147 " args[%zu] = %p (val: 0x%04X)", i, args_array[i], args_array[i] ? *(uint16_t *)args_array[i] : 0);
1162 cif_func(return_value_ptr, args_array);
1169 handler(context, return_value_ptr, args_array);
clock_t start
Definition 901_call_overhead.c:48
clock_t end
Definition 901_call_overhead.c:48
char * p
Definition 904_registry_benchmark.c:25
#define c23_nodiscard
Internal alias for the public INFIX_NODISCARD macro.
Definition compat_c23.h:92
#define c23_maybe_unused
A compatibility macro for the C23 [[maybe_unused]] attribute.
Definition compat_c23.h:156
c23_nodiscard bool infix_executable_make_executable(infix_executable_t *exec, c23_maybe_unused infix_executable_category_t category, c23_maybe_unused uint32_t prologue_size, c23_maybe_unused uint32_t epilogue_offset)
Definition executor.c:928
void infix_protected_free(infix_protected_t prot)
Frees a block of protected memory.
Definition executor.c:1079
void infix_executable_free(infix_executable_t exec)
Frees a block of executable memory and applies guard pages to prevent use-after-free.
Definition executor.c:863
static int create_anonymous_file(void)
Definition executor.c:231
c23_nodiscard infix_protected_t infix_protected_alloc(size_t size)
Allocates a block of standard memory for later protection.
Definition executor.c:1045
c23_nodiscard infix_executable_t infix_executable_alloc(size_t size)
Allocates a block of executable memory using the platform's W^X strategy.
Definition executor.c:280
#define INFIX_SEH_METADATA_SIZE
Definition executor.c:106
c23_nodiscard bool infix_protected_make_readonly(infix_protected_t prot)
Makes a block of memory read-only for security hardening.
Definition executor.c:1099
void infix_internal_dispatch_callback_fn_impl(infix_reverse_t *context, void *return_value_ptr, void **args_array)
The universal C entry point for all reverse call trampolines.
Definition executor.c:1138
@ INFIX_CODE_PROTECTION_FAILURE
Definition infix.h:1371
@ INFIX_CODE_EXECUTABLE_MEMORY_FAILURE
Definition infix.h:1370
@ INFIX_CODE_NATIVE_EXCEPTION
Definition infix.h:1366
@ INFIX_CODE_OUT_OF_MEMORY
Definition infix.h:1369
@ INFIX_CATEGORY_ABI
Definition infix.h:1355
@ INFIX_CATEGORY_ALLOCATION
Definition infix.h:1353
void(* infix_cif_func)(void *, void **)
A function pointer type for a bound forward trampoline.
Definition infix.h:418
size_t size
Definition infix.h:277
void(* infix_closure_handler_fn)(infix_context_t *, void *, void **)
A function pointer type for a generic closure handler.
Definition infix.h:430
INFIX_API INFIX_NODISCARD infix_cif_func infix_forward_get_code(infix_forward_t *)
Gets the callable function pointer from a bound forward trampoline.
Definition trampoline.c:283
#define infix_free
A macro that can be defined to override the default free function.
Definition infix.h:383
#define infix_memcpy
A macro that can be defined to override the default memcpy function.
Definition infix.h:387
#define infix_memset
A macro that can be defined to override the default memset function.
Definition infix.h:391
#define infix_malloc
A macro that can be defined to override the default malloc function.
Definition infix.h:371
Internal data structures, function prototypes, and constants.
infix_executable_category_t
Definition infix_internals.h:698
@ INFIX_EXECUTABLE_REVERSE
Definition infix_internals.h:701
@ INFIX_EXECUTABLE_SAFE_FORWARD
Definition infix_internals.h:700
static size_t _infix_align_up(size_t value, size_t alignment)
Aligns a value up to the next multiple of a power-of-two alignment.
Definition infix_internals.h:767
INFIX_INTERNAL void _infix_set_system_error(infix_error_category_t category, infix_error_code_t code, long system_code, const char *msg)
Sets the thread-local error state for a system-level error.
Definition error.c:244
INFIX_INTERNAL void _infix_set_error(infix_error_category_t category, infix_error_code_t code, size_t position)
Sets the thread-local error state with detailed information.
Definition error.c:175
Internal representation of an executable memory block for JIT code.
Definition infix_internals.h:56
size_t size
Definition infix_internals.h:66
void * rw_ptr
Definition infix_internals.h:65
void * rx_ptr
Definition infix_internals.h:64
void * eh_frame_ptr
Definition infix_internals.h:62
int shm_fd
Definition infix_internals.h:61
Internal representation of a memory block that will be made read-only.
Definition infix_internals.h:77
size_t size
Definition infix_internals.h:79
void * rw_ptr
Definition infix_internals.h:78
Internal definition of a reverse trampoline (callback/closure) handle.
Definition infix_internals.h:119
infix_type * return_type
Definition infix_internals.h:123
void * user_callback_fn
Definition infix_internals.h:128
size_t num_args
Definition infix_internals.h:125
infix_forward_t * cached_forward_trampoline
Definition infix_internals.h:133
A header for conditionally compiled debugging utilities.
#define INFIX_DEBUG_PRINTF(...)
Definition utility.h:97