asan debug callback

This commit is contained in:
jacob 2026-03-19 15:46:20 -05:00
parent 3d110a1da5
commit 7ba8c7f3bf
6 changed files with 94 additions and 18 deletions

View File

@ -176,7 +176,8 @@
#endif
//- Address sanitization
#if IsAsanEnabled
#if IsAsanEnabled && IsCpu
void __asan_set_error_report_callback(void (*callback)(char *));
void __asan_poison_memory_region(void const volatile *, size_t);
void __asan_unpoison_memory_region(void const volatile *, size_t);
#define AsanPoison(addr, size) __asan_poison_memory_region((addr), (size))
@ -281,20 +282,20 @@
////////////////////////////////////////////////////////////
//~ Linked list helper macros
// Taken from the rad debugger
// Taken from the RAD Debugger
// https://github.com/EpicGamesExt/raddebugger/blob/be5634c44867a2e31f6a109df5e574930992df01/src/base/base_core.h#L239
#define CheckNil(nil,p) ((p) == 0 || (p) == nil)
#define SetNil(nil,p) ((p) = nil)
//- Singly linked stack (first & next pointers)
//- Singly linked stack
#define SllStackPushN(f,n,next) ((n)->next=(f), (f)=(n))
#define SllStackPopN(f,next) ((f)=(f)->next)
#define SllStackPush(f,n) SllStackPushN(f,n,next)
#define SllStackPop(f) SllStackPopN(f,next)
//- Singly linked queue (first, last, & next pointers)
//- Singly linked queue
#define SllQueuePushNZ(nil,f,l,n,next) \
( \
@ -324,7 +325,7 @@
#define SllQueuePopN(f,l,next) SllQueuePopNZ(0,f,l,next)
#define SllQueuePop(f,l) SllQueuePopNZ(0,f,l,next)
//- Doubly linked stack (first, next, & prev pointers)
//- Doubly linked stack
#define DllStackPushNPZ(nil,f,n,next,prev) \
( \
@ -359,7 +360,7 @@
#define DllStackRemoveNP(f,n,next,prev) DllStackRemoveNPZ(0,f,n,next,prev)
#define DllStackRemove(f,n) DllStackRemoveNPZ(0,f,n,next,prev)
//- Doubly linked queue (first, last, next, & prev pointers)
//- Doubly linked queue
#define DllQueueInsertNPZ(nil,f,l,p,n,next,prev) \
( \
@ -836,7 +837,7 @@ Inline u64 MixU64s(u64 seed_a, u64 seed_b)
void LoadApi(ApiDesc api);
void Echo(String msg);
b32 Panic(String msg);
b32 DebugBreakPrompt(String title, String msg);
b32 DebugActionPrompt(String title, String msg);
Callstack CaptureCallstack(u64 skip_frames);
b32 IsRunningInDebugger(void);
b32 IsRunningInWine(void);

View File

@ -146,7 +146,7 @@ b32 Panic(String msg)
return 0;
}
b32 DebugBreakPrompt(String title, String msg)
b32 DebugActionPrompt(String title, String msg)
{
LogInfoF("[DEBUG BREAK PROMPT]: %F", FmtString(msg));
TempArena scratch = BeginScratchNoConflict();
@ -517,19 +517,54 @@ LogEventsArray GetLogEvents(void)
return result;
}
////////////////////////////////////////////////////////////
//~ Asan
void W32_AsanCallback(char *report_cstr)
{
i32 result = 0;
{
b32 is_debug = IsRunningInDebugger();
i32 mb_result = 0;
{
u32 mb_flags = MB_SETFOREGROUND | MB_ICONWARNING;
if (is_debug)
{
mb_flags |= MB_CANCELTRYCONTINUE;
}
mb_result = MessageBoxExA(0, report_cstr, "Address sanitization error", mb_flags, 0);
}
if (mb_result == IDCANCEL)
{
ExitProcess(1);
}
result = is_debug && mb_result != IDCONTINUE;
}
if (result)
{
DEBUGBREAK;
}
}
////////////////////////////////////////////////////////////
//~ Main
i32 W32_Main(void)
{
#if IsAsanEnabled
{
__asan_set_error_report_callback(W32_AsanCallback);
}
#endif
// Init time
{
LARGE_INTEGER qpf;
LARGE_INTEGER qpf = Zi;
QueryPerformanceFrequency(&qpf);
W32.ns_per_qpc = 1000000000 / qpf.QuadPart;
}
{
LARGE_INTEGER qpc;
LARGE_INTEGER qpc = Zi;
QueryPerformanceCounter(&qpc);
W32.timer_start_qpc = qpc.QuadPart;
}
@ -552,20 +587,19 @@ i32 W32_Main(void)
W32.panic_event = CreateEventW(0, 1, 0, 0);
W32.exit_event = CreateEventW(0, 1, 0, 0);
W32.main_thread_id = GetCurrentThreadId();
SetThreadDescription(GetCurrentThread(), L"Main thread");
// Query system info
GetSystemInfo(&W32.info);
// Init main thread
W32_InitCurrentThread(Lit("Main"));
W32.main_thread_id = GetCurrentThreadId();
SetThreadDescription(GetCurrentThread(), L"Main thread");
// Setup logging memory
W32.logs_arena = AcquireArena(Gibi(64));
W32.log_events_arena = AcquireArena(Gibi(64));
W32.readable_log_events = ArenaNext(W32.logs_arena, LogEvent);
// Init main thread
W32_InitCurrentThread(Lit("Main"));
// Get raw args from command line
Arena *perm = PermArena();
String cmdline_str = Zi;

View File

@ -142,6 +142,11 @@ String W32_StringFromError(Arena *arena, i32 code);
void W32_LogEventToFile(LogEvent *ev, HANDLE file);
void W32_Log(i32 level, String msg);
////////////////////////////////////////////////////////////
//~ Asan
void W32_AsanCallback(char *report_cstr);
////////////////////////////////////////////////////////////
//~ Main

View File

@ -4008,7 +4008,7 @@ void G_D12_DebugCallback(
{
String description = StringFromCstrNoLimit((char *)description_cstr);
Echo(StringF(scratch.arena, "[D3D12 DEBUG] %F\n", FmtString(description)));
if (DebugBreakPrompt(Lit("D3D12 Debug Break"), description))
if (DebugActionPrompt(Lit("D3D12 Debug Break"), description))
{
DEBUGBREAK;
}

View File

@ -405,6 +405,15 @@ void M_BuildEntryPoint(WaveLaneCtx *lane)
}
}
// Asan
{
CommandlineArg arg = CommandlineArgFromName(Lit("asan"));
if (arg.exists)
{
M.cmdline.asan = 1;
}
}
if (lane->idx == 0)
{
if (M.cmdline.target_compiler == M_CompilerKind_Msvc)
@ -425,6 +434,11 @@ void M_BuildEntryPoint(WaveLaneCtx *lane)
M_EchoLine(Lit("[Debug build]"));
}
if (M.cmdline.asan)
{
M_EchoLine(Lit("[ASAN]"));
}
M_EchoLine(StringF(perm, "Building layer \"%F\"", FmtString(M.cmdline.leaf_layer_name)));
}
@ -455,7 +469,15 @@ void M_BuildEntryPoint(WaveLaneCtx *lane)
PushStringToList(perm, &cp.defs, Lit("-DIsConsoleApp=0"));
}
PushStringToList(perm, &cp.defs, Lit("-DIsAsanEnabled=0"));
if (M.cmdline.asan)
{
PushStringToList(perm, &cp.defs, Lit("-DIsAsanEnabled=1"));
}
else
{
PushStringToList(perm, &cp.defs, Lit("-DIsAsanEnabled=0"));
}
PushStringToList(perm, &cp.defs, Lit("-DIsDebinfoEnabled=1"));
PushStringToList(perm, &cp.defs, Lit("-DIsDeveloperModeEnabled=1"));
PushStringToList(perm, &cp.defs, Lit("-DIsTestingEnabled=0"));
@ -481,6 +503,19 @@ void M_BuildEntryPoint(WaveLaneCtx *lane)
PushStringToList(perm, &cp.compiler_only_flags_msvc, Lit("-Od"));
}
if (M.cmdline.asan)
{
PushStringToList(perm, &cp.compiler_only_flags_msvc, Lit("-fsanitize=address"));
// PushStringToList(perm, &cp.compiler_only_flags_msvc, Lit("-fsanitize-address-use-after-return"));
}
else
{
if (!M.cmdline.release)
{
PushStringToList(perm, &cp.compiler_only_flags_msvc, Lit("-RTCsu"));
}
}
// TODO: Export debug info separately for release builds
PushStringToList(perm, &cp.flags_msvc, Lit("-DEBUG:FULL"));
PushStringToList(perm, &cp.compiler_only_flags_msvc, Lit("-Z7"));

View File

@ -141,6 +141,7 @@ Struct(M_CommandLine)
{
b32 release;
b32 console;
b32 asan;
String leaf_layer_name;
M_PlatformKind target_platform;
M_CompilerKind target_compiler;