mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-16 09:02:22 -07:00
initial upload
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Tables
|
||||
|
||||
@table(name lower_name code default display_string)
|
||||
CTRL_ExceptionCodeKindTable:
|
||||
{
|
||||
{Win32CtrlC win32_ctrl_c 0x40010005 1 "(Win32) Control-C" }
|
||||
{Win32CtrlBreak win32_ctrl_break 0x40010008 1 "(Win32) Control-Break" }
|
||||
{Win32WinRTOriginateError win32_win_rt_originate_error 0x40080201 0 "(Win32) WinRT Originate Error" }
|
||||
{Win32WinRTTransformError win32_win_rt_transform_error 0x40080202 0 "(Win32) WinRT Transform Error" }
|
||||
{Win32RPCCallCancelled win32_rpc_call_cancelled 0x0000071a 0 "(Win32) RPC Call Cancelled" }
|
||||
{Win32DatatypeMisalignment win32_datatype_misalignment 0x80000002 0 "(Win32) Data Type Misalignment" }
|
||||
{Win32AccessViolation win32_access_violation 0xc0000005 1 "(Win32) Access Violation" }
|
||||
{Win32InPageError win32_in_page_error 0xc0000006 0 "(Win32) In Page Error" }
|
||||
{Win32InvalidHandle win32_invalid_handle 0xc0000008 1 "(Win32) Invalid Handle Specified" }
|
||||
{Win32NotEnoughQuota win32_not_enough_quota 0xc0000017 0 "(Win32) Not Enough Quota" }
|
||||
{Win32IllegalInstruction win32_illegal_instruction 0xc000001d 0 "(Win32) Illegal Instruction" }
|
||||
{Win32CannotContinueException win32_cannot_continue_exception 0xc0000025 0 "(Win32) Cannot Continue From Exception" }
|
||||
{Win32InvalidExceptionDisposition win32_invalid_exception_disposition 0xc0000026 0 "(Win32) Invalid Exception Disposition Returned By Handler" }
|
||||
{Win32ArrayBoundsExceeded win32_array_bounds_exceeded 0xc000008c 0 "(Win32) Array Bounds Exceeded" }
|
||||
{Win32FloatingPointDenormalOperand win32_floating_point_denormal_operand 0xc000008d 0 "(Win32) Floating-Point Denormal Operand" }
|
||||
{Win32FloatingPointDivisionByZero win32_floating_point_division_by_zero 0xc000008e 0 "(Win32) Floating-Point Division By Zero" }
|
||||
{Win32FloatingPointInexactResult win32_floating_point_inexact_result 0xc000008f 0 "(Win32) Floating-Point Inexact Result" }
|
||||
{Win32FloatingPointInvalidOperation win32_floating_point_invalid_operation 0xc0000090 0 "(Win32) Floating-Point Invalid Operation" }
|
||||
{Win32FloatingPointOverflow win32_floating_point_overflow 0xc0000091 0 "(Win32) Floating-Point Overflow" }
|
||||
{Win32FloatingPointStackCheck win32_floating_point_stack_check 0xc0000092 0 "(Win32) Floating-Point Stack Check" }
|
||||
{Win32FloatingPointUnderflow win32_floating_point_underflow 0xc0000093 0 "(Win32) Floating-Point Underflow" }
|
||||
{Win32IntegerDivisionByZero win32_integer_division_by_zero 0xc0000094 0 "(Win32) Integer Division By Zero" }
|
||||
{Win32IntegerOverflow win32_integer_overflow 0xc0000095 0 "(Win32) Integer Overflow" }
|
||||
{Win32PrivilegedInstruction win32_privileged_instruction 0xc0000096 0 "(Win32) Privileged Instruction" }
|
||||
{Win32StackOverflow win32_stack_overflow 0xc00000fd 0 "(Win32) Stack Overflow" }
|
||||
{Win32UnableToLocateDLL win32_unable_to_locate_dll 0xc0000135 0 "(Win32) Unable To Locate DLL" }
|
||||
{Win32OrdinalNotFound win32_ordinal_not_found 0xc0000138 0 "(Win32) Ordinal Not Found" }
|
||||
{Win32EntryPointNotFound win32_entry_point_not_found 0xc0000139 0 "(Win32) Entry Point Not Found" }
|
||||
{Win32DLLInitializationFailed win32_dll_initialization_failed 0xc0000142 0 "(Win32) DLL Initialization Failed" }
|
||||
{Win32FloatingPointSSEMultipleFaults win32_floating_point_sse_multiple_faults 0xc00002b4 0 "(Win32) Floating Point SSE Multiple Faults" }
|
||||
{Win32FloatingPointSSEMultipleTraps win32_floating_point_sse_multiple_traps 0xc00002b5 0 "(Win32) Floating Point SSE Multiple Traps" }
|
||||
{Win32AssertionFailed win32_assertion_failed 0xc0000420 1 "(Win32) Assertion Failed" }
|
||||
{Win32ModuleNotFound win32_module_not_found 0xc06d007e 0 "(Win32) Module Not Found" }
|
||||
{Win32ProcedureNotFound win32_procedure_not_found 0xc06d007f 0 "(Win32) Procedure Not Found" }
|
||||
{Win32SanitizerErrorDetected win32_sanitizer_error_detected 0xe073616e 1 "(Win32) Sanitizer Error Detected" }
|
||||
{Win32SanitizerRawAccessViolation win32_sanitizer_raw_access_violation 0xe0736171 0 "(Win32) Sanitizer Raw Access Violation" }
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Generators
|
||||
|
||||
@table_gen_enum CTRL_ExceptionCodeKind:
|
||||
{
|
||||
`CTRL_ExceptionCodeKind_Null,`;
|
||||
@expand(CTRL_ExceptionCodeKindTable a) `CTRL_ExceptionCodeKind_$(a.name),`;
|
||||
`CTRL_ExceptionCodeKind_COUNT`;
|
||||
}
|
||||
|
||||
@table_gen_data(type:U32, fallback:0)
|
||||
ctrl_exception_code_kind_code_table:
|
||||
{
|
||||
`0,`;
|
||||
@expand(CTRL_ExceptionCodeKindTable a) `$(a.code),`;
|
||||
}
|
||||
|
||||
@table_gen_data(type:String8, fallback:`{0}`)
|
||||
ctrl_exception_code_kind_display_string_table:
|
||||
{
|
||||
`{0},`;
|
||||
@expand(CTRL_ExceptionCodeKindTable a) `str8_lit_comp("$(a.display_string)"),`;
|
||||
}
|
||||
|
||||
@table_gen_data(type:String8, fallback:`{0}`)
|
||||
ctrl_exception_code_kind_lowercase_code_string_table:
|
||||
{
|
||||
`{0},`;
|
||||
@expand(CTRL_ExceptionCodeKindTable a) `str8_lit_comp("$(a.lower_name)"),`;
|
||||
}
|
||||
|
||||
@table_gen_data(type:B8, fallback:0)
|
||||
ctrl_exception_code_kind_default_enable_table:
|
||||
{
|
||||
`0,`;
|
||||
@expand(CTRL_ExceptionCodeKindTable a) `$(a.default),`;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,601 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef CTRL_CORE_H
|
||||
#define CTRL_CORE_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: ID Types
|
||||
|
||||
typedef U64 CTRL_MsgID;
|
||||
typedef U64 CTRL_MachineID;
|
||||
|
||||
#define CTRL_MachineID_Client (1)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Handle Type
|
||||
|
||||
typedef struct CTRL_Handle CTRL_Handle;
|
||||
struct CTRL_Handle
|
||||
{
|
||||
U64 u64[1];
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Machine/Handle Pair Types
|
||||
|
||||
typedef struct CTRL_MachineIDHandlePair CTRL_MachineIDHandlePair;
|
||||
struct CTRL_MachineIDHandlePair
|
||||
{
|
||||
CTRL_MachineID machine_id;
|
||||
CTRL_Handle handle;
|
||||
};
|
||||
|
||||
typedef struct CTRL_MachineIDHandlePairNode CTRL_MachineIDHandlePairNode;
|
||||
struct CTRL_MachineIDHandlePairNode
|
||||
{
|
||||
CTRL_MachineIDHandlePairNode *next;
|
||||
CTRL_MachineIDHandlePair v;
|
||||
};
|
||||
|
||||
typedef struct CTRL_MachineIDHandlePairList CTRL_MachineIDHandlePairList;
|
||||
struct CTRL_MachineIDHandlePairList
|
||||
{
|
||||
CTRL_MachineIDHandlePairNode *first;
|
||||
CTRL_MachineIDHandlePairNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Trap Types
|
||||
|
||||
typedef U32 CTRL_TrapFlags;
|
||||
enum
|
||||
{
|
||||
CTRL_TrapFlag_IgnoreStackPointerCheck = (1<<0),
|
||||
CTRL_TrapFlag_SingleStepAfterHit = (1<<1),
|
||||
CTRL_TrapFlag_SaveStackPointer = (1<<2),
|
||||
CTRL_TrapFlag_BeginSpoofMode = (1<<3),
|
||||
CTRL_TrapFlag_EndStepping = (1<<4),
|
||||
};
|
||||
|
||||
typedef struct CTRL_Trap CTRL_Trap;
|
||||
struct CTRL_Trap
|
||||
{
|
||||
CTRL_TrapFlags flags;
|
||||
U64 vaddr;
|
||||
};
|
||||
|
||||
typedef struct CTRL_TrapNode CTRL_TrapNode;
|
||||
struct CTRL_TrapNode
|
||||
{
|
||||
CTRL_TrapNode *next;
|
||||
CTRL_Trap v;
|
||||
};
|
||||
|
||||
typedef struct CTRL_TrapList CTRL_TrapList;
|
||||
struct CTRL_TrapList
|
||||
{
|
||||
CTRL_TrapNode *first;
|
||||
CTRL_TrapNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct CTRL_Spoof CTRL_Spoof;
|
||||
struct CTRL_Spoof
|
||||
{
|
||||
CTRL_Handle process;
|
||||
U64 vaddr;
|
||||
U64 new_ip_value;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: User Breakpoint Types
|
||||
|
||||
typedef enum CTRL_UserBreakpointKind
|
||||
{
|
||||
CTRL_UserBreakpointKind_FileNameAndLineColNumber,
|
||||
CTRL_UserBreakpointKind_SymbolNameAndOffset,
|
||||
CTRL_UserBreakpointKind_VirtualAddress,
|
||||
CTRL_UserBreakpointKind_COUNT
|
||||
}
|
||||
CTRL_UserBreakpointKind;
|
||||
|
||||
typedef struct CTRL_UserBreakpoint CTRL_UserBreakpoint;
|
||||
struct CTRL_UserBreakpoint
|
||||
{
|
||||
CTRL_UserBreakpointKind kind;
|
||||
String8 string;
|
||||
TxtPt pt;
|
||||
U64 u64;
|
||||
String8 condition;
|
||||
};
|
||||
|
||||
typedef struct CTRL_UserBreakpointNode CTRL_UserBreakpointNode;
|
||||
struct CTRL_UserBreakpointNode
|
||||
{
|
||||
CTRL_UserBreakpointNode *next;
|
||||
CTRL_UserBreakpoint v;
|
||||
};
|
||||
|
||||
typedef struct CTRL_UserBreakpointList CTRL_UserBreakpointList;
|
||||
struct CTRL_UserBreakpointList
|
||||
{
|
||||
CTRL_UserBreakpointNode *first;
|
||||
CTRL_UserBreakpointNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Generated Code
|
||||
|
||||
#include "generated/ctrl.meta.h"
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Message Types
|
||||
|
||||
typedef enum CTRL_MsgKind
|
||||
{
|
||||
CTRL_MsgKind_Null,
|
||||
CTRL_MsgKind_LaunchAndHandshake,
|
||||
CTRL_MsgKind_LaunchAndInit,
|
||||
CTRL_MsgKind_Attach,
|
||||
CTRL_MsgKind_Kill,
|
||||
CTRL_MsgKind_Detach,
|
||||
CTRL_MsgKind_Run,
|
||||
CTRL_MsgKind_SingleStep,
|
||||
CTRL_MsgKind_SetUserEntryPoints,
|
||||
CTRL_MsgKind_COUNT,
|
||||
}
|
||||
CTRL_MsgKind;
|
||||
|
||||
typedef struct CTRL_Msg CTRL_Msg;
|
||||
struct CTRL_Msg
|
||||
{
|
||||
CTRL_MsgKind kind;
|
||||
CTRL_MsgID msg_id;
|
||||
CTRL_MachineID machine_id;
|
||||
CTRL_Handle entity;
|
||||
CTRL_Handle parent;
|
||||
U32 entity_id;
|
||||
U32 exit_code;
|
||||
B32 env_inherit;
|
||||
U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64];
|
||||
String8 path;
|
||||
String8List strings;
|
||||
String8List cmd_line_string_list;
|
||||
String8List env_string_list;
|
||||
CTRL_TrapList traps;
|
||||
CTRL_UserBreakpointList user_bps;
|
||||
CTRL_MachineIDHandlePairList freeze_state_threads; // NOTE(rjf): can be frozen or unfrozen, depending on `freeze_state_is_frozen`
|
||||
B32 freeze_state_is_frozen;
|
||||
};
|
||||
|
||||
typedef struct CTRL_MsgNode CTRL_MsgNode;
|
||||
struct CTRL_MsgNode
|
||||
{
|
||||
CTRL_MsgNode *next;
|
||||
CTRL_Msg v;
|
||||
};
|
||||
|
||||
typedef struct CTRL_MsgList CTRL_MsgList;
|
||||
struct CTRL_MsgList
|
||||
{
|
||||
CTRL_MsgNode *first;
|
||||
CTRL_MsgNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Event Types
|
||||
|
||||
typedef enum CTRL_EventKind
|
||||
{
|
||||
CTRL_EventKind_Null,
|
||||
CTRL_EventKind_Error,
|
||||
|
||||
//- rjf: starts/stops
|
||||
CTRL_EventKind_Started,
|
||||
CTRL_EventKind_Stopped,
|
||||
|
||||
//- rjf: entity creation/deletion
|
||||
CTRL_EventKind_NewProc,
|
||||
CTRL_EventKind_NewThread,
|
||||
CTRL_EventKind_NewModule,
|
||||
CTRL_EventKind_EndProc,
|
||||
CTRL_EventKind_EndThread,
|
||||
CTRL_EventKind_EndModule,
|
||||
|
||||
//- rjf: debug strings
|
||||
CTRL_EventKind_DebugString,
|
||||
CTRL_EventKind_ThreadName,
|
||||
|
||||
//- rjf: memory
|
||||
CTRL_EventKind_MemReserve,
|
||||
CTRL_EventKind_MemCommit,
|
||||
CTRL_EventKind_MemDecommit,
|
||||
CTRL_EventKind_MemRelease,
|
||||
|
||||
//- rjf: ctrl requests
|
||||
CTRL_EventKind_LaunchAndHandshakeDone,
|
||||
CTRL_EventKind_LaunchAndInitDone,
|
||||
CTRL_EventKind_AttachDone,
|
||||
CTRL_EventKind_KillDone,
|
||||
CTRL_EventKind_DetachDone,
|
||||
|
||||
CTRL_EventKind_COUNT
|
||||
}
|
||||
CTRL_EventKind;
|
||||
|
||||
typedef enum CTRL_EventCause
|
||||
{
|
||||
CTRL_EventCause_Null,
|
||||
CTRL_EventCause_Error,
|
||||
CTRL_EventCause_Finished,
|
||||
CTRL_EventCause_UserBreakpoint,
|
||||
CTRL_EventCause_InterruptedByTrap,
|
||||
CTRL_EventCause_InterruptedByException,
|
||||
CTRL_EventCause_InterruptedByHalt,
|
||||
CTRL_EventCause_COUNT
|
||||
}
|
||||
CTRL_EventCause;
|
||||
|
||||
typedef enum CTRL_ExceptionKind
|
||||
{
|
||||
CTRL_ExceptionKind_Null,
|
||||
CTRL_ExceptionKind_MemoryRead,
|
||||
CTRL_ExceptionKind_MemoryWrite,
|
||||
CTRL_ExceptionKind_MemoryExecute,
|
||||
CTRL_ExceptionKind_CppThrow,
|
||||
CTRL_ExceptionKind_COUNT
|
||||
}
|
||||
CTRL_ExceptionKind;
|
||||
|
||||
typedef struct CTRL_Event CTRL_Event;
|
||||
struct CTRL_Event
|
||||
{
|
||||
CTRL_EventKind kind;
|
||||
CTRL_EventCause cause;
|
||||
CTRL_ExceptionKind exception_kind;
|
||||
CTRL_MsgID msg_id;
|
||||
CTRL_MachineID machine_id;
|
||||
CTRL_Handle entity;
|
||||
CTRL_Handle parent;
|
||||
Architecture arch;
|
||||
U64 u64_code;
|
||||
U32 entity_id;
|
||||
Rng1U64 vaddr_rng;
|
||||
U64 rip_vaddr;
|
||||
U64 stack_base;
|
||||
U64 tls_root;
|
||||
U32 exception_code;
|
||||
String8 string;
|
||||
};
|
||||
|
||||
typedef struct CTRL_EventNode CTRL_EventNode;
|
||||
struct CTRL_EventNode
|
||||
{
|
||||
CTRL_EventNode *next;
|
||||
CTRL_Event v;
|
||||
};
|
||||
|
||||
typedef struct CTRL_EventList CTRL_EventList;
|
||||
struct CTRL_EventList
|
||||
{
|
||||
CTRL_EventNode *first;
|
||||
CTRL_EventNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Process Memory Cache Types
|
||||
|
||||
// NOTE(rjf):
|
||||
//
|
||||
// Process memory is cached with a 5-level page table. Each level has 256
|
||||
// slots, and is indexed into with 8 bits. Each index is extracted from a
|
||||
// virtual address in the following manner:
|
||||
//
|
||||
// |1------||2------||3------||4------||5------||byte-n-page|
|
||||
// xxxxxxxx xxxx0000 00000000 00000000 00000000 00000000 0000xxxx xxxxxxxx
|
||||
//
|
||||
// The top 12 bits are not used (a 52-bit address space is supported at most).
|
||||
// The next 8 most-significant-bits are used to index into the level 1 table.
|
||||
// The next 8 are used to index into the level 2. Then the level 3. Then the
|
||||
// level 4. At the level 4 table, instead of pointing to other tables, each
|
||||
// slot points at the base address of a cached 4KB page. The next 8 bits are
|
||||
// used to index into that table. The final 12 bits in the address are used
|
||||
// to refer to unique bytes within each page.
|
||||
|
||||
typedef struct CTRL_ProcessMemoryCacheNode4 CTRL_ProcessMemoryCacheNode4;
|
||||
struct CTRL_ProcessMemoryCacheNode4
|
||||
{
|
||||
U64 page_memgen_idxs[256];
|
||||
U128 page_hashes[256];
|
||||
};
|
||||
|
||||
typedef struct CTRL_ProcessMemoryCacheNode3 CTRL_ProcessMemoryCacheNode3;
|
||||
struct CTRL_ProcessMemoryCacheNode3
|
||||
{
|
||||
CTRL_ProcessMemoryCacheNode4 *children[256];
|
||||
};
|
||||
|
||||
typedef struct CTRL_ProcessMemoryCacheNode2 CTRL_ProcessMemoryCacheNode2;
|
||||
struct CTRL_ProcessMemoryCacheNode2
|
||||
{
|
||||
CTRL_ProcessMemoryCacheNode3 *children[256];
|
||||
};
|
||||
|
||||
typedef struct CTRL_ProcessMemoryCacheNode1 CTRL_ProcessMemoryCacheNode1;
|
||||
struct CTRL_ProcessMemoryCacheNode1
|
||||
{
|
||||
CTRL_ProcessMemoryCacheNode2 *children[256];
|
||||
};
|
||||
|
||||
typedef struct CTRL_ProcessMemoryRangeHashNode CTRL_ProcessMemoryRangeHashNode;
|
||||
struct CTRL_ProcessMemoryRangeHashNode
|
||||
{
|
||||
CTRL_ProcessMemoryRangeHashNode *next;
|
||||
Rng1U64 vaddr_range;
|
||||
B32 zero_terminated;
|
||||
U128 hash;
|
||||
U64 memgen_idx;
|
||||
B32 is_taken;
|
||||
};
|
||||
|
||||
typedef struct CTRL_ProcessMemoryRangeHashSlot CTRL_ProcessMemoryRangeHashSlot;
|
||||
struct CTRL_ProcessMemoryRangeHashSlot
|
||||
{
|
||||
CTRL_ProcessMemoryRangeHashNode *first;
|
||||
CTRL_ProcessMemoryRangeHashNode *last;
|
||||
};
|
||||
|
||||
typedef struct CTRL_ProcessMemoryCacheNode CTRL_ProcessMemoryCacheNode;
|
||||
struct CTRL_ProcessMemoryCacheNode
|
||||
{
|
||||
CTRL_ProcessMemoryCacheNode *next;
|
||||
CTRL_ProcessMemoryCacheNode *prev;
|
||||
Arena *arena;
|
||||
CTRL_MachineID machine_id;
|
||||
CTRL_Handle process;
|
||||
CTRL_ProcessMemoryCacheNode1 *children[256];
|
||||
U64 range_hash_slots_count;
|
||||
CTRL_ProcessMemoryRangeHashSlot *range_hash_slots;
|
||||
};
|
||||
|
||||
typedef struct CTRL_ProcessMemoryCacheSlot CTRL_ProcessMemoryCacheSlot;
|
||||
struct CTRL_ProcessMemoryCacheSlot
|
||||
{
|
||||
CTRL_ProcessMemoryCacheNode *first;
|
||||
CTRL_ProcessMemoryCacheNode *last;
|
||||
};
|
||||
|
||||
typedef struct CTRL_ProcessMemoryCacheStripe CTRL_ProcessMemoryCacheStripe;
|
||||
struct CTRL_ProcessMemoryCacheStripe
|
||||
{
|
||||
OS_Handle rw_mutex;
|
||||
};
|
||||
|
||||
typedef struct CTRL_ProcessMemoryCache CTRL_ProcessMemoryCache;
|
||||
struct CTRL_ProcessMemoryCache
|
||||
{
|
||||
U64 slots_count;
|
||||
CTRL_ProcessMemoryCacheSlot *slots;
|
||||
U64 stripes_count;
|
||||
CTRL_ProcessMemoryCacheStripe *stripes;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Wakeup Hook Function Types
|
||||
|
||||
#define CTRL_WAKEUP_FUNCTION_DEF(name) void name(void)
|
||||
typedef CTRL_WAKEUP_FUNCTION_DEF(CTRL_WakeupFunctionType);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Main State Types
|
||||
|
||||
typedef struct CTRL_State CTRL_State;
|
||||
struct CTRL_State
|
||||
{
|
||||
Arena *arena;
|
||||
CTRL_WakeupFunctionType *wakeup_hook;
|
||||
U64 run_idx;
|
||||
U64 memgen_idx;
|
||||
|
||||
// rjf: name -> register/alias hash tables for eval
|
||||
EVAL_String2NumMap arch_string2reg_tables[Architecture_COUNT];
|
||||
EVAL_String2NumMap arch_string2alias_tables[Architecture_COUNT];
|
||||
|
||||
// rjf: process memory cache
|
||||
CTRL_ProcessMemoryCache process_memory_cache;
|
||||
|
||||
// rjf: user -> ctrl msg ring buffer
|
||||
U64 u2c_ring_size;
|
||||
U8 *u2c_ring_base;
|
||||
U64 u2c_ring_write_pos;
|
||||
U64 u2c_ring_read_pos;
|
||||
OS_Handle u2c_ring_mutex;
|
||||
OS_Handle u2c_ring_cv;
|
||||
|
||||
// rjf: ctrl -> user event ring buffer
|
||||
U64 c2u_ring_size;
|
||||
U8 *c2u_ring_base;
|
||||
U64 c2u_ring_write_pos;
|
||||
U64 c2u_ring_read_pos;
|
||||
OS_Handle c2u_ring_mutex;
|
||||
OS_Handle c2u_ring_cv;
|
||||
|
||||
// rjf: ctrl thread state
|
||||
OS_Handle ctrl_thread;
|
||||
Arena *demon_event_arena;
|
||||
DEMON_EventNode *first_demon_event_node;
|
||||
DEMON_EventNode *last_demon_event_node;
|
||||
DEMON_EventNode *free_demon_event_node;
|
||||
Arena *user_entry_point_arena;
|
||||
String8List user_entry_points;
|
||||
U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64];
|
||||
U64 process_counter;
|
||||
|
||||
// rjf: user -> memstream ring buffer
|
||||
U64 u2ms_ring_size;
|
||||
U8 *u2ms_ring_base;
|
||||
U64 u2ms_ring_write_pos;
|
||||
U64 u2ms_ring_read_pos;
|
||||
OS_Handle u2ms_ring_mutex;
|
||||
OS_Handle u2ms_ring_cv;
|
||||
|
||||
// rjf: memory stream threads
|
||||
U64 ms_thread_count;
|
||||
OS_Handle *ms_threads;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Globals
|
||||
|
||||
global CTRL_State *ctrl_state = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Main Layer Initialization
|
||||
|
||||
internal void ctrl_init(CTRL_WakeupFunctionType *wakeup_hook);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Type Functions
|
||||
|
||||
internal U64 ctrl_hash_from_string(String8 string);
|
||||
internal CTRL_EventCause ctrl_event_cause_from_demon_event_kind(DEMON_EventKind event_kind);
|
||||
internal B32 ctrl_handle_match(CTRL_Handle a, CTRL_Handle b);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Ctrl <-> Demon Handle Translation Functions
|
||||
|
||||
internal DEMON_Handle ctrl_demon_handle_from_ctrl(CTRL_Handle h);
|
||||
internal CTRL_Handle ctrl_handle_from_demon(DEMON_Handle h);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Machine/Handle Pair Type Functions
|
||||
|
||||
internal void ctrl_machine_id_handle_pair_list_push(Arena *arena, CTRL_MachineIDHandlePairList *list, CTRL_MachineIDHandlePair *pair);
|
||||
internal CTRL_MachineIDHandlePairList ctrl_machine_id_handle_pair_list_copy(Arena *arena, CTRL_MachineIDHandlePairList *src);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Trap Type Functions
|
||||
|
||||
internal void ctrl_trap_list_push(Arena *arena, CTRL_TrapList *list, CTRL_Trap *trap);
|
||||
internal CTRL_TrapList ctrl_trap_list_copy(Arena *arena, CTRL_TrapList *src);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: User Breakpoint Type Functions
|
||||
|
||||
internal void ctrl_user_breakpoint_list_push(Arena *arena, CTRL_UserBreakpointList *list, CTRL_UserBreakpoint *bp);
|
||||
internal CTRL_UserBreakpointList ctrl_user_breakpoint_list_copy(Arena *arena, CTRL_UserBreakpointList *src);
|
||||
internal void ctrl_append_resolved_module_user_bp_traps(Arena *arena, DEMON_Handle process, DEMON_Handle module, CTRL_UserBreakpointList *user_bps, DEMON_TrapChunkList *traps_out);
|
||||
internal void ctrl_append_resolved_process_user_bp_traps(Arena *arena, DEMON_Handle process, CTRL_UserBreakpointList *user_bps, DEMON_TrapChunkList *traps_out);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Message Type Functions
|
||||
|
||||
//- rjf: deep copying
|
||||
internal void ctrl_msg_deep_copy(Arena *arena, CTRL_Msg *dst, CTRL_Msg *src);
|
||||
|
||||
//- rjf: list building
|
||||
internal CTRL_Msg *ctrl_msg_list_push(Arena *arena, CTRL_MsgList *list);
|
||||
|
||||
//- rjf: serialization
|
||||
internal String8 ctrl_serialized_string_from_msg_list(Arena *arena, CTRL_MsgList *msgs);
|
||||
internal CTRL_MsgList ctrl_msg_list_from_serialized_string(Arena *arena, String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Event Type Functions
|
||||
|
||||
//- rjf: list building
|
||||
internal CTRL_Event *ctrl_event_list_push(Arena *arena, CTRL_EventList *list);
|
||||
internal void ctrl_event_list_concat_in_place(CTRL_EventList *dst, CTRL_EventList *to_push);
|
||||
|
||||
//- rjf: serialization
|
||||
internal String8 ctrl_serialized_string_from_event(Arena *arena, CTRL_Event *event);
|
||||
internal CTRL_Event ctrl_event_from_serialized_string(Arena *arena, String8 string);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Shared Functions
|
||||
|
||||
//- rjf: run index
|
||||
internal U64 ctrl_run_idx(void);
|
||||
internal U64 ctrl_memgen_idx(void);
|
||||
|
||||
//- rjf: halt everything
|
||||
internal void ctrl_halt(void);
|
||||
|
||||
//- rjf: exe -> dbg path mapping
|
||||
internal String8 ctrl_inferred_og_dbg_path_from_exe_path(Arena *arena, String8 exe_path);
|
||||
internal String8 ctrl_forced_og_dbg_path_from_exe_path(Arena *arena, String8 exe_path);
|
||||
internal String8 ctrl_natural_og_dbg_path_from_exe_path(Arena *arena, String8 exe_path);
|
||||
internal String8 ctrl_og_dbg_path_from_exe_path(Arena *arena, String8 exe_path);
|
||||
|
||||
//- rjf: handle -> arch
|
||||
internal Architecture ctrl_arch_from_handle(CTRL_MachineID machine, CTRL_Handle handle);
|
||||
|
||||
//- rjf: process memory reading/writing
|
||||
internal U64 ctrl_process_read(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, void *dst);
|
||||
internal String8 ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range);
|
||||
internal String8 ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr, U64 limit);
|
||||
internal B32 ctrl_process_write_data(CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr, String8 data);
|
||||
internal U128 ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, B32 zero_terminated);
|
||||
|
||||
//- rjf: register reading/writing
|
||||
internal void *ctrl_reg_block_from_thread(CTRL_MachineID machine_id, CTRL_Handle thread);
|
||||
internal B32 ctrl_thread_write_reg_block(CTRL_MachineID machine_id, CTRL_Handle thread, void *block);
|
||||
internal U64 ctrl_rip_from_thread(CTRL_MachineID machine_id, CTRL_Handle thread);
|
||||
internal B32 ctrl_thread_write_rip(CTRL_MachineID machine_id, CTRL_Handle thread, U64 rip);
|
||||
internal U64 ctrl_tls_root_vaddr_from_thread(CTRL_MachineID machine_id, CTRL_Handle thread);
|
||||
|
||||
//- rjf: name -> register/alias hash tables, for eval
|
||||
internal EVAL_String2NumMap *ctrl_string2reg_from_arch(Architecture arch);
|
||||
internal EVAL_String2NumMap *ctrl_string2alias_from_arch(Architecture arch);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: User -> Ctrl Communication
|
||||
|
||||
internal B32 ctrl_u2c_push_msgs(CTRL_MsgList *msgs, U64 endt_us);
|
||||
internal CTRL_MsgList ctrl_u2c_pop_msgs(Arena *arena);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Ctrl -> User Communication
|
||||
|
||||
internal void ctrl_c2u_push_events(CTRL_EventList *events);
|
||||
internal CTRL_EventList ctrl_c2u_pop_events(Arena *arena);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: User -> Memory Stream Communication
|
||||
|
||||
internal B32 ctrl_u2ms_enqueue_req(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, U64 endt_us);
|
||||
internal void ctrl_u2ms_dequeue_req(CTRL_MachineID *out_machine_id, CTRL_Handle *out_process, Rng1U64 *out_vaddr_range, B32 *out_zero_terminated);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Control-Thread-Only Functions
|
||||
|
||||
//- rjf: entry point
|
||||
internal void ctrl_thread__entry_point(void *p);
|
||||
|
||||
//- rjf: attached process running/event gathering
|
||||
internal DEMON_Event *ctrl_thread__next_demon_event(Arena *arena, CTRL_Msg *msg, DEMON_RunCtrls *run_ctrls, CTRL_Spoof *spoof);
|
||||
|
||||
//- rjf: eval helpers
|
||||
internal B32 ctrl_eval_memory_read(void *u, void *out, U64 addr, U64 size);
|
||||
|
||||
//- rjf: msg kind implementations
|
||||
internal void ctrl_thread__launch_and_handshake(CTRL_Msg *msg);
|
||||
internal void ctrl_thread__launch_and_init(CTRL_Msg *msg);
|
||||
internal void ctrl_thread__attach(CTRL_Msg *msg);
|
||||
internal void ctrl_thread__kill(CTRL_Msg *msg);
|
||||
internal void ctrl_thread__detach(CTRL_Msg *msg);
|
||||
internal void ctrl_thread__run(CTRL_Msg *msg);
|
||||
internal void ctrl_thread__single_step(CTRL_Msg *msg);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Memory-Stream-Thread-Only Functions
|
||||
|
||||
//- rjf: entry point
|
||||
internal void ctrl_mem_stream_thread__entry_point(void *p);
|
||||
|
||||
#endif //CTRL_CORE_H
|
||||
@@ -0,0 +1,4 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#include "ctrl_core.c"
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef CTRL_INC_H
|
||||
#define CTRL_INC_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ NOTE(rjf): Control Layer Overview (2023/8/29)
|
||||
//
|
||||
// This layer's purpose is to provide access to the asynchronously-running, low
|
||||
// level parts of a debugger, running on the debugger client. This primarily
|
||||
// consists of process control, using the Demon layer (the lower level
|
||||
// abstraction layer for process control, across multiple OSes), but including
|
||||
// higher-level concepts, like stepping, breakpoint resolution, conditional
|
||||
// breakpoint evaluation, and so on. Right now, this just includes process
|
||||
// control *local to the debugger client machine*. But in the future, this can
|
||||
// also include communication to multiple target machines, all running their
|
||||
// own process controller, using the Demon layer.
|
||||
//
|
||||
// This part of a debugger must run asynchronously to prevent blocking the UI -
|
||||
// ideally our debugger is designed such that, if targets are running, the
|
||||
// debugger frontend is still usable for a variety of purposes. So, in short,
|
||||
// the asynchronously-running "control thread", implemented by this layer, is
|
||||
// tasked with communicating with a separately executing "user thread". This
|
||||
// communication happens in two directions - `user -> ctrl`, and the reverse,
|
||||
// `ctrl -> user`.
|
||||
//
|
||||
// In the case of `user -> ctrl` communication, this is done with a ring buffer
|
||||
// of "messages" (`CTRL_Msg`), pushed via `ctrl_u2c_push_msgs`. These messages
|
||||
// include commands like: launching targets, attaching to targets, killing
|
||||
// targets, detaching from targets, stepping/running, or single stepping.
|
||||
//
|
||||
// In the case of `ctrl -> user` communication, this is done with a ring buffer
|
||||
// of "events" (`CTRL_Event`), popped via `ctrl_c2u_pop_events`. These events
|
||||
// include information about what happened during the execution of targets -
|
||||
// including: process/module/thread creation, process/module/thread deletion,
|
||||
// debug strings, thread name events, memory allocation events, and stop events
|
||||
// (where stops can be caused by: user breakpoints, traps set for stepping,
|
||||
// exceptions, halts, or errors).
|
||||
//
|
||||
// The various stepping algorithms are implemented with two concepts: (a) the
|
||||
// "trap net", and (b) "spoofs".
|
||||
//
|
||||
// A "trap net" is a term which refers to a set of addresses paired with a set
|
||||
// of behavioral flags. Before targets run, trap instructions are written to
|
||||
// these addresses. After targets stop, these addresses are reset to their
|
||||
// original bytes. These trap instructions cause the debugger's targets to
|
||||
// stop executing, and based on which behavioral flags are associated with
|
||||
// the instruction causing the stop, the control thread may adjust parameters
|
||||
// used for running, then continue execution, or it will not resume target
|
||||
// execution, and will report stopped events. These behavioral flags can
|
||||
// include: single-stepping the stopped thread to execute the instruction at
|
||||
// the trap location, saving a stack pointer "check value" (where this check
|
||||
// value is compared against when making decisions about whether to continue
|
||||
// running or not), and so on. It's complicated to unpack why exactly these
|
||||
// behaviors are useful, but the TL;DR of it is that they are used for a
|
||||
// variety of stepping behaviors. For example, when doing a "step into" step,
|
||||
// a `call` instruction can have a trap set at it, and will be marked with
|
||||
// a "single-step-after" trap flag, as well as the "end stepping" trap flag,
|
||||
// such that the step operation will complete after the `call` has executed.
|
||||
//
|
||||
// A "spoof" is a feature the control layer uses to detect when some thread
|
||||
// returns from a particular sub-callstack. This is useful when implementing
|
||||
// "step over" in functions that may be recursive. In short, unlike a trap,
|
||||
// which writes a trap instruction (like `int3`) into an instruction stream,
|
||||
// a spoof overwrites a *return address* on some thread's *stack*. This return
|
||||
// address is not a valid address for executing code -- it is simply a value
|
||||
// that the debugger can recognize, such that it is notified when the thread
|
||||
// returns from some level in a callstack. When the thread exits some function,
|
||||
// it will return to the "spoofed" address, and it will immediately hit an
|
||||
// exception, because the spoofed address will not be a valid address for
|
||||
// code execution. At that point, the debugger can move the thread back to
|
||||
// the pre-spoof return address, and resume execution.
|
||||
|
||||
#include "ctrl_core.h"
|
||||
|
||||
#endif //CTRL_INC_H
|
||||
@@ -0,0 +1,5 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
//- GENERATED CODE
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
//- GENERATED CODE
|
||||
|
||||
#ifndef CTRL_META_H
|
||||
#define CTRL_META_H
|
||||
|
||||
typedef enum CTRL_ExceptionCodeKind
|
||||
{
|
||||
CTRL_ExceptionCodeKind_Null,
|
||||
CTRL_ExceptionCodeKind_Win32CtrlC,
|
||||
CTRL_ExceptionCodeKind_Win32CtrlBreak,
|
||||
CTRL_ExceptionCodeKind_Win32WinRTOriginateError,
|
||||
CTRL_ExceptionCodeKind_Win32WinRTTransformError,
|
||||
CTRL_ExceptionCodeKind_Win32RPCCallCancelled,
|
||||
CTRL_ExceptionCodeKind_Win32DatatypeMisalignment,
|
||||
CTRL_ExceptionCodeKind_Win32AccessViolation,
|
||||
CTRL_ExceptionCodeKind_Win32InPageError,
|
||||
CTRL_ExceptionCodeKind_Win32InvalidHandle,
|
||||
CTRL_ExceptionCodeKind_Win32NotEnoughQuota,
|
||||
CTRL_ExceptionCodeKind_Win32IllegalInstruction,
|
||||
CTRL_ExceptionCodeKind_Win32CannotContinueException,
|
||||
CTRL_ExceptionCodeKind_Win32InvalidExceptionDisposition,
|
||||
CTRL_ExceptionCodeKind_Win32ArrayBoundsExceeded,
|
||||
CTRL_ExceptionCodeKind_Win32FloatingPointDenormalOperand,
|
||||
CTRL_ExceptionCodeKind_Win32FloatingPointDivisionByZero,
|
||||
CTRL_ExceptionCodeKind_Win32FloatingPointInexactResult,
|
||||
CTRL_ExceptionCodeKind_Win32FloatingPointInvalidOperation,
|
||||
CTRL_ExceptionCodeKind_Win32FloatingPointOverflow,
|
||||
CTRL_ExceptionCodeKind_Win32FloatingPointStackCheck,
|
||||
CTRL_ExceptionCodeKind_Win32FloatingPointUnderflow,
|
||||
CTRL_ExceptionCodeKind_Win32IntegerDivisionByZero,
|
||||
CTRL_ExceptionCodeKind_Win32IntegerOverflow,
|
||||
CTRL_ExceptionCodeKind_Win32PrivilegedInstruction,
|
||||
CTRL_ExceptionCodeKind_Win32StackOverflow,
|
||||
CTRL_ExceptionCodeKind_Win32UnableToLocateDLL,
|
||||
CTRL_ExceptionCodeKind_Win32OrdinalNotFound,
|
||||
CTRL_ExceptionCodeKind_Win32EntryPointNotFound,
|
||||
CTRL_ExceptionCodeKind_Win32DLLInitializationFailed,
|
||||
CTRL_ExceptionCodeKind_Win32FloatingPointSSEMultipleFaults,
|
||||
CTRL_ExceptionCodeKind_Win32FloatingPointSSEMultipleTraps,
|
||||
CTRL_ExceptionCodeKind_Win32AssertionFailed,
|
||||
CTRL_ExceptionCodeKind_Win32ModuleNotFound,
|
||||
CTRL_ExceptionCodeKind_Win32ProcedureNotFound,
|
||||
CTRL_ExceptionCodeKind_Win32SanitizerErrorDetected,
|
||||
CTRL_ExceptionCodeKind_Win32SanitizerRawAccessViolation,
|
||||
CTRL_ExceptionCodeKind_COUNT
|
||||
} CTRL_ExceptionCodeKind;
|
||||
|
||||
U32 ctrl_exception_code_kind_code_table[] =
|
||||
{
|
||||
0,
|
||||
0x40010005,
|
||||
0x40010008,
|
||||
0x40080201,
|
||||
0x40080202,
|
||||
0x0000071a,
|
||||
0x80000002,
|
||||
0xc0000005,
|
||||
0xc0000006,
|
||||
0xc0000008,
|
||||
0xc0000017,
|
||||
0xc000001d,
|
||||
0xc0000025,
|
||||
0xc0000026,
|
||||
0xc000008c,
|
||||
0xc000008d,
|
||||
0xc000008e,
|
||||
0xc000008f,
|
||||
0xc0000090,
|
||||
0xc0000091,
|
||||
0xc0000092,
|
||||
0xc0000093,
|
||||
0xc0000094,
|
||||
0xc0000095,
|
||||
0xc0000096,
|
||||
0xc00000fd,
|
||||
0xc0000135,
|
||||
0xc0000138,
|
||||
0xc0000139,
|
||||
0xc0000142,
|
||||
0xc00002b4,
|
||||
0xc00002b5,
|
||||
0xc0000420,
|
||||
0xc06d007e,
|
||||
0xc06d007f,
|
||||
0xe073616e,
|
||||
0xe0736171,
|
||||
};
|
||||
|
||||
String8 ctrl_exception_code_kind_display_string_table[] =
|
||||
{
|
||||
{0},
|
||||
str8_lit_comp("(Win32) Control-C"),
|
||||
str8_lit_comp("(Win32) Control-Break"),
|
||||
str8_lit_comp("(Win32) WinRT Originate Error"),
|
||||
str8_lit_comp("(Win32) WinRT Transform Error"),
|
||||
str8_lit_comp("(Win32) RPC Call Cancelled"),
|
||||
str8_lit_comp("(Win32) Data Type Misalignment"),
|
||||
str8_lit_comp("(Win32) Access Violation"),
|
||||
str8_lit_comp("(Win32) In Page Error"),
|
||||
str8_lit_comp("(Win32) Invalid Handle Specified"),
|
||||
str8_lit_comp("(Win32) Not Enough Quota"),
|
||||
str8_lit_comp("(Win32) Illegal Instruction"),
|
||||
str8_lit_comp("(Win32) Cannot Continue From Exception"),
|
||||
str8_lit_comp("(Win32) Invalid Exception Disposition Returned By Handler"),
|
||||
str8_lit_comp("(Win32) Array Bounds Exceeded"),
|
||||
str8_lit_comp("(Win32) Floating-Point Denormal Operand"),
|
||||
str8_lit_comp("(Win32) Floating-Point Division By Zero"),
|
||||
str8_lit_comp("(Win32) Floating-Point Inexact Result"),
|
||||
str8_lit_comp("(Win32) Floating-Point Invalid Operation"),
|
||||
str8_lit_comp("(Win32) Floating-Point Overflow"),
|
||||
str8_lit_comp("(Win32) Floating-Point Stack Check"),
|
||||
str8_lit_comp("(Win32) Floating-Point Underflow"),
|
||||
str8_lit_comp("(Win32) Integer Division By Zero"),
|
||||
str8_lit_comp("(Win32) Integer Overflow"),
|
||||
str8_lit_comp("(Win32) Privileged Instruction"),
|
||||
str8_lit_comp("(Win32) Stack Overflow"),
|
||||
str8_lit_comp("(Win32) Unable To Locate DLL"),
|
||||
str8_lit_comp("(Win32) Ordinal Not Found"),
|
||||
str8_lit_comp("(Win32) Entry Point Not Found"),
|
||||
str8_lit_comp("(Win32) DLL Initialization Failed"),
|
||||
str8_lit_comp("(Win32) Floating Point SSE Multiple Faults"),
|
||||
str8_lit_comp("(Win32) Floating Point SSE Multiple Traps"),
|
||||
str8_lit_comp("(Win32) Assertion Failed"),
|
||||
str8_lit_comp("(Win32) Module Not Found"),
|
||||
str8_lit_comp("(Win32) Procedure Not Found"),
|
||||
str8_lit_comp("(Win32) Sanitizer Error Detected"),
|
||||
str8_lit_comp("(Win32) Sanitizer Raw Access Violation"),
|
||||
};
|
||||
|
||||
String8 ctrl_exception_code_kind_lowercase_code_string_table[] =
|
||||
{
|
||||
{0},
|
||||
str8_lit_comp("win32_ctrl_c"),
|
||||
str8_lit_comp("win32_ctrl_break"),
|
||||
str8_lit_comp("win32_win_rt_originate_error"),
|
||||
str8_lit_comp("win32_win_rt_transform_error"),
|
||||
str8_lit_comp("win32_rpc_call_cancelled"),
|
||||
str8_lit_comp("win32_datatype_misalignment"),
|
||||
str8_lit_comp("win32_access_violation"),
|
||||
str8_lit_comp("win32_in_page_error"),
|
||||
str8_lit_comp("win32_invalid_handle"),
|
||||
str8_lit_comp("win32_not_enough_quota"),
|
||||
str8_lit_comp("win32_illegal_instruction"),
|
||||
str8_lit_comp("win32_cannot_continue_exception"),
|
||||
str8_lit_comp("win32_invalid_exception_disposition"),
|
||||
str8_lit_comp("win32_array_bounds_exceeded"),
|
||||
str8_lit_comp("win32_floating_point_denormal_operand"),
|
||||
str8_lit_comp("win32_floating_point_division_by_zero"),
|
||||
str8_lit_comp("win32_floating_point_inexact_result"),
|
||||
str8_lit_comp("win32_floating_point_invalid_operation"),
|
||||
str8_lit_comp("win32_floating_point_overflow"),
|
||||
str8_lit_comp("win32_floating_point_stack_check"),
|
||||
str8_lit_comp("win32_floating_point_underflow"),
|
||||
str8_lit_comp("win32_integer_division_by_zero"),
|
||||
str8_lit_comp("win32_integer_overflow"),
|
||||
str8_lit_comp("win32_privileged_instruction"),
|
||||
str8_lit_comp("win32_stack_overflow"),
|
||||
str8_lit_comp("win32_unable_to_locate_dll"),
|
||||
str8_lit_comp("win32_ordinal_not_found"),
|
||||
str8_lit_comp("win32_entry_point_not_found"),
|
||||
str8_lit_comp("win32_dll_initialization_failed"),
|
||||
str8_lit_comp("win32_floating_point_sse_multiple_faults"),
|
||||
str8_lit_comp("win32_floating_point_sse_multiple_traps"),
|
||||
str8_lit_comp("win32_assertion_failed"),
|
||||
str8_lit_comp("win32_module_not_found"),
|
||||
str8_lit_comp("win32_procedure_not_found"),
|
||||
str8_lit_comp("win32_sanitizer_error_detected"),
|
||||
str8_lit_comp("win32_sanitizer_raw_access_violation"),
|
||||
};
|
||||
|
||||
B8 ctrl_exception_code_kind_default_enable_table[] =
|
||||
{
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
};
|
||||
|
||||
|
||||
#endif // CTRL_META_H
|
||||
Reference in New Issue
Block a user