fill out first pass implementations of raddbg_markup features; thread names, thread colors, format-string output-debug-string helper, attachment-checking

This commit is contained in:
Ryan Fleury
2025-03-28 10:56:41 -07:00
parent 4cc883a353
commit 3911a66b30
10 changed files with 137 additions and 31 deletions
+34 -5
View File
@@ -606,8 +606,8 @@ ctrl_event_from_serialized_string(Arena *arena, String8 string)
read_off += str8_deserial_read_struct(string, read_off, &event.stack_base);
read_off += str8_deserial_read_struct(string, read_off, &event.tls_root);
read_off += str8_deserial_read_struct(string, read_off, &event.timestamp);
read_off += str8_deserial_read_struct(string, read_off, &event.exception_code);
read_off += str8_deserial_read_struct(string, read_off, &event.rgba);
read_off += str8_deserial_read_struct(string, read_off, &event.exception_code);
read_off += str8_deserial_read_struct(string, read_off, &event.string.size);
event.string.str = push_array_no_zero(arena, U8, event.string.size);
read_off += str8_deserial_read(string, read_off, event.string.str, event.string.size, 1);
@@ -3603,6 +3603,7 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
Guid rdi_dbg_guid = {0};
String8 rdi_dbg_path = str8_zero();
String8 raddbg_data = str8_zero();
Rng1U64 raddbg_section_voff_range = r1u64(0, 0);
ProfScope("unpack relevant PE info")
{
B32 is_valid = 1;
@@ -3804,7 +3805,6 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
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);
@@ -3820,6 +3820,13 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
vaddr_range.min + raddbg_section_voff_range.max), raddbg_data.str);
scratch_end(scratch);
}
// rjf: if we have a raddbg section, mark the first byte as 1, to signify attachment
if(raddbg_section_voff_range.max != raddbg_section_voff_range.min)
{
U8 new_value = 1;
dmn_process_write_struct(process.dmn_handle, vaddr_range.min + raddbg_section_voff_range.min, &new_value);
}
}
}
@@ -3898,6 +3905,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_section_voff_range = raddbg_section_voff_range;
node->raddbg_data = raddbg_data;
}
}
@@ -3905,11 +3913,12 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
}
internal void
ctrl_thread__module_close(CTRL_Handle module)
ctrl_thread__module_close(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_range)
{
//////////////////////////////
//- rjf: evict module image info from cache
//
Rng1U64 raddbg_section_voff_range = {0};
{
U64 hash = ctrl_hash_from_handle(module);
U64 slot_idx = hash%ctrl_state->module_image_info_cache.slots_count;
@@ -3929,11 +3938,21 @@ ctrl_thread__module_close(CTRL_Handle module)
}
if(node)
{
raddbg_section_voff_range = node->raddbg_section_voff_range;
DLLRemove(slot->first, slot->last, node);
arena_release(node->arena);
}
}
}
//////////////////////////////
//- rjf: write 0 into first byte of raddbg data section, to signify detachment
//
if(raddbg_section_voff_range.max != raddbg_section_voff_range.min)
{
U8 new_value = 0;
dmn_process_write_struct(process.dmn_handle, vaddr_range.min + raddbg_section_voff_range.min, &new_value);
}
}
//- rjf: attached process running/event gathering
@@ -4265,13 +4284,14 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg,
{
CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts);
CTRL_Handle module_handle = ctrl_handle_make(CTRL_MachineID_Local, event->module);
CTRL_Entity *module_ent = ctrl_entity_from_handle(ctrl_state->ctrl_thread_entity_store, module_handle);
CTRL_Entity *process_ent = ctrl_process_from_entity(module_ent);
String8 module_path = event->string;
ctrl_thread__module_close(module_handle);
ctrl_thread__module_close(process_ent->handle, module_handle, module_ent->vaddr_range);
out_evt->kind = CTRL_EventKind_EndModule;
out_evt->msg_id = msg->msg_id;
out_evt->entity = module_handle;
out_evt->string = module_path;
CTRL_Entity *module_ent = ctrl_entity_from_handle(ctrl_state->ctrl_thread_entity_store, module_handle);
CTRL_Entity *debug_info_path_ent = ctrl_entity_child_from_kind(module_ent, CTRL_EntityKind_DebugInfoPath);
if(debug_info_path_ent != &ctrl_entity_nil)
{
@@ -4302,6 +4322,15 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg,
out_evt->string = event->string;
out_evt->entity_id = event->code;
}break;
case DMN_EventKind_SetThreadColor:
{
CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts);
out_evt->kind = CTRL_EventKind_ThreadColor;
out_evt->msg_id = msg->msg_id;
out_evt->entity = ctrl_handle_make(CTRL_MachineID_Local, event->thread);
out_evt->parent = ctrl_handle_make(CTRL_MachineID_Local, event->process);
out_evt->rgba = event->code;
}break;
}
ctrl_c2u_push_events(&evts);
+2 -1
View File
@@ -593,6 +593,7 @@ struct CTRL_ModuleImageInfoCacheNode
U64 entry_point_voff;
Rng1U64 tls_vaddr_range;
String8 initial_debug_info_path;
Rng1U64 raddbg_section_voff_range;
String8 raddbg_data;
};
@@ -953,7 +954,7 @@ internal void ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, C
//- rjf: module lifetime open/close work
internal void ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_range, String8 path);
internal void ctrl_thread__module_close(CTRL_Handle module);
internal void ctrl_thread__module_close(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_range);
//- rjf: attached process running/event gathering
internal DMN_Event *ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, DMN_RunCtrls *run_ctrls, CTRL_Spoof *spoof);
+1
View File
@@ -21,6 +21,7 @@ DMN_EventKindTable:
{Memory}
{DebugString}
{SetThreadName}
{SetThreadColor}
}
@table(name)
+2 -1
View File
@@ -4,7 +4,7 @@
//- GENERATED CODE
C_LINKAGE_BEGIN
String8 dmn_event_kind_string_table[17] =
String8 dmn_event_kind_string_table[18] =
{
str8_lit_comp("Null"),
str8_lit_comp("Error"),
@@ -23,6 +23,7 @@ str8_lit_comp("Halt"),
str8_lit_comp("Memory"),
str8_lit_comp("DebugString"),
str8_lit_comp("SetThreadName"),
str8_lit_comp("SetThreadColor"),
};
String8 dmn_exception_kind_string_table[5] =
+2 -1
View File
@@ -25,6 +25,7 @@ DMN_EventKind_Halt,
DMN_EventKind_Memory,
DMN_EventKind_DebugString,
DMN_EventKind_SetThreadName,
DMN_EventKind_SetThreadColor,
DMN_EventKind_COUNT,
} DMN_EventKind;
@@ -58,7 +59,7 @@ DMN_ExceptionKind_COUNT,
} DMN_ExceptionKind;
C_LINKAGE_BEGIN
extern String8 dmn_event_kind_string_table[17];
extern String8 dmn_event_kind_string_table[18];
extern String8 dmn_exception_kind_string_table[5];
C_LINKAGE_END
+7
View File
@@ -2378,6 +2378,13 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
}
}break;
//- rjf: fill set-thread-color info
case DMN_W32_EXCEPTION_RADDBG_SET_THREAD_COLOR:
{
e->kind = DMN_EventKind_SetThreadColor;
e->code = exception->ExceptionInformation[1];
}break;
//- rjf: unhandled exception case
default:
{
+1
View File
@@ -56,6 +56,7 @@
#define DMN_W32_EXCEPTION_SET_THREAD_NAME 0x406d1388u
#define DMN_w32_EXCEPTION_CLRDBG_NOTIFICATION 0x04242420u
#define DMN_w32_EXCEPTION_CLR 0xE0434352u
#define DMN_W32_EXCEPTION_RADDBG_SET_THREAD_COLOR 0x00524144u
////////////////////////////////
//~ rjf: Win32 Register Codes
+77 -20
View File
@@ -7,23 +7,37 @@
////////////////////////////////
//~ Implementation Overrides
#if !defined(raddbg_markup_vsnprintf)
# define raddbg_markup_vsnprintf vsnprintf
#if !defined(RADDBG_MARKUP_VSNPRINTF)
# define RADDBG_MARKUP_DEFAULT_VSNPRINTF 1
# define RADDBG_MARKUP_VSNPRINTF vsnprintf
#endif
////////////////////////////////
//~ Usage Macros
#define raddbg_is_attached(...) raddbg_is_attached__impl()
#define raddbg_thread_name(fmt, ...) raddbg_thread_name__impl((fmt), __VA_ARGS__)
#define raddbg_thread_color_hex(hexcode) raddbg_thread_color__impl((hexcode))
#define raddbg_thread_color_rgba(r, g, b, a) raddbg_thread_color__impl((unsigned int)(((r)*255) << 24) | (unsigned int)(((g)*255) << 16) | (unsigned int)(((b)*255) << 8) | (unsigned int)((a)*255))
#define raddbg_break(...) raddbg_break__impl()
#define raddbg_break_if(expr, ...) ((expr) ? raddbg_break__impl() : (void)0)
#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_glue(raddbg_auto_view_rule_data__, __COUNTER__)[] = ("auto_view_rule: {type: \"" #type "\", view_rule: \"" #__VA_ARGS__ "\"}")
#if defined(RADDBG_MARKUP_STUBS)
# define raddbg_is_attached(...) (0)
# define raddbg_thread_name(fmt, ...) ((void)0)
# define raddbg_thread_color_hex(hexcode) ((void)0)
# define raddbg_thread_color_rgba(r, g, b, a) ((void)0)
# define raddbg_break(...) ((void)0)
# define raddbg_break_if(expr, ...) ((void)0)
# define raddbg_watch(fmt, ...) ((void)0)
# define raddbg_pin(expr, ...)
# define raddbg_log(fmt, ...) ((void)0)
# define raddbg_auto_view_rule(type, ...) struct raddbg_glue(raddbg_auto_view_rule_stub__, __COUNTER__){int __unused__}
#else
# define raddbg_is_attached(...) raddbg_is_attached__impl()
# define raddbg_thread_name(fmt, ...) raddbg_thread_name__impl((fmt), __VA_ARGS__)
# define raddbg_thread_color_hex(hexcode) raddbg_thread_color__impl((hexcode))
# define raddbg_thread_color_rgba(r, g, b, a) raddbg_thread_color__impl((unsigned int)(((r)*255) << 24) | (unsigned int)(((g)*255) << 16) | (unsigned int)(((b)*255) << 8) | (unsigned int)((a)*255))
# define raddbg_break(...) raddbg_break__impl()
# define raddbg_break_if(expr, ...) ((expr) ? raddbg_break__impl() : (void)0)
# 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_glue(raddbg_auto_view_rule_data__, __COUNTER__)[] = ("auto_view_rule: {type: \"" #type "\", view_rule: \"" #__VA_ARGS__ "\"}")
#endif
////////////////////////////////
//~ Helpers
@@ -34,13 +48,21 @@
////////////////////////////////
//~ Win32 Implementations
#if defined(RADDBG_MARKUP_IMPLEMENTATION)
#if defined(RADDBG_MARKUP_IMPLEMENTATION) && !defined(RADDBG_MARKUP_STUBS)
#if defined(_WIN32)
//- default includes
#if RADDBG_MARKUP_DEFAULT_VSNPRINTF
#include <stdio.h>
#endif
//- section allocating
#pragma section(".raddbg", read)
#pragma section(".raddbg", read, write)
#define raddbg_exe_data __declspec(allocate(".raddbg"))
//- first byte of exe data section -> is attached
raddbg_exe_data unsigned char raddbg_is_attached_byte_marker = 0;
//- types
typedef int BOOL;
@@ -72,11 +94,12 @@ extern "C"
__declspec(dllimport) HANDLE GetCurrentThread(void);
__declspec(dllimport) DWORD GetCurrentThreadId(void);
__declspec(dllimport) void RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, const ULONG_PTR *lpArguments);
__declspec(dllimport) void OutputDebugStringA(LPCSTR buffer);
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);
int RADDBG_MARKUP_VSNPRINTF(char * const, unsigned long long const, const char * const, va_list);
#if defined(__cplusplus)
}
#endif
@@ -173,8 +196,7 @@ raddbg_encode_utf16(wchar_t *str, unsigned __int32 codepoint)
static inline int
raddbg_is_attached__impl(void)
{
// TODO(rjf)
return 0;
return !!raddbg_is_attached_byte_marker;
}
static inline void
@@ -186,7 +208,7 @@ raddbg_thread_name__impl(char *fmt, ...)
{
va_list args;
va_start(args, fmt);
raddbg_markup_vsnprintf(buffer, sizeof(buffer), fmt, args);
RADDBG_MARKUP_VSNPRINTF(buffer, sizeof(buffer), fmt, args);
va_end(args);
}
@@ -260,7 +282,32 @@ raddbg_thread_name__impl(char *fmt, ...)
static inline void
raddbg_thread_color__impl(unsigned int hexcode)
{
// TODO(rjf)
if(raddbg_is_attached())
{
#pragma pack(push, 8)
typedef struct RADDBG_ThreadColorInfo RADDBG_ThreadColorInfo;
struct RADDBG_ThreadColorInfo
{
DWORD dwThreadID;
DWORD _pad0_;
DWORD rgba;
DWORD _pad1_;
};
#pragma pack(pop)
RADDBG_ThreadColorInfo info;
info.dwThreadID = GetCurrentThreadId();
info.rgba = hexcode;
#pragma warning(push)
#pragma warning(disable: 6320 6322)
__try
{
RaiseException(0x00524144u, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info);
}
__except(1)
{
}
#pragma warning(pop)
}
}
#define raddbg_break__impl() (__debugbreak())
@@ -274,7 +321,17 @@ raddbg_watch__impl(char *fmt, ...)
static inline void
raddbg_log__impl(char *fmt, ...)
{
// TODO(rjf)
// rjf: resolve variadic arguments
char buffer[4096];
{
va_list args;
va_start(args, fmt);
RADDBG_MARKUP_VSNPRINTF(buffer, sizeof(buffer), fmt, args);
va_end(args);
}
// rjf: output debug string
OutputDebugStringA(buffer);
}
#endif // defined(_WIN32)
+9 -3
View File
@@ -2670,7 +2670,15 @@ dynamic_step_test(void){
////////////////////////////////
int
mule_main(int argc, char** argv){
mule_main(int argc, char** argv)
{
raddbg_thread_name("mule_main_thread");
raddbg_thread_color_rgba(1, 0, 0, 1);
if(raddbg_is_attached())
{
raddbg_log("raddbg is attached!\n");
}
mule_init();
// NOTE(allen): Eval Tests
@@ -2735,5 +2743,3 @@ mule_main(int argc, char** argv){
return(0);
}
+2
View File
@@ -3114,6 +3114,8 @@ rd_eval_space_write(void *u, E_Space space, void *in, Rng1U64 range)
MD_Node *child_schema = md_child_from_string(root_schema, child_key, 0);
if(str8_match(child_schema->string, str8_lit("label"), 0))
{
result = 1;
ctrl_entity_equip_string(d_state->ctrl_entity_store, entity, write_string);
rd_cmd(D_CmdKind_SetEntityName, .ctrl_entity = entity->handle, .string = write_string);
}
else if(str8_match(child_schema->string, str8_lit("dbg"), 0))