From 9796328ffa6589bb903f04a9df6403718dd17d79 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 21 Sep 2026 09:43:28 -0700 Subject: [PATCH] only inc x64 into base by default on linux, where we actually apparently need it - ideally we do not just pull in all of x64 just for a few enum codes' --- src/linux/base/linux_base.c | 54 ++++++++++++++++---------------- src/linux/base/linux_base.h | 21 ++++++++----- src/x64/x64.h | 62 +++++++++++++++++++------------------ 3 files changed, 73 insertions(+), 64 deletions(-) diff --git a/src/linux/base/linux_base.c b/src/linux/base/linux_base.c index fec7a0da..e95e2be8 100644 --- a/src/linux/base/linux_base.c +++ b/src/linux/base/linux_base.c @@ -285,7 +285,7 @@ shared_memory_alloc(U64 size, String8 name) SharedMemory result = { max_U64 }; if(size == 0 || size > max_S64) { return result; } - + int id; if(name.size == 0) { @@ -304,7 +304,7 @@ shared_memory_alloc(U64 size, String8 name) if(ftruncate(id, size) == 0) { result.u64[0] = (U64)id; } else { close(id); } } - + return result; } @@ -1107,15 +1107,15 @@ lnx_memory_fault_thread(void *unused) { LNX_MemoryFaultRequest *request = 0; ssize_t count = LNX_RETRY_ON_EINTR(read(lnx_state.demand_memory.requests[0], &request, sizeof(request))); - + if(count == 0) { break; } if(count != sizeof(request)) { _exit(1); } if(request == 0) { break; } - + lnx_in_memory_fault_callback = 1; B32 handled = lnx_state.demand_memory.fault(request->address, lnx_state.demand_memory.user_data); lnx_in_memory_fault_callback = 0; - + U32 *completion = &request->result; ins_atomic_u32_eval_assign(completion, handled ? 2 : 1); syscall(SYS_futex, completion, FUTEX_WAKE_PRIVATE, 1, 0, 0, 0); @@ -1148,25 +1148,25 @@ internal B32 lnx_dispatch_memory_read_fault(int sig, siginfo_t *info, void *context) { LNX_DemandMemory *memory = &lnx_state.demand_memory; - + #if ARCH_X64 || ARCH_X86 if(sig != SIGSEGV || info == 0 || context == 0 || - (info->si_code != SEGV_ACCERR && info->si_code != SEGV_MAPERR) || - lnx_in_memory_fault_callback || - ins_atomic_u32_eval(&memory->active) == 0) + (info->si_code != SEGV_ACCERR && info->si_code != SEGV_MAPERR) || + lnx_in_memory_fault_callback || + ins_atomic_u32_eval(&memory->active) == 0) { return 0; } - + ucontext_t *state = context; - if((state->uc_mcontext.gregs[REG_TRAPNO] != X64_Exception_PF) || + if((state->uc_mcontext.gregs[REG_TRAPNO] != X64_ExceptionCode_PF) || (state->uc_mcontext.gregs[REG_ERR] & X64_PageFaultError_Write) || (state->uc_mcontext.gregs[REG_ERR] & X64_PageFaultError_InstructionFetch) || memory->owner_pid != getpid()) { return 0; } - + int saved_errno = errno; LNX_MemoryFaultRequest request = { .address = info->si_addr }; LNX_MemoryFaultRequest *ptr = &request; @@ -1176,7 +1176,7 @@ lnx_dispatch_memory_read_fault(int sig, siginfo_t *info, void *context) errno = saved_errno; return 0; } - + // wait for the page fault handler to complete while(!ins_atomic_u32_eval(&request.result)) { @@ -1185,10 +1185,10 @@ lnx_dispatch_memory_read_fault(int sig, siginfo_t *info, void *context) _exit(1); } } - + B32 handled = request.result == 2; errno = saved_errno; - + return handled; #else NotImplemented; @@ -1210,7 +1210,7 @@ memory_read_fault_handler_set(MemoryReadFaultFunction *func, void *user_data) { return 0; } - + memory->fault = func; memory->user_data = user_data; memory->owner_pid = getpid(); @@ -1229,7 +1229,7 @@ memory_read_fault_handler_set(MemoryReadFaultFunction *func, void *user_data) } memory->workers[memory->worker_count++] = worker; } - + ins_atomic_u32_eval_assign(&memory->active, 1); } else if(memory->worker_count) @@ -1238,7 +1238,7 @@ memory_read_fault_handler_set(MemoryReadFaultFunction *func, void *user_data) { return 0; } - + ins_atomic_u32_eval_assign(&memory->active, 0); return lnx_memory_fault_workers_stop(memory); } @@ -1605,7 +1605,7 @@ process_launch(ProcessLaunchParams *params) posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP); posix_spawnattr_setpgroup(&attr, 0); } - + // package argv char **argv = push_array(scratch.arena, char *, params->cmd_line.node_count + 1); { @@ -1822,7 +1822,7 @@ lnx_signal_handler(int sig, siginfo_t *info, void *arg) { // page fault handler if(lnx_dispatch_memory_read_fault(sig, info, arg)) { return; } - + // crash handler { local_persist volatile U32 first = 0; @@ -1833,10 +1833,10 @@ lnx_signal_handler(int sig, siginfo_t *info, void *arg) sleep(UINT32_MAX); } } - + local_persist void *ips[4096]; int ips_count = backtrace(ips, ArrayCount(ips)); - + fprintf(stderr, "A fatal signal was received: %s (%d). The process is terminating.\n", strsignal(sig), sig); fprintf(stderr, "Create a new issue with this report at %s.\n\n", BUILD_ISSUES_LINK_STRING_LITERAL); fprintf(stderr, "Callstack:\n"); @@ -1844,7 +1844,7 @@ lnx_signal_handler(int sig, siginfo_t *info, void *arg) { Dl_info info = {0}; dladdr(ips[i], &info); - + char cmd[2048]; snprintf(cmd, sizeof(cmd), "llvm-symbolizer --relative-address -f -e %s %lu", info.dli_fname, (unsigned long)ips[i] - (unsigned long)info.dli_fbase); FILE *f = popen(cmd, "r"); @@ -1858,12 +1858,12 @@ lnx_signal_handler(int sig, siginfo_t *info, void *arg) String8 module = str8_skip_last_slash(str8_cstring(info.dli_fname)); String8 file = str8_skip_last_slash(str8_cstring_capped(file_name, file_name + sizeof(file_name))); if(file.size > 0) file.size -= 1; - + B32 no_func = str8_match(func, str8_lit("??"), StringMatchFlag_RightSideSloppy); B32 no_file = str8_match(file, str8_lit("??"), StringMatchFlag_RightSideSloppy); if(no_func) { func = str8_zero(); } if(no_file) { file = str8_zero(); } - + fprintf(stderr, "%ld. [0x%016lx] %.*s%s%.*s %.*s\n", i+1, (unsigned long)ips[i], (int)module.size, module.str, (!no_func || !no_file) ? ", " : "", (int)func.size, func.str, (int)file.size, file.str); } pclose(f); @@ -1874,7 +1874,7 @@ lnx_signal_handler(int sig, siginfo_t *info, void *arg) } } fprintf(stderr, "\nVersion: %s%s\n\n", BUILD_VERSION_STRING_LITERAL, BUILD_GIT_HASH_STRING_LITERAL_APPEND); - + _exit(1); } } @@ -1902,7 +1902,7 @@ main(int argc, char **argv) U64 pages = (U64)sysconf(_SC_PHYS_PAGES); U64 page_size = (U64)sysconf(_SC_PAGESIZE); U64 commit_size = (U64)sysconf(_SC_AVPHYS_PAGES); - + SystemInfo *info = &lnx_state.system_info; info->logical_processor_count = (U32)get_nprocs(); info->page_size = (U64)getpagesize(); diff --git a/src/linux/base/linux_base.h b/src/linux/base/linux_base.h index 87998e59..b5cce089 100644 --- a/src/linux/base/linux_base.h +++ b/src/linux/base/linux_base.h @@ -35,6 +35,13 @@ #include #include +// NOTE(rjf): this is required because we need to use architecture-specific code for "base" +// OS functionality - we may want to reevaluate if such things should be in base - but for +// now just pulling in the whole x64 layer, just for linux. +#if ARCH_X64 || ARCH_X86 +# include "x64/x64.h" +#endif + pid_t gettid(void); int pthread_setname_np(pthread_t thread, const char *name); int pthread_getname_np(pthread_t thread, char *name, size_t size); @@ -46,13 +53,13 @@ typedef struct timespec timespec; //~ rjf: Linux Call Interruption Retry Helper #define LNX_RETRY_ON_EINTR(expr) \ - (__extension__({ \ - __typeof__(expr) __ret; \ - do { \ - __ret = (expr); \ - } while ((__ret == -1) && errno == EINTR); \ - __ret; \ - })) +(__extension__({ \ +__typeof__(expr) __ret; \ +do { \ +__ret = (expr); \ +} while ((__ret == -1) && errno == EINTR); \ +__ret; \ +})) //////////////////////////////// diff --git a/src/x64/x64.h b/src/x64/x64.h index 7d9c1fd1..2ee37845 100644 --- a/src/x64/x64.h +++ b/src/x64/x64.h @@ -212,39 +212,40 @@ X64_DebugControlFlags; //////////////////////////////// //~ Exception Codes -typedef enum +typedef enum X64_ExceptionCode { - X64_Exception_DE = 0, // Divide error: division by zero or quotient overflow - X64_Exception_DB = 1, // Debug exception (single stepping, hardware breakpoint) - X64_Exception_NMI = 2, // Non-maskable interrupt - X64_Exception_BP = 3, // Breakpoint (int3) - X64_Exception_OF = 4, // Overflow - X64_Exception_BR = 5, // Bound range exceeded - X64_Exception_UD = 6, // Invalid opcode - X64_Exception_NM = 7, // Device not available - X64_Exception_DF = 8, // Double fault - X64_Exception_9 = 9, // Coprocessor segment overrun (obsolete) - X64_Exception_TS = 10, // Invalid task-state segment - X64_Exception_NP = 11, // Segment not present - X64_Exception_SS = 12, // Stack-segment fault - X64_Exception_GP = 13, // General-protection fault - X64_Exception_PF = 14, // Page fault - X64_Exception_15 = 15, // Reserved; Linux names it X86_TRAP_SPURIOUS - X64_Exception_MF = 16, // x87 floating-point exception - X64_Exception_AC = 17, // Alignment check - X64_Exception_MC = 18, // Machine check - X64_Exception_XF = 19, // SIMD floating-point exception - X64_Exception_VE = 20, // Virtualization exception - X64_Exception_CP = 21, // Control-protection exception - X64_Exception_Amd_HV = 28, // Hypervisor injection exception - X64_Exception_Amd_VC = 29, // VMM communication exception - X64_Exception_Amd_SX = 30, // Security exception -} X64_ExceptionCode; + X64_ExceptionCode_DE = 0, // Divide error: division by zero or quotient overflow + X64_ExceptionCode_DB = 1, // Debug exception (single stepping, hardware breakpoint) + X64_ExceptionCode_NMI = 2, // Non-maskable interrupt + X64_ExceptionCode_BP = 3, // Breakpoint (int3) + X64_ExceptionCode_OF = 4, // Overflow + X64_ExceptionCode_BR = 5, // Bound range exceeded + X64_ExceptionCode_UD = 6, // Invalid opcode + X64_ExceptionCode_NM = 7, // Device not available + X64_ExceptionCode_DF = 8, // Double fault + X64_ExceptionCode_9 = 9, // Coprocessor segment overrun (obsolete) + X64_ExceptionCode_TS = 10, // Invalid task-state segment + X64_ExceptionCode_NP = 11, // Segment not present + X64_ExceptionCode_SS = 12, // Stack-segment fault + X64_ExceptionCode_GP = 13, // General-protection fault + X64_ExceptionCode_PF = 14, // Page fault + X64_ExceptionCode_15 = 15, // Reserved; Linux names it X86_TRAP_SPURIOUS + X64_ExceptionCode_MF = 16, // x87 floating-point exception + X64_ExceptionCode_AC = 17, // Alignment check + X64_ExceptionCode_MC = 18, // Machine check + X64_ExceptionCode_XF = 19, // SIMD floating-point exception + X64_ExceptionCode_VE = 20, // Virtualization exception + X64_ExceptionCode_CP = 21, // Control-protection exception + X64_ExceptionCode_Amd_HV = 28, // Hypervisor injection exception + X64_ExceptionCode_Amd_VC = 29, // VMM communication exception + X64_ExceptionCode_Amd_SX = 30, // Security exception +} +X64_ExceptionCode; //////////////////////////////// //~ Page Fault Flags -typedef enum +typedef enum X64_PageFaultError { X64_PageFaultError_Protection = (1u << 0), X64_PageFaultError_Write = (1u << 1), @@ -253,7 +254,8 @@ typedef enum X64_PageFaultError_InstructionFetch = (1u << 4), X64_PageFaultError_ProtectionKey = (1u << 5), X64_PageFaultError_ShadowStack = (1u << 6), -} X64_PageFaultError; +} +X64_PageFaultError; //////////////////////////////// //~ rjf: Generated @@ -280,4 +282,4 @@ internal X64_XSaveLayout x64_get_xsave_layout(U64 xcr0); internal void x64_set_debug_break(U64 *drs, U64 trap_idx, U64 addr, U64 size, X64_BreakpointType bp_type, X64_DebugBreakType break_type); -#endif // BASE_X64_H +#endif // X64_H