From 03cbbac6d732f1a032b6756a9ebe3df1cbff55f7 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Wed, 26 Mar 2025 13:45:26 -0700 Subject: [PATCH] source-markup-defined auto-view-rules --- src/ctrl/ctrl_core.c | 46 +++++ src/ctrl/ctrl_core.h | 2 + src/lib_raddbg_markup/raddbg_markup.c | 245 ------------------------- src/lib_raddbg_markup/raddbg_markup.h | 250 ++++++++++++++++++++++++++ src/mule/mule_main.cpp | 2 + src/raddbg/raddbg_core.c | 34 +++- src/raddbg/raddbg_main.c | 1 - 7 files changed, 329 insertions(+), 251 deletions(-) delete mode 100644 src/lib_raddbg_markup/raddbg_markup.c diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 4ce76eb3..1f05114c 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -2077,6 +2077,26 @@ ctrl_initial_debug_info_path_from_module(Arena *arena, CTRL_Handle module_handle return result; } +internal String8 +ctrl_raddbg_data_from_module(Arena *arena, CTRL_Handle module_handle) +{ + String8 result = {0}; + U64 hash = ctrl_hash_from_handle(module_handle); + U64 slot_idx = hash%ctrl_state->module_image_info_cache.slots_count; + U64 stripe_idx = slot_idx%ctrl_state->module_image_info_cache.stripes_count; + CTRL_ModuleImageInfoCacheSlot *slot = &ctrl_state->module_image_info_cache.slots[slot_idx]; + CTRL_ModuleImageInfoCacheStripe *stripe = &ctrl_state->module_image_info_cache.stripes[stripe_idx]; + OS_MutexScopeR(stripe->rw_mutex) for(CTRL_ModuleImageInfoCacheNode *n = slot->first; n != 0; n = n->next) + { + if(ctrl_handle_match(n->module, module_handle)) + { + result = push_str8_copy(arena, n->raddbg_data); + break; + } + } + return result; +} + //////////////////////////////// //~ rjf: Unwinding Functions @@ -3582,6 +3602,7 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_ U32 rdi_dbg_time = 0; Guid rdi_dbg_guid = {0}; String8 rdi_dbg_path = str8_zero(); + String8 raddbg_data = str8_zero(); ProfScope("unpack relevant PE info") { B32 is_valid = 1; @@ -3775,6 +3796,30 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_ } } } + + // rjf: extract copy of module's raddbg data + { + Temp scratch = scratch_begin(0, 0); + U64 sec_array_off = opt_ext_off_range.max; + U64 sec_count = file_header.section_count; + COFF_SectionHeader *sec = push_array(scratch.arena, COFF_SectionHeader, sec_count); + dmn_process_read(process.dmn_handle, r1u64(vaddr_range.min + sec_array_off, vaddr_range.min + sec_array_off + sec_count*sizeof(COFF_SectionHeader)), sec); + Rng1U64 raddbg_section_voff_range = r1u64(0, 0); + for EachIndex(idx, sec_count) + { + String8 section_name = str8_cstring(sec[idx].name); + if(str8_match(section_name, str8_lit(".raddbg"), 0)) + { + raddbg_section_voff_range.min = sec[idx].voff; + raddbg_section_voff_range.max = sec[idx].voff + sec[idx].vsize; + } + } + raddbg_data.size = dim_1u64(raddbg_section_voff_range); + raddbg_data.str = push_array(arena, U8, raddbg_data.size); + dmn_process_read(process.dmn_handle, r1u64(vaddr_range.min + raddbg_section_voff_range.min, + vaddr_range.min + raddbg_section_voff_range.max), raddbg_data.str); + scratch_end(scratch); + } } } @@ -3853,6 +3898,7 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_ node->pdatas_count = pdatas_count; node->entry_point_voff = entry_point_voff; node->initial_debug_info_path = initial_debug_info_path; + node->raddbg_data = raddbg_data; } } } diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index 92541b1c..eb74a594 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -593,6 +593,7 @@ struct CTRL_ModuleImageInfoCacheNode U64 entry_point_voff; Rng1U64 tls_vaddr_range; String8 initial_debug_info_path; + String8 raddbg_data; }; typedef struct CTRL_ModuleImageInfoCacheSlot CTRL_ModuleImageInfoCacheSlot; @@ -891,6 +892,7 @@ internal PE_IntelPdata *ctrl_intel_pdata_from_module_voff(Arena *arena, CTRL_Han internal U64 ctrl_entry_point_voff_from_module(CTRL_Handle module_handle); internal Rng1U64 ctrl_tls_vaddr_range_from_module(CTRL_Handle module_handle); internal String8 ctrl_initial_debug_info_path_from_module(Arena *arena, CTRL_Handle module_handle); +internal String8 ctrl_raddbg_data_from_module(Arena *arena, CTRL_Handle module_handle); //////////////////////////////// //~ rjf: Unwinding Functions diff --git a/src/lib_raddbg_markup/raddbg_markup.c b/src/lib_raddbg_markup/raddbg_markup.c deleted file mode 100644 index 7e220eca..00000000 --- a/src/lib_raddbg_markup/raddbg_markup.c +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ Win32 Implementations - -#if defined(_WIN32) - -//- types - -typedef int BOOL; -typedef long LONG; -typedef unsigned long ULONG; -typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; -typedef unsigned long DWORD; -typedef wchar_t WCHAR; -typedef char const *LPCSTR; -typedef const WCHAR *LPCWSTR, *PCWSTR; -typedef LONG HRESULT; -typedef void *HANDLE; -struct HINSTANCE__; -typedef struct HINSTANCE__ *HMODULE; -typedef __int64 INT_PTR; -typedef INT_PTR (*FARPROC)(); - -//- prototypes - -#include - -#if defined(__cplusplus) -extern "C" -{ -#endif - __declspec(dllimport) HMODULE LoadLibraryA(LPCSTR name); - __declspec(dllimport) FARPROC GetProcAddress(HMODULE module, LPCSTR name); - __declspec(dllimport) BOOL FreeLibrary(HMODULE mod); - __declspec(dllimport) HANDLE GetCurrentThread(void); - __declspec(dllimport) DWORD GetCurrentThreadId(void); - __declspec(dllimport) void RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, const ULONG_PTR *lpArguments); - long long _InterlockedCompareExchange64(long long volatile*, long long, long long); - long long _InterlockedExchangeAdd64(long long volatile*, long long); -#pragma intrinsic(_InterlockedCompareExchange64) -#pragma intrinsic(_InterlockedExchangeAdd64) - int raddbg_markup_vsnprintf(char * const, unsigned long long const, const char * const, va_list); -#if defined(__cplusplus) -} -#endif - -//- helpers - -typedef struct RADDBG_MARKUP_UnicodeDecode RADDBG_MARKUP_UnicodeDecode; -struct RADDBG_MARKUP_UnicodeDecode -{ - unsigned __int32 inc; - unsigned __int32 codepoint; -}; -static __int8 raddbg_utf8_class[32] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,2,2,2,2,3,3,4,5}; - -static inline RADDBG_MARKUP_UnicodeDecode -raddbg_decode_utf8(char *str, unsigned __int64 max) -{ - RADDBG_MARKUP_UnicodeDecode result = {1, 0xffffffff}; - unsigned __int8 byte = str[0]; - unsigned __int8 byte_class = raddbg_utf8_class[byte >> 3]; - switch(byte_class) - { - case 1: - { - result.codepoint = byte; - }break; - case 2: - if(2 < max) - { - char cont_byte = str[1]; - if(raddbg_utf8_class[cont_byte >> 3] == 0) - { - result.codepoint = (byte & 0x0000001f) << 6; - result.codepoint |= (cont_byte & 0x0000003f); - result.inc = 2; - } - }break; - case 3: - if(2 < max) - { - char cont_byte[2] = {str[1], str[2]}; - if(raddbg_utf8_class[cont_byte[0] >> 3] == 0 && - raddbg_utf8_class[cont_byte[1] >> 3] == 0) - { - result.codepoint = (byte & 0x0000000f) << 12; - result.codepoint |= ((cont_byte[0] & 0x0000003f) << 6); - result.codepoint |= (cont_byte[1] & 0x0000003f); - result.inc = 3; - } - }break; - case 4: - if(3 < max) - { - char cont_byte[3] = {str[1], str[2], str[3]}; - if(raddbg_utf8_class[cont_byte[0] >> 3] == 0 && - raddbg_utf8_class[cont_byte[1] >> 3] == 0 && - raddbg_utf8_class[cont_byte[2] >> 3] == 0) - { - result.codepoint = (byte & 0x00000007) << 18; - result.codepoint |= ((cont_byte[0] & 0x0000003f) << 12); - result.codepoint |= ((cont_byte[1] & 0x0000003f) << 6); - result.codepoint |= (cont_byte[2] & 0x0000003f); - result.inc = 4; - } - } - } - return result; -} - -static inline unsigned __int32 -raddbg_encode_utf16(wchar_t *str, unsigned __int32 codepoint) -{ - unsigned __int32 inc = 1; - if(codepoint == 0xffffffff) - { - str[0] = (wchar_t)'?'; - } - else if(codepoint < 0x10000) - { - str[0] = (wchar_t)codepoint; - } - else - { - U32 v = codepoint - 0x10000; - str[0] = (wchar_t)(0xD800 + (v >> 10)); - str[1] = (wchar_t)(0xDC00 + (v & 0x000003ff)); - inc = 2; - } - return inc; -} - -//- implementations - -static inline int -raddbg_is_attached__impl(void) -{ - // TODO(rjf) - return 0; -} - -static inline void -raddbg_thread_name__impl(char *fmt, ...) -{ - // rjf: resolve variadic arguments - char buffer[512] = {0}; - char *name = buffer; - { - va_list args; - va_start(args, fmt); - raddbg_markup_vsnprintf(buffer, sizeof(buffer), fmt, args); - va_end(args); - } - - // rjf: get windows 10 style procedure - HRESULT (*SetThreadDescription_function)(HANDLE hThread, PCWSTR lpThreadDescription) = 0; - { - static HRESULT (*global_SetThreadDescription_function)(HANDLE hThread, PCWSTR lpThreadDescription); - static volatile __int64 global_SetThreadDescription_init_started; - static volatile __int64 global_SetThreadDescription_init_done; - __int64 do_init = !_InterlockedCompareExchange64(&global_SetThreadDescription_init_started, 1, 0); - if(do_init) - { - HMODULE module = LoadLibraryA("kernel32.dll"); - global_SetThreadDescription_function = (HRESULT (*)(HANDLE, PCWSTR))GetProcAddress(module, "SetThreadDescription"); - FreeLibrary(module); - _InterlockedExchangeAdd64(&global_SetThreadDescription_init_done, 1); - } - for(;_InterlockedExchangeAdd64(&global_SetThreadDescription_init_done, 0) == 0;) - { - // NOTE(rjf): busy-loop, until init is done - } - SetThreadDescription_function = global_SetThreadDescription_function; - } - - // rjf: set thread name, windows 10 style - if(SetThreadDescription_function) - { - WCHAR buffer16[1024] = {0}; - int name_length = 0; - for(;name[name_length]; name_length += 1); - int write_offset = 0; - for(int idx = 0; idx < name_length;) - { - RADDBG_MARKUP_UnicodeDecode decode = raddbg_decode_utf8(name+idx, name_length-idx); - write_offset += raddbg_encode_utf16(buffer16 + write_offset, decode.codepoint); - idx += decode.inc; - } - SetThreadDescription_function(GetCurrentThread(), buffer16); - } - - // rjf: set thread name, raise-exception style - { -#pragma pack(push, 8) - typedef struct THREADNAME_INFO THREADNAME_INFO; - struct THREADNAME_INFO - { - DWORD dwType; - LPCSTR szName; - DWORD dwThreadID; - DWORD dwFlags; - }; -#pragma pack(pop) - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = name; - info.dwThreadID = GetCurrentThreadId(); - info.dwFlags = 0; -#pragma warning(push) -#pragma warning(disable: 6320 6322) - __try - { - RaiseException(0x406D1388, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info); - } - __except(1) - { - } -#pragma warning(pop) - } -} - -static inline void -raddbg_thread_color__impl(unsigned int hexcode) -{ - // TODO(rjf) -} - -#define raddbg_break__impl() (__debugbreak()) - -static inline void -raddbg_watch__impl(char *fmt, ...) -{ - // TODO(rjf) -} - -static inline void -raddbg_log__impl(char *fmt, ...) -{ - // TODO(rjf) -} - -#endif // defined(_WIN32) diff --git a/src/lib_raddbg_markup/raddbg_markup.h b/src/lib_raddbg_markup/raddbg_markup.h index 390f50d9..be865bfc 100644 --- a/src/lib_raddbg_markup/raddbg_markup.h +++ b/src/lib_raddbg_markup/raddbg_markup.h @@ -23,5 +23,255 @@ #define raddbg_watch(fmt, ...) raddbg_watch__impl((fmt), __VA_ARGS__) #define raddbg_pin(expr, ...) /* NOTE(rjf): inspected by debugger ui - does not change program execution */ #define raddbg_log(fmt, ...) raddbg_log__impl((fmt), __VA_ARGS__) +#define raddbg_auto_view_rule(type, ...) raddbg_exe_data static char raddbg_auto_view_rule_data__##__COUNTER__[] = ("auto_view_rule: {type:" #type ", view_rule: " #__VA_ARGS__ "}") + +//////////////////////////////// +//~ Win32 Implementations + +#if defined(RADDBG_MARKUP_IMPLEMENTATION) +#if defined(_WIN32) + +//- section allocating +#pragma section(".raddbg", read) +#define raddbg_exe_data __declspec(allocate(".raddbg")) + +//- types + +typedef int BOOL; +typedef long LONG; +typedef unsigned long ULONG; +typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; +typedef unsigned long DWORD; +typedef wchar_t WCHAR; +typedef char const *LPCSTR; +typedef const WCHAR *LPCWSTR, *PCWSTR; +typedef LONG HRESULT; +typedef void *HANDLE; +struct HINSTANCE__; +typedef struct HINSTANCE__ *HMODULE; +typedef __int64 INT_PTR; +typedef INT_PTR (*FARPROC)(); + +//- prototypes + +#include + +#if defined(__cplusplus) +extern "C" +{ +#endif + __declspec(dllimport) HMODULE LoadLibraryA(LPCSTR name); + __declspec(dllimport) FARPROC GetProcAddress(HMODULE module, LPCSTR name); + __declspec(dllimport) BOOL FreeLibrary(HMODULE mod); + __declspec(dllimport) HANDLE GetCurrentThread(void); + __declspec(dllimport) DWORD GetCurrentThreadId(void); + __declspec(dllimport) void RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, const ULONG_PTR *lpArguments); + long long _InterlockedCompareExchange64(long long volatile*, long long, long long); + long long _InterlockedExchangeAdd64(long long volatile*, long long); +#pragma intrinsic(_InterlockedCompareExchange64) +#pragma intrinsic(_InterlockedExchangeAdd64) + int raddbg_markup_vsnprintf(char * const, unsigned long long const, const char * const, va_list); +#if defined(__cplusplus) +} +#endif + +//- helpers + +typedef struct RADDBG_MARKUP_UnicodeDecode RADDBG_MARKUP_UnicodeDecode; +struct RADDBG_MARKUP_UnicodeDecode +{ + unsigned __int32 inc; + unsigned __int32 codepoint; +}; +static __int8 raddbg_utf8_class[32] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,2,2,2,2,3,3,4,5}; + +static inline RADDBG_MARKUP_UnicodeDecode +raddbg_decode_utf8(char *str, unsigned __int64 max) +{ + RADDBG_MARKUP_UnicodeDecode result = {1, 0xffffffff}; + unsigned __int8 byte = str[0]; + unsigned __int8 byte_class = raddbg_utf8_class[byte >> 3]; + switch(byte_class) + { + case 1: + { + result.codepoint = byte; + }break; + case 2: + if(2 < max) + { + char cont_byte = str[1]; + if(raddbg_utf8_class[cont_byte >> 3] == 0) + { + result.codepoint = (byte & 0x0000001f) << 6; + result.codepoint |= (cont_byte & 0x0000003f); + result.inc = 2; + } + }break; + case 3: + if(2 < max) + { + char cont_byte[2] = {str[1], str[2]}; + if(raddbg_utf8_class[cont_byte[0] >> 3] == 0 && + raddbg_utf8_class[cont_byte[1] >> 3] == 0) + { + result.codepoint = (byte & 0x0000000f) << 12; + result.codepoint |= ((cont_byte[0] & 0x0000003f) << 6); + result.codepoint |= (cont_byte[1] & 0x0000003f); + result.inc = 3; + } + }break; + case 4: + if(3 < max) + { + char cont_byte[3] = {str[1], str[2], str[3]}; + if(raddbg_utf8_class[cont_byte[0] >> 3] == 0 && + raddbg_utf8_class[cont_byte[1] >> 3] == 0 && + raddbg_utf8_class[cont_byte[2] >> 3] == 0) + { + result.codepoint = (byte & 0x00000007) << 18; + result.codepoint |= ((cont_byte[0] & 0x0000003f) << 12); + result.codepoint |= ((cont_byte[1] & 0x0000003f) << 6); + result.codepoint |= (cont_byte[2] & 0x0000003f); + result.inc = 4; + } + } + } + return result; +} + +static inline unsigned __int32 +raddbg_encode_utf16(wchar_t *str, unsigned __int32 codepoint) +{ + unsigned __int32 inc = 1; + if(codepoint == 0xffffffff) + { + str[0] = (wchar_t)'?'; + } + else if(codepoint < 0x10000) + { + str[0] = (wchar_t)codepoint; + } + else + { + unsigned __int32 v = codepoint - 0x10000; + str[0] = (wchar_t)(0xD800 + (v >> 10)); + str[1] = (wchar_t)(0xDC00 + (v & 0x000003ff)); + inc = 2; + } + return inc; +} + +//- implementations + +static inline int +raddbg_is_attached__impl(void) +{ + // TODO(rjf) + return 0; +} + +static inline void +raddbg_thread_name__impl(char *fmt, ...) +{ + // rjf: resolve variadic arguments + char buffer[512] = {0}; + char *name = buffer; + { + va_list args; + va_start(args, fmt); + raddbg_markup_vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + } + + // rjf: get windows 10 style procedure + HRESULT (*SetThreadDescription_function)(HANDLE hThread, PCWSTR lpThreadDescription) = 0; + { + static HRESULT (*global_SetThreadDescription_function)(HANDLE hThread, PCWSTR lpThreadDescription); + static volatile __int64 global_SetThreadDescription_init_started; + static volatile __int64 global_SetThreadDescription_init_done; + __int64 do_init = !_InterlockedCompareExchange64(&global_SetThreadDescription_init_started, 1, 0); + if(do_init) + { + HMODULE module = LoadLibraryA("kernel32.dll"); + global_SetThreadDescription_function = (HRESULT (*)(HANDLE, PCWSTR))GetProcAddress(module, "SetThreadDescription"); + FreeLibrary(module); + _InterlockedExchangeAdd64(&global_SetThreadDescription_init_done, 1); + } + for(;_InterlockedExchangeAdd64(&global_SetThreadDescription_init_done, 0) == 0;) + { + // NOTE(rjf): busy-loop, until init is done + } + SetThreadDescription_function = global_SetThreadDescription_function; + } + + // rjf: set thread name, windows 10 style + if(SetThreadDescription_function) + { + WCHAR buffer16[1024] = {0}; + int name_length = 0; + for(;name[name_length]; name_length += 1); + int write_offset = 0; + for(int idx = 0; idx < name_length;) + { + RADDBG_MARKUP_UnicodeDecode decode = raddbg_decode_utf8(name+idx, name_length-idx); + write_offset += raddbg_encode_utf16(buffer16 + write_offset, decode.codepoint); + idx += decode.inc; + } + SetThreadDescription_function(GetCurrentThread(), buffer16); + } + + // rjf: set thread name, raise-exception style + { +#pragma pack(push, 8) + typedef struct THREADNAME_INFO THREADNAME_INFO; + struct THREADNAME_INFO + { + DWORD dwType; + LPCSTR szName; + DWORD dwThreadID; + DWORD dwFlags; + }; +#pragma pack(pop) + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = name; + info.dwThreadID = GetCurrentThreadId(); + info.dwFlags = 0; +#pragma warning(push) +#pragma warning(disable: 6320 6322) + __try + { + RaiseException(0x406D1388, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info); + } + __except(1) + { + } +#pragma warning(pop) + } +} + +static inline void +raddbg_thread_color__impl(unsigned int hexcode) +{ + // TODO(rjf) +} + +#define raddbg_break__impl() (__debugbreak()) + +static inline void +raddbg_watch__impl(char *fmt, ...) +{ + // TODO(rjf) +} + +static inline void +raddbg_log__impl(char *fmt, ...) +{ + // TODO(rjf) +} + +#endif // defined(_WIN32) +#endif // defined(RADDBG_MARKUP_IMPLEMENTATION) #endif // RADDBG_MARKUP_H diff --git a/src/mule/mule_main.cpp b/src/mule/mule_main.cpp index 81eb08df..9a028864 100644 --- a/src/mule/mule_main.cpp +++ b/src/mule/mule_main.cpp @@ -6,6 +6,7 @@ ** stepping, breakpoints, evaluation, cross-module calls. */ +#define RADDBG_MARKUP_IMPLEMENTATION #include "lib_raddbg_markup/raddbg_markup.h" //////////////////////////////// @@ -142,6 +143,7 @@ struct Fixed_Array{ int count; }; +raddbg_auto_view_rule(Dynamic?, slice); struct Dynamic_Array{ Pair *pairs; int count; diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 4100c2df..c77162f6 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -13900,15 +13900,39 @@ rd_frame(void) } } + //- rjf: gather auto-view-rules from loaded modules + RD_CfgList immediate_auto_view_rules = {0}; + CTRL_EntityList modules = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Module); + for(CTRL_EntityNode *n = modules.first; n != 0; n = n->next) + { + String8 raddbg_data = ctrl_raddbg_data_from_module(scratch.arena, n->v->handle); + RD_CfgList cfgs = rd_cfg_tree_list_from_string(scratch.arena, raddbg_data); + RD_Cfg *immediate_root = rd_immediate_cfg_from_keyf("module_%S_cfgs", ctrl_string_from_handle(scratch.arena, n->v->handle)); + for(RD_CfgNode *n = cfgs.first; n != 0; n = n->next) + { + rd_cfg_insert_child(immediate_root, immediate_root->last, n->v); + rd_cfg_list_push(scratch.arena, &immediate_auto_view_rules, n->v); + } + } + //- rjf: add auto-hook rules for auto-view-rules { RD_CfgList auto_view_rules = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("auto_view_rule")); - for(RD_CfgNode *n = auto_view_rules.first; n != 0; n = n->next) + RD_CfgList rules_lists[] = { - RD_Cfg *rule = n->v; - String8 type_string = rd_cfg_child_from_string(rule, str8_lit("type"))->first->string; - String8 view_rule_string = rd_cfg_child_from_string(rule, str8_lit("view_rule"))->first->string; - e_auto_hook_map_insert_new(scratch.arena, ctx->auto_hook_map, .type_pattern = type_string, .tag_expr_string = view_rule_string); + auto_view_rules, + immediate_auto_view_rules, + }; + for EachElement(list_idx, rules_lists) + { + RD_CfgList list = rules_lists[list_idx]; + for(RD_CfgNode *n = list.first; n != 0; n = n->next) + { + RD_Cfg *rule = n->v; + String8 type_string = rd_cfg_child_from_string(rule, str8_lit("type"))->first->string; + String8 view_rule_string = rd_cfg_child_from_string(rule, str8_lit("view_rule"))->first->string; + e_auto_hook_map_insert_new(scratch.arena, ctx->auto_hook_map, .type_pattern = type_string, .tag_expr_string = view_rule_string); + } } } } diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index 9e6738ef..2b018fb4 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -388,7 +388,6 @@ #include "third_party/rad_lzb_simple/rad_lzb_simple.h" #include "third_party/rad_lzb_simple/rad_lzb_simple.c" #include "lib_raddbg_markup/raddbg_markup.h" -#include "lib_raddbg_markup/raddbg_markup.c" //- rjf: [h] #include "base/base_inc.h"