mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
re-slice linux/win32 backends, top-level folder is backend (demon/win32 -> win32/demon, etc.); os_gfx -> window_manager; fix linux / opengl builds for new apis/types
This commit is contained in:
+2
-2
@@ -49,13 +49,13 @@ commands =
|
||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg debug telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f1 = { .win = "build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
//- rjf: [raddbg wsl]
|
||||
// .f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
//- rjf: [scratch]
|
||||
.f2 = { .win = "build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f2 = { .win = "wsl ./build.sh radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
//- rjf: [textperf]
|
||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build no_meta telemetry textperf && raddbg_stable --ipc bring_to_front && raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
+2
-1
@@ -28,7 +28,8 @@ struct ARCH_Info
|
||||
global read_only Rng1U16 arch_reg_code_rng_nil = {0};
|
||||
global read_only String8 arch_reg_code_name_nil = {0};
|
||||
global read_only U8 arch_reg_code_u8_nil = 0;
|
||||
global read_only ARCH_Info arch_info_nil = {0, 0, 0, 0, &arch_reg_code_rng_nil, &arch_reg_code_name_nil, &arch_reg_code_u8_nil, &arch_reg_code_u8_nil};
|
||||
global read_only B8 arch_reg_code_b8_nil = 0;
|
||||
global read_only ARCH_Info arch_info_nil = {0, 0, 0, 0, &arch_reg_code_rng_nil, &arch_reg_code_name_nil, &arch_reg_code_u8_nil, &arch_reg_code_b8_nil};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Abstracted Architecture Functions
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
#include "demon/demon_core.c"
|
||||
|
||||
#if OS_WINDOWS
|
||||
# include "demon/win32/demon_core_win32.c"
|
||||
# include "win32/demon/win32_demon.c"
|
||||
#elif OS_LINUX
|
||||
# include "demon/linux/demon_core_linux.c"
|
||||
# include "linux/demon/linux_demon.c"
|
||||
#else
|
||||
# error Demon layer backend not defined for this operating system.
|
||||
#endif
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
#include "demon/demon_core.h"
|
||||
|
||||
#if OS_WINDOWS
|
||||
# include "demon/win32/demon_core_win32.h"
|
||||
# include "win32/demon/win32_demon.h"
|
||||
#elif OS_LINUX
|
||||
# include "demon/linux/demon_core_linux.h"
|
||||
# include "linux/demon/linux_demon.h"
|
||||
#else
|
||||
# error Demon layer backend not defined for this operating system.
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,222 +0,0 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef DEMON_OS_LINUX_H
|
||||
#define DEMON_OS_LINUX_H
|
||||
|
||||
// TODO(allen): Potential Upgrades:
|
||||
//
|
||||
// memory fd upgrade - Right now for each process we hold open a file
|
||||
// descriptor for the process's memory (/proc/%d/mem) for the entire lifetime
|
||||
// of the process; it could be opened and closed with some kind of LRU cache
|
||||
// to put a finite cap on the number of handles the demon holds
|
||||
//
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Get The Linux Includes
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <elf.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Linux Demon Types
|
||||
|
||||
//- entities
|
||||
|
||||
// Demon Linux Entity Extensions
|
||||
// Process: ext_u64 set to memory file descriptor
|
||||
// Thread : ext_u64 cast to DEMON_LNX_ThreadExt
|
||||
// Module : ext_u64 set to U64 (address of name)
|
||||
|
||||
struct DEMON_LNX_ThreadExt{
|
||||
B32 expecting_dummy_sigstop;
|
||||
};
|
||||
StaticAssert(sizeof(DEMON_LNX_ThreadExt) <= sizeof(Member(DEMON_Entity, ext_u64)), check_demon_lnx_thread_ext);
|
||||
|
||||
//- helpers
|
||||
|
||||
struct DEMON_LNX_AttachNode{
|
||||
DEMON_LNX_AttachNode *next;
|
||||
pid_t pid;
|
||||
};
|
||||
|
||||
struct DEMON_LNX_ProcessAux{
|
||||
B32 filled;
|
||||
U64 phnum;
|
||||
U64 phent;
|
||||
U64 phdr;
|
||||
U64 execfn;
|
||||
};
|
||||
|
||||
struct DEMON_LNX_PhdrInfo{
|
||||
Rng1U64 range;
|
||||
U64 dynamic;
|
||||
};
|
||||
|
||||
struct DEMON_LNX_ModuleNode{
|
||||
DEMON_LNX_ModuleNode *next;
|
||||
U64 vaddr;
|
||||
U64 size;
|
||||
U64 name;
|
||||
U64 already_known;
|
||||
};
|
||||
|
||||
struct DEMON_LNX_EntityNode{
|
||||
DEMON_LNX_EntityNode *next;
|
||||
DEMON_Entity *entity;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Linux Demon Register Layouts
|
||||
|
||||
// these are defined in <sys/user.h> but only for one architecture at a time
|
||||
// (and we can't really trick it into giving us both in any obvious way)
|
||||
// we define them here so that we have them all "at once"
|
||||
|
||||
struct DEMON_LNX_UserRegsX64{
|
||||
U64 r15;
|
||||
U64 r14;
|
||||
U64 r13;
|
||||
U64 r12;
|
||||
U64 rbp;
|
||||
U64 rbx;
|
||||
U64 r11;
|
||||
U64 r10;
|
||||
U64 r9;
|
||||
U64 r8;
|
||||
U64 rax;
|
||||
U64 rcx;
|
||||
U64 rdx;
|
||||
U64 rsi;
|
||||
U64 rdi;
|
||||
U64 orig_rax;
|
||||
U64 rip;
|
||||
U64 cs;
|
||||
U64 rflags;
|
||||
U64 rsp;
|
||||
U64 ss;
|
||||
U64 fsbase;
|
||||
U64 gsbase;
|
||||
U64 ds;
|
||||
U64 es;
|
||||
U64 fs;
|
||||
U64 gs;
|
||||
};
|
||||
|
||||
struct DEMON_LNX_UserX64{
|
||||
DEMON_LNX_UserRegsX64 regs;
|
||||
S32 u_fpvalid, _pad0;
|
||||
SYMS_XSaveLegacy i387;
|
||||
U64 u_tsize, u_dsize, u_ssize, start_code, start_stack;
|
||||
U64 signal;
|
||||
S32 reserved, _pad1;
|
||||
U64 u_ar0, u_fpstate;
|
||||
U64 magic;
|
||||
U8 u_comm[32];
|
||||
U64 u_debugreg[8];
|
||||
};
|
||||
|
||||
struct DEMON_LNX_UserRegsX86{
|
||||
U32 ebx;
|
||||
U32 ecx;
|
||||
U32 edx;
|
||||
U32 esi;
|
||||
U32 edi;
|
||||
U32 ebp;
|
||||
U32 eax;
|
||||
U32 ds;
|
||||
U32 es;
|
||||
U32 fs;
|
||||
U32 gs;
|
||||
U32 orig_eax;
|
||||
U32 eip;
|
||||
U32 cs;
|
||||
U32 eflags;
|
||||
U32 sp;
|
||||
U32 ss;
|
||||
};
|
||||
|
||||
struct DEMON_LNX_UserX86{
|
||||
DEMON_LNX_UserRegsX86 regs;
|
||||
S32 u_fpvalid;
|
||||
SYMS_FSave i387;
|
||||
U32 u_tsize, u_dsize, u_ssize, start_code, start_stack;
|
||||
S32 signal, reserved;
|
||||
U32 u_ar0, u_fpstate;
|
||||
U32 magic;
|
||||
U8 u_comm[32];
|
||||
U32 u_debugreg[8];
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
enum
|
||||
{
|
||||
DEMON_LNX_PermFlags_Read = (1 << 0),
|
||||
DEMON_LNX_PermFlags_Write = (1 << 1),
|
||||
DEMON_LNX_PermFlags_Exec = (1 << 2),
|
||||
DEMON_LNX_PermFlags_Private = (1 << 3)
|
||||
};
|
||||
typedef int DEMON_LNX_PermFlags;
|
||||
|
||||
enum
|
||||
{
|
||||
DEMON_LNX_MapsEntryType_Null,
|
||||
DEMON_LNX_MapsEntryType_Path,
|
||||
DEMON_LNX_MapsEntryType_Heap,
|
||||
DEMON_LNX_MapsEntryType_Stack,
|
||||
DEMON_LNX_MapsEntryType_VDSO,
|
||||
};
|
||||
typedef int DEMON_LNX_MapsEntryType;
|
||||
|
||||
struct DEMON_LNX_MapsEntry
|
||||
{
|
||||
U64 address_lo;
|
||||
U64 address_hi;
|
||||
DEMON_LNX_PermFlags perms;
|
||||
U64 offset;
|
||||
U32 dev_major;
|
||||
U32 dev_minor;
|
||||
U64 inode;
|
||||
String8 pathname;
|
||||
DEMON_LNX_MapsEntryType type;
|
||||
pid_t stack_tid;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Helpers
|
||||
|
||||
internal DEMON_LNX_ThreadExt* demon_lnx_thread_ext(DEMON_Entity *entity);
|
||||
|
||||
internal B32 demon_lnx_attach_pid(Arena *arena, pid_t pid, DEMON_LNX_AttachNode **new_node);
|
||||
|
||||
internal String8 demon_lnx_executable_path_from_pid(Arena *arena, pid_t pid);
|
||||
internal int demon_lnx_open_memory_fd_for_pid(pid_t pid);
|
||||
|
||||
internal Arch demon_lnx_arch_from_pid(pid_t pid);
|
||||
internal DEMON_LNX_ProcessAux demon_lnx_aux_from_pid(pid_t pid, Arch arch);
|
||||
internal DEMON_LNX_PhdrInfo demon_lnx_phdr_info_from_memory(int memory_fd, B32 is_32bit,
|
||||
U64 phvaddr, U64 phstride, U64 phcount);
|
||||
internal DEMON_LNX_ModuleNode* demon_lnx_module_list_from_process(Arena *arena, DEMON_Entity *process);
|
||||
|
||||
internal U64 demon_lnx_read_memory(int memory_fd, void *dst, U64 src, U64 size);
|
||||
internal B32 demon_lnx_write_memory(int memory_fd, U64 dst, void *src, U64 size);
|
||||
internal String8 demon_lnx_read_memory_str(Arena *arena, int memory_fd, U64 address);
|
||||
|
||||
internal void demon_lnx_regs_x64_from_usr_regs_x64(SYMS_RegX64 *dst, DEMON_LNX_UserRegsX64 *src);
|
||||
internal void demon_lnx_usr_regs_x64_from_regs_x64(DEMON_LNX_UserRegsX64 *dst, SYMS_RegX64 *src);
|
||||
|
||||
internal String8 demon_lnx_read_int_string(int fd);
|
||||
internal B32 demon_lnx_read_expect(int fd, char expect);
|
||||
internal int demon_lnx_read_whitespace(int fd);
|
||||
internal String8 demon_lnx_read_string(Arena *arena, int fd);
|
||||
|
||||
internal int demon_lnx_open_maps(pid_t pid);
|
||||
internal B32 demon_lnx_next_map(Arena *arena, int maps, DEMON_LNX_MapsEntry *entry_out);
|
||||
|
||||
#endif //DEMON_OS_LINUX_H
|
||||
@@ -17,7 +17,6 @@
|
||||
// --- Code Base ---------------------------------------------------------------
|
||||
|
||||
#include "base/base_inc.h"
|
||||
#include "os/os_inc.h"
|
||||
#include "hash_table.h"
|
||||
#include "coff/coff.h"
|
||||
#include "coff/coff_parse.h"
|
||||
@@ -37,7 +36,6 @@
|
||||
#include "llvm/llvm.h"
|
||||
|
||||
#include "base/base_inc.c"
|
||||
#include "os/os_inc.c"
|
||||
#include "hash_table.c"
|
||||
#include "coff/coff.c"
|
||||
#include "coff/coff_parse.c"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,4 +4,154 @@
|
||||
#ifndef LINUX_BASE_H
|
||||
#define LINUX_BASE_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Includes
|
||||
|
||||
#include <dirent.h>
|
||||
#include <dlfcn.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <execinfo.h>
|
||||
#include <fcntl.h>
|
||||
#include <features.h>
|
||||
#include <linux/limits.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <signal.h>
|
||||
#include <spawn.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/random.h>
|
||||
#include <sys/sendfile.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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);
|
||||
|
||||
typedef struct tm tm;
|
||||
typedef struct timespec timespec;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Linux Call Interruption Retry Helper
|
||||
|
||||
#define OS_LNX_RETRY_ON_EINTR(expr) \
|
||||
(__extension__({ \
|
||||
__typeof__(expr) __ret; \
|
||||
do { \
|
||||
__ret = (expr); \
|
||||
} while ((__ret == -1) && errno == EINTR); \
|
||||
__ret; \
|
||||
}))
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: File Iterator
|
||||
|
||||
typedef struct OS_LNX_FileIter OS_LNX_FileIter;
|
||||
struct OS_LNX_FileIter
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *dp;
|
||||
String8 path;
|
||||
};
|
||||
StaticAssert(sizeof(Member(FileIter, memory)) >= sizeof(OS_LNX_FileIter), os_lnx_file_iter_size_check);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Safe Call Handler Chain
|
||||
|
||||
typedef struct OS_LNX_SafeCallChain OS_LNX_SafeCallChain;
|
||||
struct OS_LNX_SafeCallChain
|
||||
{
|
||||
OS_LNX_SafeCallChain *next;
|
||||
ThreadEntryPointFunctionType *fail_handler;
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entities
|
||||
|
||||
typedef enum OS_LNX_EntityKind
|
||||
{
|
||||
OS_LNX_EntityKind_Thread,
|
||||
OS_LNX_EntityKind_Mutex,
|
||||
OS_LNX_EntityKind_RWMutex,
|
||||
OS_LNX_EntityKind_ConditionVariable,
|
||||
OS_LNX_EntityKind_Barrier,
|
||||
}
|
||||
OS_LNX_EntityKind;
|
||||
|
||||
typedef struct OS_LNX_Entity OS_LNX_Entity;
|
||||
struct OS_LNX_Entity
|
||||
{
|
||||
OS_LNX_Entity *next;
|
||||
OS_LNX_EntityKind kind;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
pthread_t handle;
|
||||
ThreadEntryPointFunctionType *func;
|
||||
void *ptr;
|
||||
} thread;
|
||||
pthread_mutex_t mutex_handle;
|
||||
pthread_rwlock_t rwmutex_handle;
|
||||
struct
|
||||
{
|
||||
pthread_cond_t cond_handle;
|
||||
pthread_mutex_t rwlock_mutex_handle;
|
||||
} cv;
|
||||
pthread_barrier_t barrier;
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: State
|
||||
|
||||
typedef struct OS_LNX_State OS_LNX_State;
|
||||
struct OS_LNX_State
|
||||
{
|
||||
Arena *arena;
|
||||
SystemInfo system_info;
|
||||
ProcessInfo process_info;
|
||||
pthread_mutex_t entity_mutex;
|
||||
Arena *entity_arena;
|
||||
OS_LNX_Entity *entity_free;
|
||||
U64 default_env_count;
|
||||
char **default_env;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global OS_LNX_State os_lnx_state = {0};
|
||||
thread_static OS_LNX_SafeCallChain *os_lnx_safe_call_chain = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Helpers
|
||||
|
||||
internal DateTime os_lnx_date_time_from_tm(tm in, U32 msec);
|
||||
internal tm os_lnx_tm_from_date_time(DateTime dt);
|
||||
internal timespec os_lnx_timespec_from_date_time(DateTime dt);
|
||||
internal DenseTime os_lnx_dense_time_from_timespec(timespec in);
|
||||
internal FileProperties os_lnx_file_properties_from_stat(struct stat *s);
|
||||
internal void os_lnx_safe_call_sig_handler(int x);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entities
|
||||
|
||||
internal OS_LNX_Entity *os_lnx_entity_alloc(OS_LNX_EntityKind kind);
|
||||
internal void os_lnx_entity_release(OS_LNX_Entity *entity);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Thread Entry Point
|
||||
|
||||
internal void *os_lnx_thread_entry_point(void *ptr);
|
||||
|
||||
#endif // LINUX_BASE_H
|
||||
|
||||
@@ -1163,197 +1163,190 @@ dmn_lnx_thread_write_sp(DMN_LNX_Thread *thread, U64 sp)
|
||||
internal B32
|
||||
dmn_lnx_thread_read_reg_block(DMN_LNX_Thread *thread)
|
||||
{
|
||||
AssertAlways(thread->state == DMN_LNX_ThreadState_Stopped);
|
||||
|
||||
B32 is_reg_block_read = 0;
|
||||
|
||||
switch(thread->process->ctx->arch)
|
||||
if(thread->state == DMN_LNX_ThreadState_Stopped)
|
||||
{
|
||||
case Arch_Null: {} break;
|
||||
case Arch_x64:
|
||||
switch(thread->process->ctx->arch)
|
||||
{
|
||||
DMN_LNX_ProcessCtx *process_ctx = thread->process->ctx;
|
||||
X64_RegBlock *dst = thread->reg_block;
|
||||
|
||||
// general purpose registers
|
||||
default:{}break;
|
||||
case Arch_x64:
|
||||
{
|
||||
OS_LNX_GprsX64 src;
|
||||
int ptrace_result = OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_GETREGSET, thread->tid, (void *)NT_PRSTATUS, &(struct iovec){ .iov_len = sizeof(src), .iov_base = &src }));
|
||||
if(ptrace_result < 0) { goto exit; }
|
||||
DMN_LNX_ProcessCtx *process_ctx = thread->process->ctx;
|
||||
X64_RegBlock *dst = thread->reg_block;
|
||||
|
||||
dst->r15.u64 = src.r15;
|
||||
dst->r14.u64 = src.r14;
|
||||
dst->r13.u64 = src.r13;
|
||||
dst->r12.u64 = src.r12;
|
||||
dst->rbp.u64 = src.rbp;
|
||||
dst->rbx.u64 = src.rbx;
|
||||
dst->r11.u64 = src.r11;
|
||||
dst->r10.u64 = src.r10;
|
||||
dst->r9.u64 = src.r9;
|
||||
dst->r8.u64 = src.r8;
|
||||
dst->rax.u64 = src.rax;
|
||||
dst->rcx.u64 = src.rcx;
|
||||
dst->rdx.u64 = src.rdx;
|
||||
dst->rsi.u64 = src.rsi;
|
||||
dst->rdi.u64 = src.rdi;
|
||||
dst->rip.u64 = src.rip;
|
||||
dst->cs.u16 = src.cs;
|
||||
dst->rflags.u64 = src.rflags;
|
||||
dst->rsp.u64 = src.rsp;
|
||||
dst->ss.u16 = src.ss;
|
||||
dst->fsbase.u64 = src.fsbase;
|
||||
dst->gsbase.u64 = src.gsbase;
|
||||
dst->ds.u16 = src.ds;
|
||||
dst->es.u16 = src.es;
|
||||
dst->fs.u16 = src.fs;
|
||||
dst->gs.u16 = src.gs;
|
||||
thread->orig_rax = src.orig_rax;
|
||||
}
|
||||
|
||||
// xsave
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
X64_XSave *xsave = 0;
|
||||
X64_FXSave *fxsave = 0;
|
||||
|
||||
// get xsave
|
||||
if(x64_is_xsave_supported())
|
||||
// general purpose registers
|
||||
{
|
||||
void *xsave_raw = push_array(scratch.arena, U8, process_ctx->xsave_size);
|
||||
int ptrace_result = OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_GETREGSET, thread->tid, (void *)NT_X86_XSTATE, &(struct iovec){ .iov_len = process_ctx->xsave_size, .iov_base = xsave_raw }));
|
||||
if(ptrace_result < 0) { goto exit; }
|
||||
OS_LNX_GprsX64 src;
|
||||
int ptrace_result = OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_GETREGSET, thread->tid, (void *)NT_PRSTATUS, &(struct iovec){ .iov_len = sizeof(src), .iov_base = &src }));
|
||||
if(ptrace_result < 0) { goto exit; }
|
||||
|
||||
xsave = xsave_raw;
|
||||
fxsave = &xsave->fxsave;
|
||||
dst->r15 = src.r15;
|
||||
dst->r14 = src.r14;
|
||||
dst->r13 = src.r13;
|
||||
dst->r12 = src.r12;
|
||||
dst->rbp = src.rbp;
|
||||
dst->rbx = src.rbx;
|
||||
dst->r11 = src.r11;
|
||||
dst->r10 = src.r10;
|
||||
dst->r9 = src.r9;
|
||||
dst->r8 = src.r8;
|
||||
dst->rax = src.rax;
|
||||
dst->rcx = src.rcx;
|
||||
dst->rdx = src.rdx;
|
||||
dst->rsi = src.rsi;
|
||||
dst->rdi = src.rdi;
|
||||
dst->rip = src.rip;
|
||||
dst->cs = src.cs;
|
||||
dst->rflags = src.rflags;
|
||||
dst->rsp = src.rsp;
|
||||
dst->ss = src.ss;
|
||||
dst->fsbase = src.fsbase;
|
||||
dst->gsbase = src.gsbase;
|
||||
dst->ds = src.ds;
|
||||
dst->es = src.es;
|
||||
dst->fs = src.fs;
|
||||
dst->gs = src.gs;
|
||||
thread->orig_rax = src.orig_rax;
|
||||
}
|
||||
|
||||
// get fxsave
|
||||
if(fxsave == 0)
|
||||
// xsave
|
||||
{
|
||||
fxsave = push_array(scratch.arena, X64_FXSave, 1);
|
||||
int ptrace_result = OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_GETREGSET, thread->tid, (void *)NT_FPREGSET, &(struct iovec){ .iov_len = sizeof(*fxsave), .iov_base = fxsave }));
|
||||
if(ptrace_result < 0) { goto exit; }
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
fxsave = 0;
|
||||
}
|
||||
X64_XSave *xsave = 0;
|
||||
X64_FXSave *fxsave = 0;
|
||||
|
||||
// copy fxsave registers
|
||||
if(fxsave)
|
||||
{
|
||||
X64_FXSave *src = fxsave;
|
||||
|
||||
// copy x87 registers
|
||||
dst->fcw.u16 = src->fcw;
|
||||
dst->fsw.u16 = src->fsw;
|
||||
dst->ftw = src->ftw;
|
||||
dst->fop.u16 = src->fop;
|
||||
dst->fip.u64 = src->fip;
|
||||
dst->fdp.u64 = src->fdp;
|
||||
dst->mxcsr.u32 = src->mxcsr;
|
||||
dst->mxcsr_mask.u32 = src->mxcsr_mask;
|
||||
for EachIndex(i, 8)
|
||||
// get xsave
|
||||
if(x64_is_xsave_supported())
|
||||
{
|
||||
MemoryCopy(&dst->st0 + i, src->st_space + i, sizeof(REGS_Reg80));
|
||||
void *xsave_raw = push_array(scratch.arena, U8, process_ctx->xsave_size);
|
||||
int ptrace_result = OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_GETREGSET, thread->tid, (void *)NT_X86_XSTATE, &(struct iovec){ .iov_len = process_ctx->xsave_size, .iov_base = xsave_raw }));
|
||||
if(ptrace_result < 0) { goto exit; }
|
||||
xsave = xsave_raw;
|
||||
fxsave = &xsave->fxsave;
|
||||
}
|
||||
|
||||
// SSE registers are always available in x64
|
||||
// get fxsave
|
||||
if(fxsave == 0)
|
||||
{
|
||||
U128 *xmm_d = fxsave->xmm_space;
|
||||
REGS_Reg512 *zmm_s = &dst->zmm0;
|
||||
for EachIndex(i, 16)
|
||||
fxsave = push_array(scratch.arena, X64_FXSave, 1);
|
||||
int ptrace_result = OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_GETREGSET, thread->tid, (void *)NT_FPREGSET, &(struct iovec){ .iov_len = sizeof(*fxsave), .iov_base = fxsave }));
|
||||
if(ptrace_result < 0) { goto exit; }
|
||||
fxsave = 0;
|
||||
}
|
||||
|
||||
// copy fxsave registers
|
||||
if(fxsave)
|
||||
{
|
||||
X64_FXSave *src = fxsave;
|
||||
|
||||
// copy x87 registers
|
||||
dst->fcw = src->fcw;
|
||||
dst->fsw = src->fsw;
|
||||
dst->ftw = src->ftw;
|
||||
dst->fop = src->fop;
|
||||
dst->fip = src->fip;
|
||||
dst->fdp = src->fdp;
|
||||
dst->mxcsr = src->mxcsr;
|
||||
dst->mxcsr_mask = src->mxcsr_mask;
|
||||
for EachIndex(i, 8)
|
||||
{
|
||||
MemoryCopy(&zmm_s[i], &xmm_d[i], sizeof(*xmm_d));
|
||||
MemoryCopy(&dst->st0 + i, src->st_space + i, sizeof(U80));
|
||||
}
|
||||
|
||||
// SSE registers are always available in x64
|
||||
{
|
||||
U128 *xmm_d = fxsave->xmm_space;
|
||||
U512 *zmm_s = &dst->zmm0;
|
||||
for EachIndex(i, 16)
|
||||
{
|
||||
MemoryCopy(&zmm_s[i], &xmm_d[i], sizeof(*xmm_d));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// copy xsave registers
|
||||
//
|
||||
// compact register layout is not supported (xsave->header.xcomp_bv == 0)
|
||||
//
|
||||
if(xsave && xsave->header.xcomp_bv == 0)
|
||||
{
|
||||
if(xsave->header.xstate_bv & X64_XStateComponentFlag_AVX &&
|
||||
process_ctx->xsave_layout.avx_offset + 16*sizeof(U128) <= process_ctx->xsave_size)
|
||||
{
|
||||
U128 *avx_s = (U128 *)((U8 *)xsave + process_ctx->xsave_layout.avx_offset);
|
||||
U512 *zmm_d = &dst->zmm0;
|
||||
for EachIndex(n, 16)
|
||||
{
|
||||
MemoryCopy(&zmm_d[n].u8[16], &avx_s[n], sizeof(U128));
|
||||
}
|
||||
}
|
||||
|
||||
if(xsave->header.xstate_bv & X64_XStateComponentFlag_OPMASK &&
|
||||
process_ctx->xsave_layout.opmask_offset + sizeof(U64) * 8 <= process_ctx->xsave_size)
|
||||
{
|
||||
U64 *kmask_s = (U64 *)((U8 *)xsave + process_ctx->xsave_layout.opmask_offset);
|
||||
U64 *kmask_d = &dst->k0;
|
||||
for EachIndex(n, 8)
|
||||
{
|
||||
MemoryCopy(&kmask_d[n], &kmask_s[n], sizeof(U64));
|
||||
}
|
||||
}
|
||||
|
||||
if(xsave->header.xstate_bv & X64_XStateComponentFlag_ZMM_H &&
|
||||
process_ctx->xsave_layout.zmm_h_offset + sizeof(U256) * 16 <= process_ctx->xsave_size)
|
||||
{
|
||||
U256 *avx512h_s = (U256 *)((U8 *)xsave + process_ctx->xsave_layout.zmm_h_offset);
|
||||
U512 *zmmh_d = &dst->zmm0;
|
||||
for EachIndex(n, 16)
|
||||
{
|
||||
MemoryCopy(&zmmh_d[n].u8[32], &avx512h_s[n], sizeof(U256));
|
||||
}
|
||||
}
|
||||
|
||||
if(xsave->header.xstate_bv & X64_XStateComponentFlag_ZMM &&
|
||||
process_ctx->xsave_layout.zmm_offset + sizeof(U512) * 16 <= process_ctx->xsave_size)
|
||||
{
|
||||
U512 *avx512_s = (U512 *)((U8 *)xsave + process_ctx->xsave_layout.zmm_offset);
|
||||
U512 *zmm_d = &dst->zmm16;
|
||||
for EachIndex(n, 16)
|
||||
{
|
||||
MemoryCopy(&zmm_d[n], &avx512_s[n], sizeof(U512));
|
||||
}
|
||||
}
|
||||
|
||||
if(xsave->header.xstate_bv & X64_XStateComponentFlag_CETU &&
|
||||
process_ctx->xsave_layout.cet_u_offset + sizeof(U64)*2 <= process_ctx->xsave_size)
|
||||
{
|
||||
U64 *cet_u = (U64 *)((U8 *)xsave + process_ctx->xsave_layout.cet_u_offset);
|
||||
dst->cetmsr = cet_u[0];
|
||||
dst->cetssp = cet_u[1];
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
// debug registers
|
||||
{
|
||||
U64 *dr_d = &dst->dr0;
|
||||
for EachIndex(n, 8)
|
||||
{
|
||||
if(n != 4 && n != 5)
|
||||
{
|
||||
U64 offset = OffsetOf(OS_LNX_UserX64, u_debugreg[n]);
|
||||
errno = 0;
|
||||
long peek_result = OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_PEEKUSER, thread->tid, PtrFromInt(offset), 0));
|
||||
if(errno != 0) { goto exit; }
|
||||
dr_d[n] = peek_result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// copy xsave registers
|
||||
if(xsave)
|
||||
{
|
||||
// compact register layout is not supported
|
||||
AssertAlways(xsave->header.xcomp_bv == 0);
|
||||
|
||||
if(xsave->header.xstate_bv & X64_XStateComponentFlag_AVX)
|
||||
{
|
||||
AssertAlways(process_ctx->xsave_layout.avx_offset + 16*sizeof(REGS_Reg128) <= process_ctx->xsave_size);
|
||||
REGS_Reg128 *avx_s = (REGS_Reg128 *)((U8 *)xsave + process_ctx->xsave_layout.avx_offset);
|
||||
REGS_Reg512 *zmm_d = &dst->zmm0;
|
||||
for EachIndex(n, 16)
|
||||
{
|
||||
MemoryCopy(&zmm_d[n].v[16], &avx_s[n], sizeof(REGS_Reg128));
|
||||
}
|
||||
}
|
||||
|
||||
if(xsave->header.xstate_bv & X64_XStateComponentFlag_OPMASK)
|
||||
{
|
||||
AssertAlways(process_ctx->xsave_layout.opmask_offset + sizeof(REGS_Reg64) * 8 <= process_ctx->xsave_size);
|
||||
REGS_Reg64 *kmask_s = (REGS_Reg64 *)((U8 *)xsave + process_ctx->xsave_layout.opmask_offset);
|
||||
REGS_Reg64 *kmask_d = &dst->k0;
|
||||
for EachIndex(n, 8)
|
||||
{
|
||||
MemoryCopy(&kmask_d[n], &kmask_s[n], sizeof(REGS_Reg64));
|
||||
}
|
||||
}
|
||||
|
||||
if(xsave->header.xstate_bv & X64_XStateComponentFlag_ZMM_H)
|
||||
{
|
||||
AssertAlways(process_ctx->xsave_layout.zmm_h_offset + sizeof(REGS_Reg256) * 16 <= process_ctx->xsave_size);
|
||||
REGS_Reg256 *avx512h_s = (REGS_Reg256 *)((U8 *)xsave + process_ctx->xsave_layout.zmm_h_offset);
|
||||
REGS_Reg512 *zmmh_d = &dst->zmm0;
|
||||
for EachIndex(n, 16)
|
||||
{
|
||||
MemoryCopy(&zmmh_d[n].v[32], &avx512h_s[n], sizeof(REGS_Reg256));
|
||||
}
|
||||
}
|
||||
|
||||
if(xsave->header.xstate_bv & X64_XStateComponentFlag_ZMM)
|
||||
{
|
||||
AssertAlways(process_ctx->xsave_layout.zmm_offset + sizeof(REGS_Reg512) * 16 <= process_ctx->xsave_size);
|
||||
REGS_Reg512 *avx512_s = (REGS_Reg512 *)((U8 *)xsave + process_ctx->xsave_layout.zmm_offset);
|
||||
REGS_Reg512 *zmm_d = &dst->zmm16;
|
||||
for EachIndex(n, 16)
|
||||
{
|
||||
MemoryCopy(&zmm_d[n], &avx512_s[n], sizeof(REGS_Reg512));
|
||||
}
|
||||
}
|
||||
|
||||
if(xsave->header.xstate_bv & X64_XStateComponentFlag_CETU)
|
||||
{
|
||||
AssertAlways(process_ctx->xsave_layout.cet_u_offset + sizeof(U64)*2 <= process_ctx->xsave_size);
|
||||
U64 *cet_u = (U64 *)((U8 *)xsave + process_ctx->xsave_layout.cet_u_offset);
|
||||
dst->cetmsr.u64 = cet_u[0];
|
||||
dst->cetssp.u64 = cet_u[1];
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
// debug registers
|
||||
{
|
||||
REGS_Reg64 *dr_d = &dst->dr0;
|
||||
for EachIndex(n, 8)
|
||||
{
|
||||
if(n != 4 && n != 5)
|
||||
{
|
||||
U64 offset = OffsetOf(OS_LNX_UserX64, u_debugreg[n]);
|
||||
errno = 0;
|
||||
long peek_result = OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_PEEKUSER, thread->tid, PtrFromInt(offset), 0));
|
||||
if(errno != 0) { goto exit; }
|
||||
dr_d[n].u64 = peek_result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is_reg_block_read = 1;
|
||||
} break;
|
||||
case Arch_x86:
|
||||
case Arch_arm64:
|
||||
case Arch_arm32: { NotImplemented; } break;
|
||||
default: { InvalidPath; } break;
|
||||
is_reg_block_read = 1;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
exit:;
|
||||
return is_reg_block_read;
|
||||
}
|
||||
@@ -1376,33 +1369,33 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread)
|
||||
// general purpose registers
|
||||
{
|
||||
OS_LNX_GprsX64 dst;
|
||||
dst.r15 = src->r15.u64;
|
||||
dst.r14 = src->r14.u64;
|
||||
dst.r13 = src->r13.u64;
|
||||
dst.r12 = src->r12.u64;
|
||||
dst.rbp = src->rbp.u64;
|
||||
dst.rbx = src->rbx.u64;
|
||||
dst.r11 = src->r11.u64;
|
||||
dst.r10 = src->r10.u64;
|
||||
dst.r9 = src->r9.u64;
|
||||
dst.r8 = src->r8.u64;
|
||||
dst.rax = src->rax.u64;
|
||||
dst.rcx = src->rcx.u64;
|
||||
dst.rdx = src->rdx.u64;
|
||||
dst.rsi = src->rsi.u64;
|
||||
dst.rdi = src->rdi.u64;
|
||||
dst.r15 = src->r15;
|
||||
dst.r14 = src->r14;
|
||||
dst.r13 = src->r13;
|
||||
dst.r12 = src->r12;
|
||||
dst.rbp = src->rbp;
|
||||
dst.rbx = src->rbx;
|
||||
dst.r11 = src->r11;
|
||||
dst.r10 = src->r10;
|
||||
dst.r9 = src->r9;
|
||||
dst.r8 = src->r8;
|
||||
dst.rax = src->rax;
|
||||
dst.rcx = src->rcx;
|
||||
dst.rdx = src->rdx;
|
||||
dst.rsi = src->rsi;
|
||||
dst.rdi = src->rdi;
|
||||
dst.orig_rax = thread->orig_rax;
|
||||
dst.rip = src->rip.u64;
|
||||
dst.cs = src->cs.u16;
|
||||
dst.rflags = src->rflags.u64;
|
||||
dst.rsp = src->rsp.u64;
|
||||
dst.ss = src->ss.u16;
|
||||
dst.fsbase = src->fsbase.u64;
|
||||
dst.gsbase = src->gsbase.u64;
|
||||
dst.ds = src->ds.u16;
|
||||
dst.es = src->es.u16;
|
||||
dst.fs = src->fs.u16;
|
||||
dst.gs = src->gs.u16;
|
||||
dst.rip = src->rip;
|
||||
dst.cs = src->cs;
|
||||
dst.rflags = src->rflags;
|
||||
dst.rsp = src->rsp;
|
||||
dst.ss = src->ss;
|
||||
dst.fsbase = src->fsbase;
|
||||
dst.gsbase = src->gsbase;
|
||||
dst.ds = src->ds;
|
||||
dst.es = src->es;
|
||||
dst.fs = src->fs;
|
||||
dst.gs = src->gs;
|
||||
int ptrace_result = OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_SETREGSET, thread->tid, (void *)NT_PRSTATUS, &(struct iovec){ .iov_base = &dst, .iov_len = sizeof(dst) }));
|
||||
if(ptrace_result < 0) { goto exit; }
|
||||
}
|
||||
@@ -1413,27 +1406,27 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread)
|
||||
|
||||
X64_FXSave dst_fxsave = {0};
|
||||
{
|
||||
dst_fxsave.fcw = src->fcw.u16;
|
||||
dst_fxsave.fsw = src->fsw.u16;
|
||||
dst_fxsave.fcw = src->fcw;
|
||||
dst_fxsave.fsw = src->fsw;
|
||||
dst_fxsave.ftw = src->ftw;
|
||||
dst_fxsave.fop = src->fop.u16;
|
||||
dst_fxsave.fip = src->fip.u64;
|
||||
dst_fxsave.fdp = src->fdp.u64;
|
||||
dst_fxsave.mxcsr = src->mxcsr.u32;
|
||||
dst_fxsave.mxcsr_mask = src->mxcsr_mask.u32;
|
||||
dst_fxsave.fop = src->fop;
|
||||
dst_fxsave.fip = src->fip;
|
||||
dst_fxsave.fdp = src->fdp;
|
||||
dst_fxsave.mxcsr = src->mxcsr;
|
||||
dst_fxsave.mxcsr_mask = src->mxcsr_mask;
|
||||
|
||||
REGS_Reg128 *st_d = (REGS_Reg128 *)dst_fxsave.st_space;
|
||||
REGS_Reg80 *st_s = &src->st0;
|
||||
U128 *st_d = (U128 *)dst_fxsave.st_space;
|
||||
U80 *st_s = &src->st0;
|
||||
for EachIndex(n, 8)
|
||||
{
|
||||
MemoryCopy(&st_d[n], &st_s[n], sizeof(REGS_Reg80));
|
||||
MemoryCopy(&st_d[n], &st_s[n], sizeof(U80));
|
||||
}
|
||||
|
||||
REGS_Reg128 *xmm_d = (REGS_Reg128 *)dst_fxsave.xmm_space;
|
||||
REGS_Reg512 *xmm_s = &src->zmm0;
|
||||
U128 *xmm_d = (U128 *)dst_fxsave.xmm_space;
|
||||
U512 *xmm_s = &src->zmm0;
|
||||
for EachIndex(n, 16)
|
||||
{
|
||||
MemoryCopy(&xmm_d[n], &xmm_s[n], sizeof(REGS_Reg128));
|
||||
MemoryCopy(&xmm_d[n], &xmm_s[n], sizeof(U128));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1447,13 +1440,13 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread)
|
||||
|
||||
if(process_ctx->xsave_layout.avx_offset)
|
||||
{
|
||||
if(process_ctx->xsave_layout.avx_offset + sizeof(REGS_Reg128) * 16 <= process_ctx->xsave_size)
|
||||
if(process_ctx->xsave_layout.avx_offset + sizeof(U128) * 16 <= process_ctx->xsave_size)
|
||||
{
|
||||
REGS_Reg128 *avx_d = (REGS_Reg128 *)(xsave_raw + process_ctx->xsave_layout.avx_offset);
|
||||
REGS_Reg512 *zmm_s = &src->zmm0;
|
||||
U128 *avx_d = (U128 *)(xsave_raw + process_ctx->xsave_layout.avx_offset);
|
||||
U512 *zmm_s = &src->zmm0;
|
||||
for EachIndex(n, 16)
|
||||
{
|
||||
MemoryCopy(&avx_d[n], &zmm_s[n].v[16], sizeof(REGS_Reg128));
|
||||
MemoryCopy(&avx_d[n], &zmm_s[n].u8[16], sizeof(U128));
|
||||
}
|
||||
dst->header.xstate_bv |= X64_XStateComponentFlag_AVX;
|
||||
}
|
||||
@@ -1461,13 +1454,13 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread)
|
||||
|
||||
if(process_ctx->xsave_layout.opmask_offset)
|
||||
{
|
||||
if(process_ctx->xsave_layout.opmask_offset + sizeof(REGS_Reg64) * 8 <= process_ctx->xsave_size)
|
||||
if(process_ctx->xsave_layout.opmask_offset + sizeof(U64) * 8 <= process_ctx->xsave_size)
|
||||
{
|
||||
REGS_Reg64 *kmask_d = (REGS_Reg64 *)(xsave_raw + process_ctx->xsave_layout.opmask_offset);
|
||||
REGS_Reg64 *kmask_s = &src->k0;
|
||||
U64 *kmask_d = (U64 *)(xsave_raw + process_ctx->xsave_layout.opmask_offset);
|
||||
U64 *kmask_s = &src->k0;
|
||||
for EachIndex(n, 8)
|
||||
{
|
||||
MemoryCopy(&kmask_d[n], &kmask_s[n], sizeof(REGS_Reg64));
|
||||
MemoryCopy(&kmask_d[n], &kmask_s[n], sizeof(U64));
|
||||
}
|
||||
dst->header.xstate_bv |= X64_XStateComponentFlag_OPMASK;
|
||||
}
|
||||
@@ -1476,13 +1469,13 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread)
|
||||
|
||||
if(process_ctx->xsave_layout.zmm_h_offset)
|
||||
{
|
||||
if(process_ctx->xsave_layout.zmm_h_offset + sizeof(REGS_Reg256) * 16 <= process_ctx->xsave_size)
|
||||
if(process_ctx->xsave_layout.zmm_h_offset + sizeof(U256) * 16 <= process_ctx->xsave_size)
|
||||
{
|
||||
REGS_Reg256 *avx512h_d = (REGS_Reg256 *)(xsave_raw + process_ctx->xsave_layout.zmm_h_offset);
|
||||
REGS_Reg512 *zmmh_s = &src->zmm0;
|
||||
U256 *avx512h_d = (U256 *)(xsave_raw + process_ctx->xsave_layout.zmm_h_offset);
|
||||
U512 *zmmh_s = &src->zmm0;
|
||||
for EachIndex(n, 16)
|
||||
{
|
||||
MemoryCopy(&avx512h_d[n], &zmmh_s[n].v[32], sizeof(REGS_Reg256));
|
||||
MemoryCopy(&avx512h_d[n], &zmmh_s[n].u8[32], sizeof(U256));
|
||||
}
|
||||
dst->header.xstate_bv |= X64_XStateComponentFlag_ZMM_H;
|
||||
}
|
||||
@@ -1491,13 +1484,13 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread)
|
||||
|
||||
if(process_ctx->xsave_layout.zmm_offset)
|
||||
{
|
||||
if(process_ctx->xsave_layout.zmm_offset + sizeof(REGS_Reg512) * 16 <= process_ctx->xsave_size)
|
||||
if(process_ctx->xsave_layout.zmm_offset + sizeof(U512) * 16 <= process_ctx->xsave_size)
|
||||
{
|
||||
REGS_Reg512 *avx512_d = (REGS_Reg512 *)(xsave_raw + process_ctx->xsave_layout.zmm_offset);
|
||||
REGS_Reg512 *zmm_s = &src->zmm16;
|
||||
U512 *avx512_d = (U512 *)(xsave_raw + process_ctx->xsave_layout.zmm_offset);
|
||||
U512 *zmm_s = &src->zmm16;
|
||||
for EachIndex(n, 16)
|
||||
{
|
||||
MemoryCopy(&avx512_d[n], &zmm_s[n], sizeof(REGS_Reg512));
|
||||
MemoryCopy(&avx512_d[n], &zmm_s[n], sizeof(U512));
|
||||
}
|
||||
dst->header.xstate_bv |= X64_XStateComponentFlag_ZMM;
|
||||
}
|
||||
@@ -1506,9 +1499,9 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread)
|
||||
|
||||
if(process_ctx->xsave_layout.cet_u_offset)
|
||||
{
|
||||
if(process_ctx->xsave_layout.cet_u_offset + sizeof(REGS_Reg64) * 2 <= process_ctx->xsave_size)
|
||||
if(process_ctx->xsave_layout.cet_u_offset + sizeof(U64) * 2 <= process_ctx->xsave_size)
|
||||
{
|
||||
REGS_Reg64 *cet_u = (REGS_Reg64 *)(xsave_raw + process_ctx->xsave_layout.cet_u_offset);
|
||||
U64 *cet_u = (U64 *)(xsave_raw + process_ctx->xsave_layout.cet_u_offset);
|
||||
cet_u[0] = src->cetmsr;
|
||||
cet_u[1] = src->cetssp;
|
||||
dst->header.xstate_bv |= X64_XStateComponentFlag_CETU;
|
||||
@@ -1527,15 +1520,15 @@ dmn_lnx_thread_write_reg_block(DMN_LNX_Thread *thread)
|
||||
|
||||
// debug registers
|
||||
{
|
||||
src->dr7.u64 |= (1 << 10);
|
||||
src->dr7 |= (1 << 10);
|
||||
|
||||
REGS_Reg64 *dr_s = &src->dr0;
|
||||
U64 *dr_s = &src->dr0;
|
||||
for EachIndex(n, 8)
|
||||
{
|
||||
if(n != 4 && n != 5)
|
||||
{
|
||||
U64 offset = OffsetOf(OS_LNX_UserX64, u_debugreg[n]);
|
||||
int ptrace_result = OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_POKEUSER, thread->tid, PtrFromInt(offset), (void*)(uintptr_t)dr_s[n].u64));
|
||||
int ptrace_result = OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_POKEUSER, thread->tid, PtrFromInt(offset), (void*)(uintptr_t)dr_s[n]));
|
||||
if(ptrace_result < 0) { goto exit; }
|
||||
}
|
||||
}
|
||||
@@ -1563,8 +1556,8 @@ dmn_lnx_set_single_step_flag(DMN_LNX_Thread *thread, B32 is_on)
|
||||
case Arch_x64:
|
||||
{
|
||||
X64_RegBlock *reg_block = thread->reg_block;
|
||||
if(is_on) { reg_block->rflags.u64 |= X64_RFlag_Trap; }
|
||||
else { reg_block->rflags.u64 &= ~X64_RFlag_Trap; }
|
||||
if(is_on) { reg_block->rflags |= X64_RFlag_Trap; }
|
||||
else { reg_block->rflags &= ~X64_RFlag_Trap; }
|
||||
thread->is_reg_block_dirty = 1;
|
||||
is_flag_set = 1;
|
||||
} break;
|
||||
@@ -2086,36 +2079,31 @@ dmn_lnx_event_data_breakpoint(Arena *arena, DMN_EventList *events, pid_t tid)
|
||||
U64 address = 0;
|
||||
switch(thread->process->ctx->arch)
|
||||
{
|
||||
case Arch_Null: {} break;
|
||||
default:{}break;
|
||||
case Arch_x64:
|
||||
{
|
||||
X64_RegBlock *regs_x64 = thread->reg_block;
|
||||
if(regs_x64->dr6.u64 & X64_DebugStatusFlag_B0)
|
||||
if(regs_x64->dr6 & X64_DebugStatusFlag_B0)
|
||||
{
|
||||
address = regs_x64->dr0.u64;
|
||||
address = regs_x64->dr0;
|
||||
}
|
||||
else if(regs_x64->dr6.u64 & X64_DebugStatusFlag_B1)
|
||||
else if(regs_x64->dr6 & X64_DebugStatusFlag_B1)
|
||||
{
|
||||
address = regs_x64->dr1.u64;
|
||||
address = regs_x64->dr1;
|
||||
}
|
||||
else if(regs_x64->dr6.u64 & X64_DebugStatusFlag_B2)
|
||||
else if(regs_x64->dr6 & X64_DebugStatusFlag_B2)
|
||||
{
|
||||
address = regs_x64->dr2.u64;
|
||||
address = regs_x64->dr2;
|
||||
}
|
||||
else if(regs_x64->dr6.u64 & X64_DebugStatusFlag_B3)
|
||||
else if(regs_x64->dr6 & X64_DebugStatusFlag_B3)
|
||||
{
|
||||
address = regs_x64->dr3.u64;
|
||||
address = regs_x64->dr3;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_valid = 0;
|
||||
}
|
||||
} break;
|
||||
case Arch_x86:
|
||||
case Arch_arm32:
|
||||
case Arch_arm64:
|
||||
{ NotImplemented; } break;
|
||||
default: { InvalidPath; } break;
|
||||
}break;
|
||||
}
|
||||
|
||||
if(is_valid)
|
||||
@@ -2275,7 +2263,7 @@ dmn_ctrl_exclusive_access_end(void)
|
||||
}
|
||||
|
||||
internal U32
|
||||
dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params)
|
||||
dmn_ctrl_launch(DMN_CtrlCtx *ctx, ProcessLaunchParams *params)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
@@ -2966,7 +2954,7 @@ dmn_process_memory_release(DMN_Handle process, U64 vaddr, U64 size)
|
||||
}
|
||||
|
||||
internal void
|
||||
dmn_process_memory_protect(DMN_Handle process, U64 vaddr, U64 size, OS_AccessFlags flags)
|
||||
dmn_process_memory_protect(DMN_Handle process, U64 vaddr, U64 size, AccessFlags flags)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -3030,7 +3018,7 @@ dmn_tls_root_vaddr_from_thread(DMN_Handle thread_handle)
|
||||
{
|
||||
X64_RegBlock *reg_block = thread->reg_block;
|
||||
U64 dtv_pointer = 0;
|
||||
if(dmn_lnx_read_struct(thread->process->fd, reg_block->fsbase.u64 + 8, &dtv_pointer))
|
||||
if(dmn_lnx_read_struct(thread->process->fd, reg_block->fsbase + 8, &dtv_pointer))
|
||||
{
|
||||
tls_root_vaddr = dtv_pointer;
|
||||
}
|
||||
@@ -4,6 +4,66 @@
|
||||
#ifndef DEMON_CORE_LINUX_H
|
||||
#define DEMON_CORE_LINUX_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Register Layouts
|
||||
//
|
||||
// These are defined in <sys/user.h>, but only for one architecture at a time
|
||||
|
||||
typedef struct OS_LNX_GprsX64 OS_LNX_GprsX64;
|
||||
struct OS_LNX_GprsX64
|
||||
{
|
||||
U64 r15;
|
||||
U64 r14;
|
||||
U64 r13;
|
||||
U64 r12;
|
||||
U64 rbp;
|
||||
U64 rbx;
|
||||
U64 r11;
|
||||
U64 r10;
|
||||
U64 r9;
|
||||
U64 r8;
|
||||
U64 rax;
|
||||
U64 rcx;
|
||||
U64 rdx;
|
||||
U64 rsi;
|
||||
U64 rdi;
|
||||
U64 orig_rax;
|
||||
U64 rip;
|
||||
U64 cs;
|
||||
U64 rflags;
|
||||
U64 rsp;
|
||||
U64 ss;
|
||||
U64 fsbase;
|
||||
U64 gsbase;
|
||||
U64 ds;
|
||||
U64 es;
|
||||
U64 fs;
|
||||
U64 gs;
|
||||
};
|
||||
|
||||
typedef struct OS_LNX_UserX64 OS_LNX_UserX64;
|
||||
struct OS_LNX_UserX64
|
||||
{
|
||||
OS_LNX_GprsX64 regs;
|
||||
S32 u_fpvalid;
|
||||
U32 _pad0;
|
||||
X64_FXSave i387;
|
||||
U64 u_tsize;
|
||||
U64 u_dsize;
|
||||
U64 u_ssize;
|
||||
U64 start_code;
|
||||
U64 start_stack;
|
||||
U64 signal;
|
||||
U32 reserved;
|
||||
U32 _pad1;
|
||||
U64 u_ar0;
|
||||
U64 u_fpstate;
|
||||
U64 magic;
|
||||
U8 u_comm[32];
|
||||
U64 u_debugreg[8];
|
||||
};
|
||||
StaticAssert(sizeof(OS_LNX_UserX64) == 912, g_os_lnx_user_x64_size_check);
|
||||
|
||||
////////////////////////////////
|
||||
//~ TLS
|
||||
|
||||
@@ -41,17 +101,17 @@ typedef struct DMN_LNX_ProbeList
|
||||
} DMN_LNX_ProbeList;
|
||||
|
||||
#define DMN_LNX_Probe_XList \
|
||||
X(InitStart, 2, "init_start") \
|
||||
X(InitComplete, 2, "init_complete") \
|
||||
X(RelocStart, 2, "reloc_start") \
|
||||
X(RelocComplete, 3, "reloc_complete") \
|
||||
X(MapStart, 2, "map_start") \
|
||||
X(MapComplete, 3, "map_complete") \
|
||||
X(UnmapStart, 2, "unmap_start") \
|
||||
X(UnmapComplete, 2, "unmap_complete") \
|
||||
X(LongJmp, 3, "longjmp") \
|
||||
X(LongJmpTarget, 3, "longjmp_target") \
|
||||
X(SetJmp, 3, "setjmp")
|
||||
X(InitStart, 2, "init_start") \
|
||||
X(InitComplete, 2, "init_complete") \
|
||||
X(RelocStart, 2, "reloc_start") \
|
||||
X(RelocComplete, 3, "reloc_complete") \
|
||||
X(MapStart, 2, "map_start") \
|
||||
X(MapComplete, 3, "map_complete") \
|
||||
X(UnmapStart, 2, "unmap_start") \
|
||||
X(UnmapComplete, 2, "unmap_complete") \
|
||||
X(LongJmp, 3, "longjmp") \
|
||||
X(LongJmpTarget, 3, "longjmp_target") \
|
||||
X(SetJmp, 3, "setjmp")
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -98,7 +98,7 @@ os_get_clipboard_text(Arena *arena)
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Windows (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle
|
||||
internal OS_Window
|
||||
os_window_open(Rng2F32 rect, OS_WindowFlags flags, String8 title)
|
||||
{
|
||||
Vec2F32 resolution = dim_2f32(rect);
|
||||
@@ -161,22 +161,22 @@ os_window_open(Rng2F32 rect, OS_WindowFlags flags, String8 title)
|
||||
scratch_end(scratch);
|
||||
|
||||
//- rjf: convert to handle & return
|
||||
OS_Handle handle = {(U64)w};
|
||||
OS_Window handle = {(U64)w};
|
||||
return handle;
|
||||
}
|
||||
|
||||
internal void
|
||||
os_window_close(OS_Handle handle)
|
||||
os_window_close(OS_Window handle)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return;}
|
||||
if(os_window_match(handle, os_window_zero())) {return;}
|
||||
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
||||
XDestroyWindow(os_lnx_gfx_state->display, w->window);
|
||||
}
|
||||
|
||||
internal void
|
||||
os_window_set_title(OS_Handle handle, String8 title)
|
||||
os_window_set_title(OS_Window handle, String8 title)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return;}
|
||||
if(os_window_match(handle, os_window_zero())) {return;}
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
||||
String8 title_copy = push_str8_copy(scratch.arena, title);
|
||||
@@ -185,25 +185,25 @@ os_window_set_title(OS_Handle handle, String8 title)
|
||||
}
|
||||
|
||||
internal void
|
||||
os_window_first_paint(OS_Handle handle)
|
||||
os_window_first_paint(OS_Window handle)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return;}
|
||||
if(os_window_match(handle, os_window_zero())) {return;}
|
||||
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
||||
XMapWindow(os_lnx_gfx_state->display, w->window);
|
||||
}
|
||||
|
||||
internal void
|
||||
os_window_focus(OS_Handle handle)
|
||||
os_window_focus(OS_Window handle)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return;}
|
||||
if(os_window_match(handle, os_window_zero())) {return;}
|
||||
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
||||
XSetInputFocus(os_lnx_gfx_state->display, w->window, RevertToNone, CurrentTime);
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_window_is_focused(OS_Handle handle)
|
||||
os_window_is_focused(OS_Window handle)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return 0;}
|
||||
if(os_window_match(handle, os_window_zero())) {return 0;}
|
||||
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
||||
Window focused_window = 0;
|
||||
int revert_to = 0;
|
||||
@@ -213,96 +213,96 @@ os_window_is_focused(OS_Handle handle)
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_window_is_fullscreen(OS_Handle handle)
|
||||
os_window_is_fullscreen(OS_Window handle)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return 0;}
|
||||
if(os_window_match(handle, os_window_zero())) {return 0;}
|
||||
// TODO(rjf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal void
|
||||
os_window_set_fullscreen(OS_Handle handle, B32 fullscreen)
|
||||
os_window_set_fullscreen(OS_Window handle, B32 fullscreen)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return;}
|
||||
if(os_window_match(handle, os_window_zero())) {return;}
|
||||
// TODO(rjf)
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_window_is_maximized(OS_Handle handle)
|
||||
os_window_is_maximized(OS_Window handle)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return 0;}
|
||||
if(os_window_match(handle, os_window_zero())) {return 0;}
|
||||
// TODO(rjf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal void
|
||||
os_window_set_maximized(OS_Handle handle, B32 maximized)
|
||||
os_window_set_maximized(OS_Window handle, B32 maximized)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return;}
|
||||
if(os_window_match(handle, os_window_zero())) {return;}
|
||||
// TODO(rjf)
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_window_is_minimized(OS_Handle handle)
|
||||
os_window_is_minimized(OS_Window handle)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return 0;}
|
||||
if(os_window_match(handle, os_window_zero())) {return 0;}
|
||||
// TODO(rjf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal void
|
||||
os_window_set_minimized(OS_Handle handle, B32 minimized)
|
||||
os_window_set_minimized(OS_Window handle, B32 minimized)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return;}
|
||||
if(os_window_match(handle, os_window_zero())) {return;}
|
||||
// TODO(rjf)
|
||||
}
|
||||
|
||||
internal void
|
||||
os_window_bring_to_front(OS_Handle handle)
|
||||
os_window_bring_to_front(OS_Window handle)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return;}
|
||||
if(os_window_match(handle, os_window_zero())) {return;}
|
||||
// TODO(rjf)
|
||||
}
|
||||
|
||||
internal void
|
||||
os_window_set_monitor(OS_Handle handle, OS_Handle monitor)
|
||||
os_window_set_monitor(OS_Window handle, OS_Monitor monitor)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return;}
|
||||
if(os_window_match(handle, os_window_zero())) {return;}
|
||||
// TODO(rjf)
|
||||
}
|
||||
|
||||
internal void
|
||||
os_window_clear_custom_border_data(OS_Handle handle)
|
||||
os_window_clear_custom_border_data(OS_Window handle)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return;}
|
||||
if(os_window_match(handle, os_window_zero())) {return;}
|
||||
// TODO(rjf)
|
||||
}
|
||||
|
||||
internal void
|
||||
os_window_push_custom_title_bar(OS_Handle handle, F32 thickness)
|
||||
os_window_push_custom_title_bar(OS_Window handle, F32 thickness)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return;}
|
||||
if(os_window_match(handle, os_window_zero())) {return;}
|
||||
// TODO(rjf)
|
||||
}
|
||||
|
||||
internal void
|
||||
os_window_push_custom_edges(OS_Handle handle, F32 thickness)
|
||||
os_window_push_custom_edges(OS_Window handle, F32 thickness)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return;}
|
||||
if(os_window_match(handle, os_window_zero())) {return;}
|
||||
// TODO(rjf)
|
||||
}
|
||||
|
||||
internal void
|
||||
os_window_push_custom_title_bar_client_area(OS_Handle handle, Rng2F32 rect)
|
||||
os_window_push_custom_title_bar_client_area(OS_Window handle, Rng2F32 rect)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return;}
|
||||
if(os_window_match(handle, os_window_zero())) {return;}
|
||||
// TODO(rjf)
|
||||
}
|
||||
|
||||
internal Rng2F32
|
||||
os_rect_from_window(OS_Handle handle)
|
||||
os_rect_from_window(OS_Window handle)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return r2f32p(0, 0, 0, 0);}
|
||||
if(os_window_match(handle, os_window_zero())) {return r2f32p(0, 0, 0, 0);}
|
||||
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
||||
XWindowAttributes atts = {0};
|
||||
Status s = XGetWindowAttributes(os_lnx_gfx_state->display, w->window, &atts);
|
||||
@@ -311,7 +311,7 @@ os_rect_from_window(OS_Handle handle)
|
||||
}
|
||||
|
||||
internal Rng2F32
|
||||
os_client_rect_from_window(OS_Handle handle)
|
||||
os_client_rect_from_window(OS_Window handle)
|
||||
{
|
||||
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
||||
XWindowAttributes atts = {0};
|
||||
@@ -321,7 +321,7 @@ os_client_rect_from_window(OS_Handle handle)
|
||||
}
|
||||
|
||||
internal F32
|
||||
os_dpi_from_window(OS_Handle handle)
|
||||
os_dpi_from_window(OS_Window handle)
|
||||
{
|
||||
// TODO(rjf)
|
||||
return 96.f;
|
||||
@@ -330,16 +330,16 @@ os_dpi_from_window(OS_Handle handle)
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks External Windows (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle
|
||||
internal OS_ExternalWindow
|
||||
os_focused_external_window(void)
|
||||
{
|
||||
OS_Handle result = {0};
|
||||
OS_ExternalWindow result = {0};
|
||||
// TODO(rjf)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
os_focus_external_window(OS_Handle handle)
|
||||
os_focus_external_window(OS_ExternalWindow handle)
|
||||
{
|
||||
// TODO(rjf)
|
||||
}
|
||||
@@ -347,46 +347,46 @@ os_focus_external_window(OS_Handle handle)
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Monitors (Implemented Per-OS)
|
||||
|
||||
internal OS_HandleArray
|
||||
internal OS_MonitorArray
|
||||
os_push_monitors_array(Arena *arena)
|
||||
{
|
||||
OS_HandleArray result = {0};
|
||||
OS_MonitorArray result = {0};
|
||||
// TODO(rjf)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal OS_Handle
|
||||
internal OS_Monitor
|
||||
os_primary_monitor(void)
|
||||
{
|
||||
OS_Handle result = {0};
|
||||
OS_Monitor result = {0};
|
||||
// TODO(rjf)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal OS_Handle
|
||||
os_monitor_from_window(OS_Handle window)
|
||||
internal OS_Monitor
|
||||
os_monitor_from_window(OS_Window window)
|
||||
{
|
||||
OS_Handle result = {0};
|
||||
OS_Monitor result = {0};
|
||||
// TODO(rjf)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
os_name_from_monitor(Arena *arena, OS_Handle monitor)
|
||||
os_name_from_monitor(Arena *arena, OS_Monitor monitor)
|
||||
{
|
||||
// TODO(rjf)
|
||||
return str8_zero();
|
||||
}
|
||||
|
||||
internal Vec2F32
|
||||
os_dim_from_monitor(OS_Handle monitor)
|
||||
os_dim_from_monitor(OS_Monitor monitor)
|
||||
{
|
||||
// TODO(rjf)
|
||||
return v2f32(0, 0);
|
||||
}
|
||||
|
||||
internal F32
|
||||
os_dpi_from_monitor(OS_Handle monitor)
|
||||
os_dpi_from_monitor(OS_Monitor monitor)
|
||||
{
|
||||
// TODO(rjf)
|
||||
return 96.f;
|
||||
@@ -652,9 +652,9 @@ os_key_is_down(OS_Key key)
|
||||
}
|
||||
|
||||
internal Vec2F32
|
||||
os_mouse_from_window(OS_Handle handle)
|
||||
os_mouse_from_window(OS_Window handle)
|
||||
{
|
||||
if(os_handle_match(handle, os_handle_zero())) {return v2f32(0, 0);}
|
||||
if(os_window_match(handle, os_window_zero())) {return v2f32(0, 0);}
|
||||
OS_LNX_Window *w = (OS_LNX_Window *)handle.u64[0];
|
||||
Vec2F32 result = {0};
|
||||
{
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,215 +0,0 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef OS_CORE_LINUX_H
|
||||
#define OS_CORE_LINUX_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Includes
|
||||
|
||||
#include <dirent.h>
|
||||
#include <dlfcn.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <execinfo.h>
|
||||
#include <fcntl.h>
|
||||
#include <features.h>
|
||||
#include <linux/limits.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <signal.h>
|
||||
#include <spawn.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/random.h>
|
||||
#include <sys/sendfile.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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);
|
||||
|
||||
typedef struct tm tm;
|
||||
typedef struct timespec timespec;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
#define OS_LNX_RETRY_ON_EINTR(expr) \
|
||||
(__extension__({ \
|
||||
__typeof__(expr) __ret; \
|
||||
do { \
|
||||
__ret = (expr); \
|
||||
} while ((__ret == -1) && errno == EINTR); \
|
||||
__ret; \
|
||||
}))
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Register Layouts
|
||||
//
|
||||
// These are defined in <sys/user.h>, but only for one architecture at a time
|
||||
|
||||
typedef struct OS_LNX_GprsX64 OS_LNX_GprsX64;
|
||||
struct OS_LNX_GprsX64
|
||||
{
|
||||
U64 r15;
|
||||
U64 r14;
|
||||
U64 r13;
|
||||
U64 r12;
|
||||
U64 rbp;
|
||||
U64 rbx;
|
||||
U64 r11;
|
||||
U64 r10;
|
||||
U64 r9;
|
||||
U64 r8;
|
||||
U64 rax;
|
||||
U64 rcx;
|
||||
U64 rdx;
|
||||
U64 rsi;
|
||||
U64 rdi;
|
||||
U64 orig_rax;
|
||||
U64 rip;
|
||||
U64 cs;
|
||||
U64 rflags;
|
||||
U64 rsp;
|
||||
U64 ss;
|
||||
U64 fsbase;
|
||||
U64 gsbase;
|
||||
U64 ds;
|
||||
U64 es;
|
||||
U64 fs;
|
||||
U64 gs;
|
||||
};
|
||||
|
||||
typedef struct OS_LNX_UserX64 OS_LNX_UserX64;
|
||||
struct OS_LNX_UserX64
|
||||
{
|
||||
OS_LNX_GprsX64 regs;
|
||||
S32 u_fpvalid;
|
||||
U32 _pad0;
|
||||
X64_FXSave i387;
|
||||
U64 u_tsize;
|
||||
U64 u_dsize;
|
||||
U64 u_ssize;
|
||||
U64 start_code;
|
||||
U64 start_stack;
|
||||
U64 signal;
|
||||
U32 reserved;
|
||||
U32 _pad1;
|
||||
U64 u_ar0;
|
||||
U64 u_fpstate;
|
||||
U64 magic;
|
||||
U8 u_comm[32];
|
||||
U64 u_debugreg[8];
|
||||
};
|
||||
StaticAssert(sizeof(OS_LNX_UserX64) == 912, g_os_lnx_user_x64_size_check);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: File Iterator
|
||||
|
||||
typedef struct OS_LNX_FileIter OS_LNX_FileIter;
|
||||
struct OS_LNX_FileIter
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *dp;
|
||||
String8 path;
|
||||
};
|
||||
StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(OS_LNX_FileIter), os_lnx_file_iter_size_check);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Safe Call Handler Chain
|
||||
|
||||
typedef struct OS_LNX_SafeCallChain OS_LNX_SafeCallChain;
|
||||
struct OS_LNX_SafeCallChain
|
||||
{
|
||||
OS_LNX_SafeCallChain *next;
|
||||
ThreadEntryPointFunctionType *fail_handler;
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entities
|
||||
|
||||
typedef enum OS_LNX_EntityKind
|
||||
{
|
||||
OS_LNX_EntityKind_Thread,
|
||||
OS_LNX_EntityKind_Mutex,
|
||||
OS_LNX_EntityKind_RWMutex,
|
||||
OS_LNX_EntityKind_ConditionVariable,
|
||||
OS_LNX_EntityKind_Barrier,
|
||||
}
|
||||
OS_LNX_EntityKind;
|
||||
|
||||
typedef struct OS_LNX_Entity OS_LNX_Entity;
|
||||
struct OS_LNX_Entity
|
||||
{
|
||||
OS_LNX_Entity *next;
|
||||
OS_LNX_EntityKind kind;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
pthread_t handle;
|
||||
ThreadEntryPointFunctionType *func;
|
||||
void *ptr;
|
||||
} thread;
|
||||
pthread_mutex_t mutex_handle;
|
||||
pthread_rwlock_t rwmutex_handle;
|
||||
struct
|
||||
{
|
||||
pthread_cond_t cond_handle;
|
||||
pthread_mutex_t rwlock_mutex_handle;
|
||||
} cv;
|
||||
pthread_barrier_t barrier;
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: State
|
||||
|
||||
typedef struct OS_LNX_State OS_LNX_State;
|
||||
struct OS_LNX_State
|
||||
{
|
||||
Arena *arena;
|
||||
OS_SystemInfo system_info;
|
||||
OS_ProcessInfo process_info;
|
||||
pthread_mutex_t entity_mutex;
|
||||
Arena *entity_arena;
|
||||
OS_LNX_Entity *entity_free;
|
||||
U64 default_env_count;
|
||||
char **default_env;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global OS_LNX_State os_lnx_state = {0};
|
||||
thread_static OS_LNX_SafeCallChain *os_lnx_safe_call_chain = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Helpers
|
||||
|
||||
internal DateTime os_lnx_date_time_from_tm(tm in, U32 msec);
|
||||
internal tm os_lnx_tm_from_date_time(DateTime dt);
|
||||
internal timespec os_lnx_timespec_from_date_time(DateTime dt);
|
||||
internal DenseTime os_lnx_dense_time_from_timespec(timespec in);
|
||||
internal FileProperties os_lnx_file_properties_from_stat(struct stat *s);
|
||||
internal void os_lnx_safe_call_sig_handler(int x);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entities
|
||||
|
||||
internal OS_LNX_Entity *os_lnx_entity_alloc(OS_LNX_EntityKind kind);
|
||||
internal void os_lnx_entity_release(OS_LNX_Entity *entity);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Thread Entry Point
|
||||
|
||||
internal void *os_lnx_thread_entry_point(void *ptr);
|
||||
|
||||
#endif // OS_CORE_LINUX_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,88 +0,0 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef LINUX_H
|
||||
#define LINUX_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Get all these linux includes
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/limits.h>
|
||||
#include <time.h>
|
||||
#include <dirent.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/sysinfo.h>
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): File Iterator
|
||||
|
||||
struct LNX_FileIter{
|
||||
int fd;
|
||||
DIR *dir;
|
||||
};
|
||||
StaticAssert(sizeof(Member(OS_FileIter, memory)) >= sizeof(LNX_FileIter), file_iter_memory_size);
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Threading Entities
|
||||
|
||||
enum LNX_EntityKind{
|
||||
LNX_EntityKind_Null,
|
||||
LNX_EntityKind_Thread,
|
||||
LNX_EntityKind_Mutex,
|
||||
LNX_EntityKind_ConditionVariable,
|
||||
};
|
||||
|
||||
struct LNX_Entity{
|
||||
LNX_Entity *next;
|
||||
LNX_EntityKind kind;
|
||||
volatile U32 reference_mask;
|
||||
union{
|
||||
struct{
|
||||
ThreadEntryPointFunctionType *func;
|
||||
void *ptr;
|
||||
pthread_t handle;
|
||||
} thread;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Safe Call Chain
|
||||
|
||||
struct LNX_SafeCallChain{
|
||||
LNX_SafeCallChain *next;
|
||||
ThreadEntryPointFunctionType *fail_handler;
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(allen): Helpers
|
||||
|
||||
internal B32 lnx_write_list_to_file_descriptor(int fd, String8List list);
|
||||
|
||||
internal void lnx_date_time_from_tm(DateTime *out, struct tm *in, U32 msec);
|
||||
internal void lnx_tm_from_date_time(struct tm *out, DateTime *in);
|
||||
internal void lnx_dense_time_from_timespec(DenseTime *out, struct timespec *in);
|
||||
internal void lnx_file_properties_from_stat(FileProperties *out, struct stat *in);
|
||||
|
||||
internal String8 lnx_string_from_signal(int signum);
|
||||
internal String8 lnx_string_from_errno(int error_number);
|
||||
|
||||
internal LNX_Entity* lnx_alloc_entity(LNX_EntityKind kind);
|
||||
internal void lnx_free_entity(LNX_Entity *entity);
|
||||
internal void* lnx_thread_base(void *ptr);
|
||||
|
||||
internal void lnx_safe_call_sig_handler(int);
|
||||
|
||||
#endif //LINUX_H
|
||||
@@ -1,279 +0,0 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type Functions (Helpers, Implemented Once)
|
||||
|
||||
internal OS_Handle
|
||||
os_handle_zero(void)
|
||||
{
|
||||
OS_Handle handle = {0};
|
||||
return handle;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_handle_match(OS_Handle a, OS_Handle b)
|
||||
{
|
||||
return a.u64[0] == b.u64[0];
|
||||
}
|
||||
|
||||
internal void
|
||||
os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle)
|
||||
{
|
||||
OS_HandleNode *n = push_array(arena, OS_HandleNode, 1);
|
||||
n->v = handle;
|
||||
SLLQueuePush(handles->first, handles->last, n);
|
||||
handles->count += 1;
|
||||
}
|
||||
|
||||
internal OS_HandleArray
|
||||
os_handle_array_from_list(Arena *arena, OS_HandleList *list)
|
||||
{
|
||||
OS_HandleArray result = {0};
|
||||
result.count = list->count;
|
||||
result.v = push_array_no_zero(arena, OS_Handle, result.count);
|
||||
U64 idx = 0;
|
||||
for(OS_HandleNode *n = list->first; n != 0; n = n->next, idx += 1)
|
||||
{
|
||||
result.v[idx] = n->v;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
|
||||
|
||||
internal String8
|
||||
os_data_from_file_path(Arena *arena, String8 path)
|
||||
{
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path);
|
||||
FileProperties props = os_properties_from_file(file);
|
||||
String8 data = os_string_from_file_range(arena, file, r1u64(0, props.size));
|
||||
os_file_close(file);
|
||||
return data;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_write_data_to_file_path(String8 path, String8 data)
|
||||
{
|
||||
B32 good = 0;
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Write, path);
|
||||
if(!os_handle_match(file, os_handle_zero()))
|
||||
{
|
||||
U64 bytes_written = os_file_write(file, r1u64(0, data.size), data.str);
|
||||
good = (bytes_written == data.size);
|
||||
os_file_close(file);
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_write_data_list_to_file_path(String8 path, String8List list)
|
||||
{
|
||||
B32 good = 0;
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Write, path);
|
||||
if(!os_handle_match(file, os_handle_zero()))
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
U64 write_buffer_size = KB(64);
|
||||
U8 *write_buffer = push_array_no_zero(scratch.arena, U8, write_buffer_size);
|
||||
U64 write_buffer_write_pos = 0;
|
||||
U64 write_buffer_read_pos = 0;
|
||||
U64 file_off = 0;
|
||||
{
|
||||
for(String8Node *n = list.first; n != 0; n = n->next)
|
||||
{
|
||||
for(U64 n_off = 0; n_off < n->string.size;)
|
||||
{
|
||||
U64 write_buffer_unconsumed_size = (write_buffer_write_pos - write_buffer_read_pos);
|
||||
U64 write_buffer_available_size = (write_buffer_size - write_buffer_unconsumed_size);
|
||||
if(write_buffer_available_size == 0)
|
||||
{
|
||||
U64 file_write_size = os_file_write(file, r1u64(file_off, file_off+write_buffer_size), write_buffer);
|
||||
if(file_write_size != write_buffer_size)
|
||||
{
|
||||
goto dbl_break;
|
||||
}
|
||||
file_off += write_buffer_size;
|
||||
write_buffer_read_pos += write_buffer_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
U64 bytes_to_copy = Min(write_buffer_available_size, n->string.size - n_off);
|
||||
write_buffer_write_pos += ring_write(write_buffer, write_buffer_size, write_buffer_write_pos, n->string.str + n_off, bytes_to_copy);
|
||||
n_off += bytes_to_copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(write_buffer_write_pos > write_buffer_read_pos)
|
||||
{
|
||||
U64 file_write_size = os_file_write(file, r1u64(file_off, file_off + (write_buffer_write_pos-write_buffer_read_pos)), write_buffer);
|
||||
file_off += file_write_size;
|
||||
}
|
||||
}
|
||||
dbl_break:;
|
||||
good = (file_off == list.total_size);
|
||||
os_file_close(file);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
internal B32
|
||||
os_append_data_to_file_path(String8 path, String8 data)
|
||||
{
|
||||
B32 good = 0;
|
||||
if(data.size != 0)
|
||||
{
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append, path);
|
||||
if(!os_handle_match(file, os_handle_zero()))
|
||||
{
|
||||
U64 pos = os_properties_from_file(file).size;
|
||||
U64 bytes_written = os_file_write(file, r1u64(pos, pos+data.size), data.str);
|
||||
good = (bytes_written == data.size);
|
||||
os_file_close(file);
|
||||
}
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
internal OS_FileID
|
||||
os_id_from_file_path(String8 path)
|
||||
{
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path);
|
||||
OS_FileID id = os_id_from_file(file);
|
||||
os_file_close(file);
|
||||
return id;
|
||||
}
|
||||
|
||||
internal S64
|
||||
os_file_id_compare(OS_FileID a, OS_FileID b)
|
||||
{
|
||||
S64 cmp = MemoryCompare((void*)&a.v[0], (void*)&b.v[0], sizeof(a.v));
|
||||
return cmp;
|
||||
}
|
||||
|
||||
internal String8
|
||||
os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range)
|
||||
{
|
||||
U64 pre_pos = arena_pos(arena);
|
||||
String8 result;
|
||||
result.size = dim_1u64(range);
|
||||
result.str = push_array_no_zero(arena, U8, result.size);
|
||||
U64 actual_read_size = os_file_read(file, range, result.str);
|
||||
if(actual_read_size < result.size)
|
||||
{
|
||||
arena_pop_to(arena, pre_pos + actual_read_size);
|
||||
result.size = actual_read_size;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
os_file_read_cstring(Arena *arena, OS_Handle file, U64 off)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8List block_list = {0};
|
||||
for(U64 cursor = off, stride = 256;; cursor += stride)
|
||||
{
|
||||
U8 *raw_block = push_array_no_zero(scratch.arena, U8, stride);
|
||||
U64 read_size = os_file_read(file, r1u64(cursor, cursor + stride), raw_block);
|
||||
String8 block = str8_cstring_capped(raw_block, raw_block+read_size);
|
||||
str8_list_push(scratch.arena, &block_list, block);
|
||||
if(read_size != stride || (block.size+1 <= read_size && block.str[block.size] == 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
String8 result = str8_list_join(arena, &block_list, 0);
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Process Launcher Helpers
|
||||
|
||||
internal OS_Handle
|
||||
os_cmd_line_launch(String8 string)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
U8 split_chars[] = {' '};
|
||||
String8List parts = str8_split(scratch.arena, string, split_chars, ArrayCount(split_chars), 0);
|
||||
OS_Handle handle = {0};
|
||||
if(parts.node_count != 0)
|
||||
{
|
||||
// rjf: unpack exe part
|
||||
String8 exe = parts.first->string;
|
||||
String8 exe_folder = str8_chop_last_slash(exe);
|
||||
if(exe_folder.size == 0)
|
||||
{
|
||||
exe_folder = os_get_current_path(scratch.arena);
|
||||
}
|
||||
|
||||
// rjf: find stdout delimiter
|
||||
String8Node *stdout_delimiter_n = 0;
|
||||
for(String8Node *n = parts.first; n != 0; n = n->next)
|
||||
{
|
||||
if(str8_match(n->string, str8_lit(">"), 0))
|
||||
{
|
||||
stdout_delimiter_n = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: read stdout path
|
||||
String8 stdout_path = {0};
|
||||
if(stdout_delimiter_n && stdout_delimiter_n->next)
|
||||
{
|
||||
stdout_path = stdout_delimiter_n->next->string;
|
||||
}
|
||||
|
||||
// rjf: open stdout handle
|
||||
OS_Handle stdout_handle = {0};
|
||||
if(stdout_path.size != 0)
|
||||
{
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Read, stdout_path);
|
||||
os_file_close(file);
|
||||
stdout_handle = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite|OS_AccessFlag_Inherited, stdout_path);
|
||||
}
|
||||
|
||||
// rjf: form command line
|
||||
String8List cmdline = {0};
|
||||
for(String8Node *n = parts.first; n != stdout_delimiter_n && n != 0; n = n->next)
|
||||
{
|
||||
str8_list_push(scratch.arena, &cmdline, n->string);
|
||||
}
|
||||
|
||||
// rjf: launch
|
||||
OS_ProcessLaunchParams params = {0};
|
||||
params.cmd_line = cmdline;
|
||||
params.path = exe_folder;
|
||||
params.inherit_env = 1;
|
||||
params.stdout_file = stdout_handle;
|
||||
handle = os_process_launch(¶ms);
|
||||
|
||||
// rjf: close stdout handle
|
||||
{
|
||||
if(stdout_path.size != 0)
|
||||
{
|
||||
os_file_close(stdout_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
return handle;
|
||||
}
|
||||
|
||||
internal OS_Handle
|
||||
os_cmd_line_launchf(char *fmt, ...)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
String8 string = push_str8fv(scratch.arena, fmt, args);
|
||||
OS_Handle result = os_cmd_line_launch(string);
|
||||
va_end(args);
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,324 +0,0 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef OS_CORE_H
|
||||
#define OS_CORE_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: System Info
|
||||
|
||||
typedef struct OS_SystemInfo OS_SystemInfo;
|
||||
struct OS_SystemInfo
|
||||
{
|
||||
U32 logical_processor_count;
|
||||
U64 page_size;
|
||||
U64 large_page_size;
|
||||
U64 allocation_granularity;
|
||||
String8 machine_name;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Process Info
|
||||
|
||||
typedef struct OS_ProcessInfo OS_ProcessInfo;
|
||||
struct OS_ProcessInfo
|
||||
{
|
||||
U32 pid;
|
||||
B32 large_pages_allowed;
|
||||
String8 binary_path;
|
||||
String8 initial_path;
|
||||
String8 user_program_data_path;
|
||||
String8List module_load_paths;
|
||||
String8List environment;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Access Flags
|
||||
|
||||
typedef U32 OS_AccessFlags;
|
||||
enum
|
||||
{
|
||||
OS_AccessFlag_Read = (1<<0),
|
||||
OS_AccessFlag_Write = (1<<1),
|
||||
OS_AccessFlag_Execute = (1<<2),
|
||||
OS_AccessFlag_Append = (1<<3),
|
||||
OS_AccessFlag_ShareRead = (1<<4),
|
||||
OS_AccessFlag_ShareWrite = (1<<5),
|
||||
OS_AccessFlag_Inherited = (1<<6),
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Files
|
||||
|
||||
typedef U32 OS_FileIterFlags;
|
||||
enum
|
||||
{
|
||||
OS_FileIterFlag_SkipFolders = (1 << 0),
|
||||
OS_FileIterFlag_SkipFiles = (1 << 1),
|
||||
OS_FileIterFlag_SkipHiddenFiles = (1 << 2),
|
||||
OS_FileIterFlag_Done = (1 << 31),
|
||||
};
|
||||
|
||||
typedef struct OS_FileIter OS_FileIter;
|
||||
struct OS_FileIter
|
||||
{
|
||||
OS_FileIterFlags flags;
|
||||
U8 memory[800];
|
||||
};
|
||||
|
||||
typedef struct OS_FileInfo OS_FileInfo;
|
||||
struct OS_FileInfo
|
||||
{
|
||||
String8 name;
|
||||
FileProperties props;
|
||||
};
|
||||
|
||||
// nick: on-disk file identifier
|
||||
typedef struct OS_FileID OS_FileID;
|
||||
struct OS_FileID
|
||||
{
|
||||
U64 v[3];
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type
|
||||
|
||||
typedef struct OS_Handle OS_Handle;
|
||||
struct OS_Handle
|
||||
{
|
||||
U64 u64[1];
|
||||
};
|
||||
|
||||
typedef struct OS_HandleNode OS_HandleNode;
|
||||
struct OS_HandleNode
|
||||
{
|
||||
OS_HandleNode *next;
|
||||
OS_Handle v;
|
||||
};
|
||||
|
||||
typedef struct OS_HandleList OS_HandleList;
|
||||
struct OS_HandleList
|
||||
{
|
||||
OS_HandleNode *first;
|
||||
OS_HandleNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct OS_HandleArray OS_HandleArray;
|
||||
struct OS_HandleArray
|
||||
{
|
||||
OS_Handle *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Process Launch Parameters
|
||||
|
||||
typedef struct OS_ProcessLaunchParams OS_ProcessLaunchParams;
|
||||
struct OS_ProcessLaunchParams
|
||||
{
|
||||
String8List cmd_line;
|
||||
String8 path;
|
||||
String8List env;
|
||||
B32 inherit_env;
|
||||
B32 debug_subprocesses;
|
||||
B32 consoleless;
|
||||
OS_Handle stdout_file;
|
||||
OS_Handle stderr_file;
|
||||
OS_Handle stdin_file;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type Functions (Helpers, Implemented Once)
|
||||
|
||||
internal OS_Handle os_handle_zero(void);
|
||||
internal B32 os_handle_match(OS_Handle a, OS_Handle b);
|
||||
internal void os_handle_list_push(Arena *arena, OS_HandleList *handles, OS_Handle handle);
|
||||
internal OS_HandleArray os_handle_array_from_list(Arena *arena, OS_HandleList *list);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Filesystem Helpers (Helpers, Implemented Once)
|
||||
|
||||
internal String8 os_data_from_file_path(Arena *arena, String8 path);
|
||||
internal B32 os_write_data_to_file_path(String8 path, String8 data);
|
||||
internal B32 os_write_data_list_to_file_path(String8 path, String8List list);
|
||||
internal B32 os_append_data_to_file_path(String8 path, String8 data);
|
||||
internal OS_FileID os_id_from_file_path(String8 path);
|
||||
internal S64 os_file_id_compare(OS_FileID a, OS_FileID b);
|
||||
internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range);
|
||||
internal String8 os_file_read_cstring(Arena *arena, OS_Handle file, U64 off);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Process Launcher Helpers
|
||||
|
||||
internal OS_Handle os_cmd_line_launch(String8 string);
|
||||
internal OS_Handle os_cmd_line_launchf(char *fmt, ...);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks System/Process Info (Implemented Per-OS)
|
||||
|
||||
internal OS_SystemInfo *os_get_system_info(void);
|
||||
internal OS_ProcessInfo *os_get_process_info(void);
|
||||
internal String8 os_get_current_path(Arena *arena);
|
||||
internal U32 os_get_process_start_time_unix(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Memory Allocation (Implemented Per-OS)
|
||||
|
||||
//- rjf: basic
|
||||
internal void *os_reserve(U64 size);
|
||||
internal B32 os_commit(void *ptr, U64 size);
|
||||
internal void os_decommit(void *ptr, U64 size);
|
||||
internal void os_release(void *ptr, U64 size);
|
||||
|
||||
//- rjf: large pages
|
||||
internal void *os_reserve_large(U64 size);
|
||||
internal B32 os_commit_large(void *ptr, U64 size);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Thread Info (Implemented Per-OS)
|
||||
|
||||
internal U32 os_tid(void);
|
||||
internal void os_set_thread_name(String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Aborting (Implemented Per-OS)
|
||||
|
||||
internal void os_abort(S32 exit_code);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks File System (Implemented Per-OS)
|
||||
|
||||
//- rjf: files
|
||||
internal OS_Handle os_file_open(OS_AccessFlags flags, String8 path);
|
||||
internal void os_file_close(OS_Handle file);
|
||||
internal U64 os_file_read(OS_Handle file, Rng1U64 rng, void *out_data);
|
||||
#define os_file_read_struct(f, off, ptr) os_file_read((f), r1u64((off), (off)+sizeof(*(ptr))), (ptr))
|
||||
internal U64 os_file_write(OS_Handle file, Rng1U64 rng, void *data);
|
||||
internal B32 os_file_set_times(OS_Handle file, DateTime time);
|
||||
internal FileProperties os_properties_from_file(OS_Handle file);
|
||||
internal OS_FileID os_id_from_file(OS_Handle file);
|
||||
internal B32 os_file_reserve_size(OS_Handle file, U64 size);
|
||||
internal B32 os_delete_file_at_path(String8 path);
|
||||
internal B32 os_copy_file_path(String8 dst, String8 src);
|
||||
internal B32 os_move_file_path(String8 dst, String8 src);
|
||||
internal String8 os_full_path_from_path(Arena *arena, String8 path);
|
||||
internal B32 os_file_path_exists(String8 path);
|
||||
internal B32 os_folder_path_exists(String8 path);
|
||||
internal FileProperties os_properties_from_file_path(String8 path);
|
||||
|
||||
//- rjf: file maps
|
||||
internal OS_Handle os_file_map_open(OS_AccessFlags flags, OS_Handle file);
|
||||
internal void os_file_map_close(OS_Handle map);
|
||||
internal void * os_file_map_view_open(OS_Handle map, OS_AccessFlags flags, Rng1U64 range);
|
||||
internal void os_file_map_view_close(OS_Handle map, void *ptr, Rng1U64 range);
|
||||
|
||||
//- rjf: directory iteration
|
||||
internal OS_FileIter *os_file_iter_begin(Arena *arena, String8 path, OS_FileIterFlags flags);
|
||||
internal B32 os_file_iter_next(Arena *arena, OS_FileIter *iter, OS_FileInfo *info_out);
|
||||
internal void os_file_iter_end(OS_FileIter *iter);
|
||||
|
||||
//- rjf: directory creation
|
||||
internal B32 os_make_directory(String8 path);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Shared Memory (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle os_shared_memory_alloc(U64 size, String8 name);
|
||||
internal OS_Handle os_shared_memory_open(String8 name);
|
||||
internal void os_shared_memory_close(OS_Handle handle);
|
||||
internal void * os_shared_memory_view_open(OS_Handle handle, Rng1U64 range);
|
||||
internal void os_shared_memory_view_close(OS_Handle handle, void *ptr, Rng1U64 range);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Time (Implemented Per-OS)
|
||||
|
||||
internal U64 os_now_microseconds(void);
|
||||
internal U32 os_now_unix(void);
|
||||
internal DateTime os_now_universal_time(void);
|
||||
internal DateTime os_universal_time_from_local(DateTime *local_time);
|
||||
internal DateTime os_local_time_from_universal(DateTime *universal_time);
|
||||
internal void os_sleep_milliseconds(U32 msec);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Child Processes (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle os_process_launch(OS_ProcessLaunchParams *params);
|
||||
internal B32 os_process_join(OS_Handle handle, U64 endt_us, U64 *exit_code_out);
|
||||
internal void os_process_detach(OS_Handle handle);
|
||||
internal B32 os_process_kill(OS_Handle handle);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Threads (Implemented Per-OS)
|
||||
|
||||
internal Thread os_thread_launch(ThreadEntryPointFunctionType *f, void *p);
|
||||
internal B32 os_thread_join(Thread handle, U64 endt_us);
|
||||
internal void os_thread_detach(Thread handle);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Synchronization Primitives (Implemented Per-OS)
|
||||
|
||||
//- rjf: recursive mutexes
|
||||
internal Mutex os_mutex_alloc(void);
|
||||
internal void os_mutex_release(Mutex mutex);
|
||||
internal void os_mutex_take(Mutex mutex);
|
||||
internal void os_mutex_drop(Mutex mutex);
|
||||
|
||||
//- rjf: reader/writer mutexes
|
||||
internal RWMutex os_rw_mutex_alloc(void);
|
||||
internal void os_rw_mutex_release(RWMutex mutex);
|
||||
internal void os_rw_mutex_take(RWMutex mutex, B32 write_mode);
|
||||
internal void os_rw_mutex_drop(RWMutex mutex, B32 write_mode);
|
||||
|
||||
//- rjf: condition variables
|
||||
internal CondVar os_cond_var_alloc(void);
|
||||
internal void os_cond_var_release(CondVar cv);
|
||||
// returns false on timeout, true on signal, (max_wait_ms = max_U64) -> no timeout
|
||||
internal B32 os_cond_var_wait(CondVar cv, Mutex mutex, U64 endt_us);
|
||||
internal B32 os_cond_var_wait_rw(CondVar cv, RWMutex mutex_rw, B32 write_mode, U64 endt_us);
|
||||
internal void os_cond_var_signal(CondVar cv);
|
||||
internal void os_cond_var_broadcast(CondVar cv);
|
||||
|
||||
//- rjf: cross-process semaphores
|
||||
internal Semaphore os_semaphore_alloc(U32 initial_count, U32 max_count, String8 name);
|
||||
internal void os_semaphore_release(Semaphore semaphore);
|
||||
internal Semaphore os_semaphore_open(String8 name);
|
||||
internal void os_semaphore_close(Semaphore semaphore);
|
||||
internal B32 os_semaphore_take(Semaphore semaphore, U64 endt_us);
|
||||
internal void os_semaphore_drop(Semaphore semaphore);
|
||||
|
||||
//- rjf: barriers
|
||||
internal Barrier os_barrier_alloc(U64 count);
|
||||
internal void os_barrier_release(Barrier barrier);
|
||||
internal void os_barrier_wait(Barrier barrier);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Dynamically-Loaded Libraries (Implemented Per-OS)
|
||||
|
||||
internal OS_Handle os_library_open(String8 path);
|
||||
internal void os_library_close(OS_Handle lib);
|
||||
internal VoidProc *os_library_load_proc(OS_Handle lib, String8 name);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Safe Calls (Implemented Per-OS)
|
||||
|
||||
internal void os_safe_call(ThreadEntryPointFunctionType *func, ThreadEntryPointFunctionType *fail_handler, void *ptr);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks GUIDs (Implemented Per-OS)
|
||||
|
||||
internal Guid os_make_guid(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @os_hooks Entry Points (Implemented Per-OS)
|
||||
|
||||
// NOTE(rjf): The implementation of `os_core` will define low-level entry
|
||||
// points if BUILD_ENTRY_DEFINING_UNIT is defined to 1. These will call
|
||||
// into the standard codebase program entry points, named "entry_point".
|
||||
|
||||
#if BUILD_ENTRY_DEFINING_UNIT
|
||||
raddbg_entry_point(entry_point);
|
||||
internal no_inline void entry_point(CmdLine *cmdline);
|
||||
#endif
|
||||
|
||||
#endif // OS_CORE_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,27 +0,0 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
// #include "os/core/os_core.c"
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
# include "os/gfx/os_gfx.c"
|
||||
#endif
|
||||
|
||||
#if OS_WINDOWS
|
||||
// # include "os/core/win32/os_core_win32.c"
|
||||
#elif OS_LINUX
|
||||
# include "os/core/linux/os_core_linux.c"
|
||||
#else
|
||||
# error OS core layer not implemented for this operating system.
|
||||
#endif
|
||||
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
# if OS_GFX_STUB
|
||||
# include "os/gfx/stub/os_gfx_stub.c"
|
||||
# elif OS_WINDOWS
|
||||
# include "os/gfx/win32/os_gfx_win32.c"
|
||||
# elif OS_LINUX
|
||||
# include "os/gfx/linux/os_gfx_linux.c"
|
||||
# else
|
||||
# error OS graphical layer not implemented for this operating system.
|
||||
# endif
|
||||
#endif
|
||||
@@ -1,40 +0,0 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef OS_INC_H
|
||||
#define OS_INC_H
|
||||
|
||||
#if !defined(OS_FEATURE_GRAPHICAL)
|
||||
# define OS_FEATURE_GRAPHICAL 0
|
||||
#endif
|
||||
|
||||
#if !defined(OS_GFX_STUB)
|
||||
# define OS_GFX_STUB 0
|
||||
#endif
|
||||
|
||||
// #include "os/core/os_core.h"
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
# include "os/gfx/os_gfx.h"
|
||||
#endif
|
||||
|
||||
#if OS_WINDOWS
|
||||
// # include "os/core/win32/os_core_win32.h"
|
||||
#elif OS_LINUX
|
||||
# include "os/core/linux/os_core_linux.h"
|
||||
#else
|
||||
# error OS core layer not implemented for this operating system.
|
||||
#endif
|
||||
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
# if OS_GFX_STUB
|
||||
# include "os/gfx/stub/os_gfx_stub.h"
|
||||
# elif OS_WINDOWS
|
||||
# include "os/gfx/win32/os_gfx_win32.h"
|
||||
# elif OS_LINUX
|
||||
# include "os/gfx/linux/os_gfx_linux.h"
|
||||
# else
|
||||
# error OS graphical layer not implemented for this operating system.
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif // OS_INC_H
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "linker/hash_table.h"
|
||||
#include "linker/lf_hash_table.h"
|
||||
#include "linker/base_ext/base_bit_array.h"
|
||||
#include "os/os_inc.h"
|
||||
#include "rdi/rdi_local.h"
|
||||
#include "rdi_make/rdi_make_local.h"
|
||||
#include "coff/coff_inc.h"
|
||||
@@ -47,7 +46,6 @@
|
||||
#include "linker/hash_table.c"
|
||||
#include "linker/lf_hash_table.c"
|
||||
#include "linker/base_ext/base_bit_array.c"
|
||||
#include "os/os_inc.c"
|
||||
#include "rdi/rdi_local.c"
|
||||
#include "rdi_make/rdi_make_local.c"
|
||||
#include "coff/coff_inc.c"
|
||||
|
||||
@@ -265,11 +265,11 @@
|
||||
#include "linker/hash_table.h"
|
||||
#include "linker/lf_hash_table.h"
|
||||
#include "linker/base_ext/base_bit_array.h"
|
||||
#include "os/os_inc.h"
|
||||
#include "artifact_cache/artifact_cache.h"
|
||||
#include "rdi/rdi_local.h"
|
||||
#include "rdi_make/rdi_make_local.h"
|
||||
#include "mdesk/mdesk.h"
|
||||
#include "window_manager/window_manager_inc.h"
|
||||
#include "config/config_inc.h"
|
||||
#include "content/content.h"
|
||||
#include "file_stream/file_stream.h"
|
||||
@@ -318,11 +318,11 @@
|
||||
#include "linker/hash_table.c"
|
||||
#include "linker/lf_hash_table.c"
|
||||
#include "linker/base_ext/base_bit_array.c"
|
||||
#include "os/os_inc.c"
|
||||
#include "artifact_cache/artifact_cache.c"
|
||||
#include "rdi/rdi_local.c"
|
||||
#include "rdi_make/rdi_make_local.c"
|
||||
#include "mdesk/mdesk.c"
|
||||
#include "window_manager/window_manager_inc.c"
|
||||
#include "config/config_inc.c"
|
||||
#include "content/content.c"
|
||||
#include "file_stream/file_stream.c"
|
||||
|
||||
@@ -79,7 +79,7 @@ r_ogl_os_init(CmdLine *cmdln)
|
||||
}
|
||||
|
||||
internal R_Handle
|
||||
r_ogl_os_window_equip(OS_Handle window)
|
||||
r_ogl_os_window_equip(OS_Window window)
|
||||
{
|
||||
OS_LNX_Window *window_os = (OS_LNX_Window *)window.u64[0];
|
||||
R_OGL_LNX_Window *w = r_ogl_lnx_state->free_window;
|
||||
@@ -163,7 +163,7 @@ r_ogl_os_window_equip(OS_Handle window)
|
||||
}
|
||||
|
||||
internal void
|
||||
r_ogl_os_window_unequip(OS_Handle os, R_Handle r)
|
||||
r_ogl_os_window_unequip(OS_Window os, R_Handle r)
|
||||
{
|
||||
R_OGL_LNX_Window *w = (R_OGL_LNX_Window *)r.u64[0];
|
||||
{
|
||||
@@ -173,7 +173,7 @@ r_ogl_os_window_unequip(OS_Handle os, R_Handle r)
|
||||
}
|
||||
|
||||
internal void
|
||||
r_ogl_os_select_window(OS_Handle os, R_Handle r)
|
||||
r_ogl_os_select_window(OS_Window os, R_Handle r)
|
||||
{
|
||||
OS_LNX_Window *w = (OS_LNX_Window *)os.u64[0];
|
||||
R_OGL_LNX_Window *w_r = (R_OGL_LNX_Window *)r.u64[0];
|
||||
@@ -181,7 +181,7 @@ r_ogl_os_select_window(OS_Handle os, R_Handle r)
|
||||
}
|
||||
|
||||
internal void
|
||||
r_ogl_os_window_swap(OS_Handle os, R_Handle r)
|
||||
r_ogl_os_window_swap(OS_Window os, R_Handle r)
|
||||
{
|
||||
OS_LNX_Window *w = (OS_LNX_Window *)os.u64[0];
|
||||
R_OGL_LNX_Window *w_r = (R_OGL_LNX_Window *)r.u64[0];
|
||||
|
||||
@@ -79,27 +79,27 @@ r_ogl_os_init(CmdLine *cmdln)
|
||||
}
|
||||
|
||||
internal R_Handle
|
||||
r_ogl_os_window_equip(OS_Handle window)
|
||||
r_ogl_os_window_equip(OS_Window window)
|
||||
{
|
||||
R_Handle result = {0};
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
r_ogl_os_window_unequip(OS_Handle os, R_Handle r)
|
||||
r_ogl_os_window_unequip(OS_Window os, R_Handle r)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal void
|
||||
r_ogl_os_select_window(OS_Handle os, R_Handle r)
|
||||
r_ogl_os_select_window(OS_Window os, R_Handle r)
|
||||
{
|
||||
OS_LNX_Window *w = (OS_LNX_Window *)os.u64[0];
|
||||
glXMakeCurrent(os_lnx_gfx_state->display, w->window, r_ogl_lnx_ctx);
|
||||
}
|
||||
|
||||
internal void
|
||||
r_ogl_os_window_swap(OS_Handle os, R_Handle r)
|
||||
r_ogl_os_window_swap(OS_Window os, R_Handle r)
|
||||
{
|
||||
OS_LNX_Window *w = (OS_LNX_Window *)os.u64[0];
|
||||
glXSwapBuffers(os_lnx_gfx_state->display, w->window);
|
||||
|
||||
@@ -201,14 +201,14 @@ r_init(CmdLine *cmdln)
|
||||
//- rjf: window setup/teardown
|
||||
|
||||
r_hook R_Handle
|
||||
r_window_equip(OS_Handle window)
|
||||
r_window_equip(OS_Window window)
|
||||
{
|
||||
R_Handle result = r_ogl_os_window_equip(window);
|
||||
return result;
|
||||
}
|
||||
|
||||
r_hook void
|
||||
r_window_unequip(OS_Handle window, R_Handle window_equip)
|
||||
r_window_unequip(OS_Window window, R_Handle window_equip)
|
||||
{
|
||||
r_ogl_os_window_unequip(window, window_equip);
|
||||
}
|
||||
@@ -341,7 +341,7 @@ r_end_frame(void)
|
||||
}
|
||||
|
||||
r_hook void
|
||||
r_window_begin_frame(OS_Handle os, R_Handle r)
|
||||
r_window_begin_frame(OS_Window os, R_Handle r)
|
||||
{
|
||||
r_ogl_os_select_window(os, r);
|
||||
|
||||
@@ -358,7 +358,7 @@ r_window_begin_frame(OS_Handle os, R_Handle r)
|
||||
}
|
||||
|
||||
r_hook void
|
||||
r_window_end_frame(OS_Handle os, R_Handle r)
|
||||
r_window_end_frame(OS_Window os, R_Handle r)
|
||||
{
|
||||
for(R_OGL_FlushBuffer *flush_buffer = r_ogl_state->first_buffer_to_flush; flush_buffer != 0; flush_buffer = flush_buffer->next)
|
||||
{
|
||||
@@ -372,7 +372,7 @@ r_window_end_frame(OS_Handle os, R_Handle r)
|
||||
//- rjf: render pass submission
|
||||
|
||||
r_hook void
|
||||
r_window_submit(OS_Handle window, R_Handle window_equip, R_PassList *passes)
|
||||
r_window_submit(OS_Window window, R_Handle window_equip, R_PassList *passes)
|
||||
{
|
||||
Rng2F32 viewport_rect = os_client_rect_from_window(window);
|
||||
Vec2F32 viewport_dim = dim_2f32(viewport_rect);
|
||||
|
||||
@@ -224,9 +224,9 @@ internal void r_ogl_debug_message_callback(GLenum source, GLenum type, GLuint id
|
||||
|
||||
internal VoidProc *r_ogl_os_load_procedure(char *name);
|
||||
internal void r_ogl_os_init(CmdLine *cmdln);
|
||||
internal R_Handle r_ogl_os_window_equip(OS_Handle window);
|
||||
internal void r_ogl_os_window_unequip(OS_Handle os, R_Handle r);
|
||||
internal void r_ogl_os_select_window(OS_Handle os, R_Handle r);
|
||||
internal void r_ogl_os_window_swap(OS_Handle os, R_Handle r);
|
||||
internal R_Handle r_ogl_os_window_equip(OS_Window window);
|
||||
internal void r_ogl_os_window_unequip(OS_Window os, R_Handle r);
|
||||
internal void r_ogl_os_select_window(OS_Window os, R_Handle r);
|
||||
internal void r_ogl_os_window_swap(OS_Window os, R_Handle r);
|
||||
|
||||
#endif // RENDER_OPENGL_H
|
||||
|
||||
@@ -101,7 +101,7 @@ r_ogl_os_init(CmdLine *cmdline)
|
||||
}
|
||||
|
||||
internal R_Handle
|
||||
r_ogl_os_window_equip(OS_Handle window)
|
||||
r_ogl_os_window_equip(OS_Window window)
|
||||
{
|
||||
//- rjf: unpack window
|
||||
OS_W32_Window *w = os_w32_window_from_handle(window);
|
||||
@@ -155,12 +155,12 @@ r_ogl_os_window_equip(OS_Handle window)
|
||||
}
|
||||
|
||||
internal void
|
||||
r_ogl_os_window_unequip(OS_Handle os, R_Handle r)
|
||||
r_ogl_os_window_unequip(OS_Window os, R_Handle r)
|
||||
{
|
||||
}
|
||||
|
||||
internal void
|
||||
r_ogl_os_select_window(OS_Handle os, R_Handle r)
|
||||
r_ogl_os_select_window(OS_Window os, R_Handle r)
|
||||
{
|
||||
OS_W32_Window *w = os_w32_window_from_handle(os);
|
||||
if(w != 0)
|
||||
@@ -172,7 +172,7 @@ r_ogl_os_select_window(OS_Handle os, R_Handle r)
|
||||
}
|
||||
|
||||
internal void
|
||||
r_ogl_os_window_swap(OS_Handle os, R_Handle r)
|
||||
r_ogl_os_window_swap(OS_Window os, R_Handle r)
|
||||
{
|
||||
OS_W32_Window *w = os_w32_window_from_handle(os);
|
||||
if(w != 0)
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
//- rjf: [h]
|
||||
#include "base/base_inc.h"
|
||||
#include "os/os_inc.h"
|
||||
#include "content/content.h"
|
||||
#include "artifact_cache/artifact_cache.h"
|
||||
#include "file_stream/file_stream.h"
|
||||
@@ -21,7 +20,6 @@
|
||||
|
||||
//- rjf: [c]
|
||||
#include "base/base_inc.c"
|
||||
#include "os/os_inc.c"
|
||||
#include "content/content.c"
|
||||
#include "artifact_cache/artifact_cache.c"
|
||||
#include "file_stream/file_stream.c"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
//- rjf: [h]
|
||||
#include "base/base_inc.h"
|
||||
#include "os/os_inc.h"
|
||||
#include "render/render_inc.h"
|
||||
#include "font_provider/font_provider_inc.h"
|
||||
#include "font_cache/font_cache.h"
|
||||
@@ -20,7 +19,6 @@
|
||||
|
||||
//- rjf: [c]
|
||||
#include "base/base_inc.c"
|
||||
#include "os/os_inc.c"
|
||||
#include "render/render_inc.c"
|
||||
#include "font_provider/font_provider_inc.c"
|
||||
#include "font_cache/font_cache.c"
|
||||
|
||||
+4
-21
@@ -69,6 +69,7 @@ stap_list_from_string(Arena *arena, String8 string)
|
||||
internal String8
|
||||
stap_parse_args_x64(String8 string, STAP_Arg *arg_out)
|
||||
{
|
||||
ARCH_Info *arch_info = arch_info_from_arch(Arch_x64);
|
||||
String8 error = str8_lit("unknown parse error");
|
||||
U64 sep_pos = str8_find_needle(string, 0, str8_lit("@"), 0);
|
||||
if (sep_pos < string.size) {
|
||||
@@ -200,14 +201,9 @@ stap_parse_args_x64(String8 string, STAP_Arg *arg_out)
|
||||
index_str = str8_skip(index_str, 1);
|
||||
|
||||
// parse base
|
||||
B8 base_is_alias = 0;
|
||||
U32 base_reg_code = 0;
|
||||
if (base_str.size) {
|
||||
base_reg_code = regs_reg_code_from_name(Arch_x64, base_str);
|
||||
if (base_reg_code == 0) {
|
||||
base_reg_code = regs_alias_code_from_name(Arch_x64, base_str);
|
||||
base_is_alias = base_reg_code != 0;
|
||||
}
|
||||
base_reg_code = arch_reg_code_from_name(arch_info, base_str);
|
||||
if (base_reg_code == 0) {
|
||||
error = str8_lit("unknown base register");
|
||||
goto operand_parse_exit;
|
||||
@@ -215,14 +211,9 @@ stap_parse_args_x64(String8 string, STAP_Arg *arg_out)
|
||||
}
|
||||
|
||||
// parse index
|
||||
B8 index_is_alias = 0;
|
||||
U32 index_reg_code = 0;
|
||||
if (index_str.size) {
|
||||
index_reg_code = regs_reg_code_from_name(Arch_x64, index_str);
|
||||
if (index_reg_code == 0) {
|
||||
index_reg_code = regs_alias_code_from_name(Arch_x64, index_str);
|
||||
index_is_alias = index_reg_code != 0;
|
||||
}
|
||||
index_reg_code = arch_reg_code_from_name(arch_info, index_str);
|
||||
if (index_reg_code == 0) {
|
||||
error = str8_lit("unknown index register");
|
||||
}
|
||||
@@ -247,9 +238,7 @@ stap_parse_args_x64(String8 string, STAP_Arg *arg_out)
|
||||
arg.type = STAP_ArgType_MemoryRef;
|
||||
arg.memory_ref.disp = disp;
|
||||
arg.memory_ref.base.reg_code = base_reg_code;
|
||||
arg.memory_ref.base.is_alias = base_is_alias;
|
||||
arg.memory_ref.index.reg_code = index_reg_code;
|
||||
arg.memory_ref.index.is_alias = index_is_alias;
|
||||
arg.memory_ref.scale = scale;
|
||||
}
|
||||
// $imm
|
||||
@@ -296,19 +285,13 @@ stap_parse_args_x64(String8 string, STAP_Arg *arg_out)
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
|
||||
B8 is_reg_alias = 0;
|
||||
U32 reg_code = regs_reg_code_from_name(Arch_x64, reg_str);
|
||||
if (reg_code == 0) {
|
||||
reg_code = regs_alias_code_from_name(Arch_x64, reg_str);
|
||||
is_reg_alias = reg_code != 0;
|
||||
}
|
||||
U32 reg_code = arch_reg_code_from_name(arch_info, reg_str);
|
||||
if (reg_code == 0) {
|
||||
error = str8_lit("invalid register name");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
|
||||
arg.type = STAP_ArgType_Reg;
|
||||
arg.reg.is_alias = is_reg_alias;
|
||||
arg.reg.reg_code = reg_code;
|
||||
} else {
|
||||
goto operand_parse_exit;
|
||||
|
||||
@@ -29,17 +29,14 @@ typedef struct STAP_Arg
|
||||
U64 imm;
|
||||
struct {
|
||||
U32 reg_code;
|
||||
B8 is_alias;
|
||||
} reg;
|
||||
struct {
|
||||
S64 disp;
|
||||
struct {
|
||||
U32 reg_code;
|
||||
B8 is_alias;
|
||||
} base;
|
||||
struct {
|
||||
U32 reg_code;
|
||||
B8 is_alias;
|
||||
} index;
|
||||
U64 scale;
|
||||
} memory_ref;
|
||||
|
||||
@@ -5,12 +5,10 @@
|
||||
#define BUILD_CONSOLE_INTERFACE 1
|
||||
|
||||
#include "base/base_inc.h"
|
||||
#include "os/os_inc.h"
|
||||
#include "arch/arch_inc.h"
|
||||
#include "stap/stap_parse.h"
|
||||
|
||||
#include "base/base_inc.c"
|
||||
#include "os/os_inc.c"
|
||||
#include "arch/arch_inc.c"
|
||||
#include "stap/stap_parse.c"
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
// Headers
|
||||
|
||||
#include "base/base_inc.h"
|
||||
#include "os/os_inc.h"
|
||||
#include "coff/coff.h"
|
||||
#include "coff/coff_parse.h"
|
||||
|
||||
@@ -16,7 +15,6 @@
|
||||
// Implementations
|
||||
|
||||
#include "base/base_inc.c"
|
||||
#include "os/os_inc.c"
|
||||
#include "coff/coff.c"
|
||||
#include "coff/coff_parse.c"
|
||||
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
#include "linker/hash_table.h"
|
||||
#include "linker/lf_hash_table.h"
|
||||
#include "linker/base_ext/base_bit_array.h"
|
||||
#include "os/os_inc.h"
|
||||
#include "artifact_cache/artifact_cache.h"
|
||||
#include "rdi/rdi_local.h"
|
||||
#include "rdi_make/rdi_make_local.h"
|
||||
#include "mdesk/mdesk.h"
|
||||
#include "window_manager/window_manager_inc.h"
|
||||
#include "config/config_inc.h"
|
||||
#include "content/content.h"
|
||||
#include "file_stream/file_stream.h"
|
||||
@@ -98,11 +98,11 @@
|
||||
#include "linker/hash_table.c"
|
||||
#include "linker/lf_hash_table.c"
|
||||
#include "linker/base_ext/base_bit_array.c"
|
||||
#include "os/os_inc.c"
|
||||
#include "artifact_cache/artifact_cache.c"
|
||||
#include "rdi/rdi_local.c"
|
||||
#include "rdi_make/rdi_make_local.c"
|
||||
#include "mdesk/mdesk.c"
|
||||
#include "window_manager/window_manager_inc.c"
|
||||
#include "config/config_inc.c"
|
||||
#include "content/content.c"
|
||||
#include "file_stream/file_stream.c"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef OS_GFX_WIN32_H
|
||||
#define OS_GFX_WIN32_H
|
||||
#ifndef WIN32_WINDOW_MANAGER_H
|
||||
#define WIN32_WINDOW_MANAGER_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Includes / Libraries
|
||||
@@ -120,4 +120,4 @@ internal LRESULT os_w32_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LP
|
||||
|
||||
internal BOOL os_w32_monitor_gather_enum_proc(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM bundle_ptr);
|
||||
|
||||
#endif // OS_GFX_WIN32_H
|
||||
#endif // WIN32_WINDOW_MANAGER_H
|
||||
+3
-3
@@ -3,8 +3,8 @@
|
||||
|
||||
//- GENERATED CODE
|
||||
|
||||
#ifndef OS_GFX_META_H
|
||||
#define OS_GFX_META_H
|
||||
#ifndef WINDOW_MANAGER_META_H
|
||||
#define WINDOW_MANAGER_META_H
|
||||
|
||||
typedef enum OS_Key
|
||||
{
|
||||
@@ -160,4 +160,4 @@ extern String8 os_g_key_cfg_string_table[143];
|
||||
|
||||
C_LINKAGE_END
|
||||
|
||||
#endif // OS_GFX_META_H
|
||||
#endif // WINDOW_MANAGER_META_H
|
||||
@@ -4,7 +4,7 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: Generated Code
|
||||
|
||||
#include "generated/os_gfx.meta.c"
|
||||
#include "window_manager/generated/window_manager.meta.c"
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type Helpers
|
||||
@@ -77,7 +77,7 @@ OS_Cursor;
|
||||
////////////////////////////////
|
||||
//~ rjf: Generated Code
|
||||
|
||||
#include "os/gfx/generated/os_gfx.meta.h"
|
||||
#include "window_manager/generated/window_manager.meta.h"
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Event Types
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#include "window_manager.c"
|
||||
#if WM_STUB
|
||||
# include "window_manager_stub.c"
|
||||
#elif OS_WINDOWS
|
||||
# include "win32/window_manager/win32_window_manager.c"
|
||||
#elif OS_LINUX
|
||||
# include "linux/window_manager/linux_window_manager.c"
|
||||
#else
|
||||
# error Window manager layer not implemented for this operating system.
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef WINDOW_MANAGER_INC_H
|
||||
#define WINDOW_MANAGER_INC_H
|
||||
|
||||
#include "window_manager.h"
|
||||
#if WM_STUB
|
||||
# include "window_manager_stub.h"
|
||||
#elif OS_WINDOWS
|
||||
# include "win32/window_manager/win32_window_manager.h"
|
||||
#elif OS_LINUX
|
||||
# include "linux/window_manager/linux_window_manager.h"
|
||||
#else
|
||||
# error Window manager layer not implemented for this operating system.
|
||||
#endif
|
||||
|
||||
#endif // WINDOW_MANAGER_INC_H
|
||||
+23
-15
@@ -34,7 +34,8 @@ enum
|
||||
////////////////////////////////
|
||||
//~ fxsave/xsave
|
||||
|
||||
typedef struct AlignType(16) X64_FXSave
|
||||
typedef struct X64_FXSave X64_FXSave;
|
||||
struct AlignType(16) X64_FXSave
|
||||
{
|
||||
U16 fcw;
|
||||
U16 fsw;
|
||||
@@ -48,23 +49,25 @@ typedef struct AlignType(16) X64_FXSave
|
||||
U128 st_space[8];
|
||||
U128 xmm_space[16];
|
||||
U8 padding[96];
|
||||
} X64_FXSave;
|
||||
};
|
||||
StaticAssert(sizeof(X64_FXSave) == 512, g_x64_xsave_legacy_size_check);
|
||||
|
||||
typedef struct X64_XSaveHeader
|
||||
typedef struct X64_XSaveHeader X64_XSaveHeader;
|
||||
struct X64_XSaveHeader
|
||||
{
|
||||
U64 xstate_bv;
|
||||
U64 xcomp_bv;
|
||||
U8 reserved[48];
|
||||
} X64_XSaveHeader;
|
||||
};
|
||||
StaticAssert(sizeof(X64_XSaveHeader) == 64, g_x64_xsave_header_size_check);
|
||||
|
||||
typedef struct AlignType(64) X64_XSave
|
||||
typedef struct X64_XSave X64_XSave;
|
||||
struct AlignType(64) X64_XSave
|
||||
{
|
||||
X64_FXSave fxsave;
|
||||
X64_XSaveHeader header;
|
||||
// U8 ext_area[0];
|
||||
} X64_XSave;
|
||||
};
|
||||
StaticAssert(sizeof(X64_XSave) == 576, g_x64_xsave_size_check);
|
||||
|
||||
typedef U32 X64_XStateComponentIdx;
|
||||
@@ -90,7 +93,6 @@ enum
|
||||
X64_XStateComponentIdx_TILECFG = 17,
|
||||
X64_XStateComponentIdx_TILEDATA = 18,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
X64_XStateComponentFlag_FP = (1 << X64_XStateComponentIdx_FP),
|
||||
@@ -114,7 +116,8 @@ enum
|
||||
X64_XStateComponentFlag_TILEDATA = (1 << X64_XStateComponentIdx_TILEDATA),
|
||||
};
|
||||
|
||||
typedef struct
|
||||
typedef struct X64_XSaveLayout X64_XSaveLayout;
|
||||
struct X64_XSaveLayout
|
||||
{
|
||||
U64 x87_offset;
|
||||
U64 sse_offset;
|
||||
@@ -135,12 +138,12 @@ typedef struct
|
||||
U64 hwp_offset;
|
||||
U64 tile_cfg_offset;
|
||||
U64 tile_data_offset;
|
||||
} X64_XSaveLayout;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Debug Status Register
|
||||
|
||||
typedef enum
|
||||
typedef enum X64_DebugStatusFlags
|
||||
{
|
||||
X64_DebugStatusFlag_B0 = (1 << 0),
|
||||
X64_DebugStatusFlag_B1 = (1 << 1),
|
||||
@@ -151,16 +154,19 @@ typedef enum
|
||||
X64_DebugStatusFlag_SingleStep = (1 << 14),
|
||||
X64_DebugStatusFlag_TaskSwitch = (1 << 15),
|
||||
X64_DebugStatusFlag_RTM = (1 << 16),
|
||||
} X64_DebugStatusFlags;
|
||||
}
|
||||
X64_DebugStatusFlags;
|
||||
|
||||
////////////////////////////////
|
||||
//~ Debug Control Register
|
||||
|
||||
typedef enum X64_BreakpointType {
|
||||
typedef enum X64_BreakpointType
|
||||
{
|
||||
X64_BreakpointType_Null,
|
||||
X64_BreakpointType_Local,
|
||||
X64_BreakpointType_Global,
|
||||
} X64_BreakpointType;
|
||||
}
|
||||
X64_BreakpointType;
|
||||
|
||||
typedef enum X64_DebugBreakType
|
||||
{
|
||||
@@ -169,7 +175,8 @@ typedef enum X64_DebugBreakType
|
||||
X64_DebugBreakType_Write,
|
||||
X64_DebugBreakType_ReadWriteIO,
|
||||
X64_DebugBreakType_ReadWriteNoFetch,
|
||||
} X64_DebugBreakType;
|
||||
}
|
||||
X64_DebugBreakType;
|
||||
|
||||
typedef enum X64_DebugControlFlags
|
||||
{
|
||||
@@ -199,7 +206,8 @@ typedef enum X64_DebugControlFlags
|
||||
X64_DebugControlFlag_LEN1 = (3 << 22),
|
||||
X64_DebugControlFlag_LEN2 = (3 << 26),
|
||||
X64_DebugControlFlag_LEN3 = (3 << 30),
|
||||
} X64_DebugControlFlags;
|
||||
}
|
||||
X64_DebugControlFlags;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Generated
|
||||
|
||||
Reference in New Issue
Block a user