From e621d1366965670c6c9628baa55dd579ab557a9a Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 11 Apr 2025 17:03:36 -0700 Subject: [PATCH] frontend ui/editor & data funnelling for hardware data breakpoints --- src/ctrl/ctrl_core.c | 2 ++ src/ctrl/ctrl_core.h | 9 +++++++++ src/dbg_engine/dbg_engine_core.c | 8 ++++++++ src/dbg_engine/dbg_engine_core.h | 9 +++++++++ src/raddbg/generated/raddbg.meta.c | 8 ++++++-- src/raddbg/generated/raddbg.meta.h | 2 +- src/raddbg/raddbg.mdesk | 8 ++++++++ src/raddbg/raddbg_core.c | 16 ++++++++++++++++ 8 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 0e3ec2a7..96cff2ec 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -385,6 +385,7 @@ ctrl_serialized_string_from_msg_list(Arena *arena, CTRL_MsgList *msgs) { CTRL_UserBreakpoint *bp = &n->v; str8_serial_push_struct(scratch.arena, &msgs_srlzed, &bp->kind); + str8_serial_push_struct(scratch.arena, &msgs_srlzed, &bp->flags); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &bp->string.size); str8_serial_push_data(scratch.arena, &msgs_srlzed, bp->string.str, bp->string.size); str8_serial_push_struct(scratch.arena, &msgs_srlzed, &bp->pt); @@ -506,6 +507,7 @@ ctrl_msg_list_from_serialized_string(Arena *arena, String8 string) msg->user_bps.count += 1; CTRL_UserBreakpoint *bp = &n->v; read_off += str8_deserial_read_struct(string, read_off, &bp->kind); + read_off += str8_deserial_read_struct(string, read_off, &bp->flags); read_off += str8_deserial_read_struct(string, read_off, &bp->string.size); bp->string.str = push_array_no_zero(arena, U8, bp->string.size); read_off += str8_deserial_read(string, read_off, bp->string.str, bp->string.size, 1); diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index 5d5642f8..a3fab44e 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -259,6 +259,14 @@ struct CTRL_Spoof //////////////////////////////// //~ rjf: User Breakpoint Types +typedef U32 CTRL_UserBreakpointFlags; +enum +{ + CTRL_UserBreakpointFlag_BreakOnWrite = (1<<0), + CTRL_UserBreakpointFlag_BreakOnRead = (1<<1), + CTRL_UserBreakpointFlag_BreakOnExecute = (1<<2), +}; + typedef enum CTRL_UserBreakpointKind { CTRL_UserBreakpointKind_Null, @@ -272,6 +280,7 @@ typedef struct CTRL_UserBreakpoint CTRL_UserBreakpoint; struct CTRL_UserBreakpoint { CTRL_UserBreakpointKind kind; + CTRL_UserBreakpointFlags flags; String8 string; TxtPt pt; U64 u64; diff --git a/src/dbg_engine/dbg_engine_core.c b/src/dbg_engine/dbg_engine_core.c index dec0cf0d..884e1c53 100644 --- a/src/dbg_engine/dbg_engine_core.c +++ b/src/dbg_engine/dbg_engine_core.c @@ -2403,6 +2403,12 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P // rjf: unpack user breakpoint entity D_Breakpoint *bp = &batch_breakpoints->v[idx]; + // rjf: d -> ctrl flags + CTRL_UserBreakpointFlags ctrl_bp_flags = 0; + if(bp->flags & D_BreakpointFlag_BreakOnWrite) { ctrl_bp_flags |= CTRL_UserBreakpointFlag_BreakOnWrite; } + if(bp->flags & D_BreakpointFlag_BreakOnRead) { ctrl_bp_flags |= CTRL_UserBreakpointFlag_BreakOnRead; } + if(bp->flags & D_BreakpointFlag_BreakOnExecute) { ctrl_bp_flags |= CTRL_UserBreakpointFlag_BreakOnExecute; } + // rjf: textual location -> add breakpoints for all possible override locations if(bp->file_path.size != 0 && bp->pt.line != 0) { @@ -2410,6 +2416,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P for(String8Node *n = overrides.first; n != 0; n = n->next) { CTRL_UserBreakpoint ctrl_user_bp = {CTRL_UserBreakpointKind_FileNameAndLineColNumber}; + ctrl_user_bp.flags = ctrl_bp_flags; ctrl_user_bp.string = n->string; ctrl_user_bp.pt = bp->pt; ctrl_user_bp.condition = bp->condition; @@ -2421,6 +2428,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P else if(bp->vaddr_expr.size != 0) { CTRL_UserBreakpoint ctrl_user_bp = {CTRL_UserBreakpointKind_Expression}; + ctrl_user_bp.flags = ctrl_bp_flags; ctrl_user_bp.string = bp->vaddr_expr; ctrl_user_bp.condition = bp->condition; ctrl_user_breakpoint_list_push(scratch.arena, &msg->user_bps, &ctrl_user_bp); diff --git a/src/dbg_engine/dbg_engine_core.h b/src/dbg_engine/dbg_engine_core.h index cabaca1d..68c977a7 100644 --- a/src/dbg_engine/dbg_engine_core.h +++ b/src/dbg_engine/dbg_engine_core.h @@ -28,9 +28,18 @@ struct D_TargetArray U64 count; }; +typedef U32 D_BreakpointFlags; +enum +{ + D_BreakpointFlag_BreakOnWrite = (1<<0), + D_BreakpointFlag_BreakOnRead = (1<<1), + D_BreakpointFlag_BreakOnExecute = (1<<2), +}; + typedef struct D_Breakpoint D_Breakpoint; struct D_Breakpoint { + D_BreakpointFlags flags; String8 file_path; TxtPt pt; String8 vaddr_expr; diff --git a/src/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index 0e0c1425..c343c535 100644 --- a/src/raddbg/generated/raddbg.meta.c +++ b/src/raddbg/generated/raddbg.meta.c @@ -4,7 +4,7 @@ //- GENERATED CODE C_LINKAGE_BEGIN -RD_VocabInfo rd_vocab_info_table[307] = +RD_VocabInfo rd_vocab_info_table[311] = { {str8_lit_comp("auto_view_rule"), str8_lit_comp("auto_view_rules"), str8_lit_comp("Auto View Rule"), str8_lit_comp("Auto View Rules"), RD_IconKind_Binoculars}, {str8_lit_comp("file_path_map"), str8_lit_comp("file_path_maps"), str8_lit_comp("File Path Map"), str8_lit_comp("File Path Maps"), RD_IconKind_FileOutline}, @@ -99,6 +99,10 @@ RD_VocabInfo rd_vocab_info_table[307] = {str8_lit_comp("num_columns"), str8_lit_comp(""), str8_lit_comp("Number of Columns"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("bitmap"), str8_lit_comp("bitmaps"), str8_lit_comp("Bitmap"), str8_lit_comp("Bitmaps"), RD_IconKind_Bitmap}, {str8_lit_comp("geo3d"), str8_lit_comp(""), str8_lit_comp("Geometry (3D)"), str8_lit_comp(""), RD_IconKind_Cube}, +{str8_lit_comp("address_range_size"), str8_lit_comp("address_range_sizes"), str8_lit_comp("Address Range Size"), str8_lit_comp("Address Range Sizes"), RD_IconKind_Null}, +{str8_lit_comp("break_on_read"), str8_lit_comp(""), str8_lit_comp("Break On Read"), str8_lit_comp(""), RD_IconKind_Null}, +{str8_lit_comp("break_on_write"), str8_lit_comp(""), str8_lit_comp("Break On Write"), str8_lit_comp(""), RD_IconKind_Null}, +{str8_lit_comp("break_on_execute"), str8_lit_comp(""), str8_lit_comp("Break On Execution"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("launch_and_run"), str8_lit_comp(""), str8_lit_comp("Launch and Run"), str8_lit_comp(""), RD_IconKind_Play}, {str8_lit_comp("launch_and_step_into"), str8_lit_comp(""), str8_lit_comp("Launch and Step Into"), str8_lit_comp(""), RD_IconKind_PlayStepForward}, {str8_lit_comp("kill"), str8_lit_comp(""), str8_lit_comp("Kill"), str8_lit_comp(""), RD_IconKind_X}, @@ -323,7 +327,7 @@ RD_NameSchemaInfo rd_name_schema_info_table[16] = {str8_lit_comp("memory"), str8_lit_comp("x:\n{\n 'size': code_string,\n @default(16) 'num_columns': @range[1, 64] u64,\n}\n")}, {str8_lit_comp("bitmap"), str8_lit_comp("x:\n{\n 'w': code_string,\n 'h': code_string,\n 'fmt': tex2dformat,\n}\n")}, {str8_lit_comp("target"), str8_lit_comp("@commands(enable_cfg, launch_and_run, launch_and_step_into, remove_cfg)\n@collection_commands(add_target)\nx:\n{\n 'label': code_string,\n 'executable': path,\n 'arguments': string,\n 'working_directory': path,\n 'entry_point': code_string,\n 'stdout_path': path,\n 'stderr_path': path,\n 'stdin_path': path,\n 'environment': query,\n 'debug_subprocesses': bool,\n @no_expand @default(0) 'enabled': bool,\n}\n")}, -{str8_lit_comp("breakpoint"), str8_lit_comp("@commands(enable_cfg, remove_cfg)\n@collection_commands(toggle_breakpoint, add_breakpoint, add_address_breakpoint)\nx:\n{\n 'label': code_string,\n 'condition': code_string,\n 'source_location': path_pt,\n 'address_location': code_string,\n 'hit_count': u64,\n @no_expand @default(1) 'enabled': bool,\n}\n")}, +{str8_lit_comp("breakpoint"), str8_lit_comp("@commands(enable_cfg, remove_cfg)\n@collection_commands(toggle_breakpoint, add_breakpoint, add_address_breakpoint)\nx:\n{\n 'label': code_string,\n 'condition': code_string,\n 'source_location': path_pt,\n 'address_location': code_string,\n 'hit_count': u64,\n 'address_range_size': @or(1, 2, 4, 8) u64,\n 'break_on_write': bool,\n 'break_on_read': bool,\n 'break_on_execute': bool,\n @no_expand @default(1) 'enabled': bool,\n}\n")}, {str8_lit_comp("watch_pin"), str8_lit_comp("@commands(remove_cfg)\n@collection_commands(add_watch_pin)\nx:\n{\n 'expression': code_string,\n 'view_rule': code_string,\n 'source_location': path_pt,\n 'address_location': code_string,\n}\n")}, {str8_lit_comp("file_path_map"), str8_lit_comp("@collection_commands(add_file_path_map) @commands(remove_cfg) x:{'source':path, 'dest':path}")}, {str8_lit_comp("auto_view_rule"), str8_lit_comp("@collection_commands(add_auto_view_rule) @commands(remove_cfg) x:{'type':code_string, 'view_rule':code_string}")}, diff --git a/src/raddbg/generated/raddbg.meta.h b/src/raddbg/generated/raddbg.meta.h index 1839748b..4bf58a22 100644 --- a/src/raddbg/generated/raddbg.meta.h +++ b/src/raddbg/generated/raddbg.meta.h @@ -644,7 +644,7 @@ RD_Query query; .os_event = rd_regs()->os_event,\ C_LINKAGE_BEGIN -extern RD_VocabInfo rd_vocab_info_table[307]; +extern RD_VocabInfo rd_vocab_info_table[311]; extern RD_NameSchemaInfo rd_name_schema_info_table[16]; extern Rng1U64 rd_reg_slot_range_table[42]; extern String8 rd_binding_version_remap_old_name_table[8]; diff --git a/src/raddbg/raddbg.mdesk b/src/raddbg/raddbg.mdesk index e535d07d..1bf5a8b1 100644 --- a/src/raddbg/raddbg.mdesk +++ b/src/raddbg/raddbg.mdesk @@ -112,6 +112,10 @@ RD_VocabTable: {num_columns "" "Number of Columns" "" Null } {bitmap _ "Bitmap" _ Bitmap } {geo3d "" "Geometry (3D)" "" Cube } + {address_range_size _ "Address Range Size" _ Null } + {break_on_read "" "Break On Read" "" Null } + {break_on_write "" "Break On Write" "" Null } + {break_on_execute "" "Break On Execution" "" Null } } @struct RD_VocabInfo: @@ -249,6 +253,10 @@ RD_VocabTable: 'source_location': path_pt, 'address_location': code_string, 'hit_count': u64, + 'address_range_size': @or(1, 2, 4, 8) u64, + 'break_on_write': bool, + 'break_on_read': bool, + 'break_on_execute': bool, @no_expand @default(1) 'enabled': bool, } ```, diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index b1a3d113..e6c2da65 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -15778,8 +15778,24 @@ Z(getting_started) continue; } + //- rjf: compute breakpoint flags + D_BreakpointFlags flags = 0; + if(str8_match(rd_cfg_child_from_string(src_bp, str8_lit("break_on_write"))->first->string, str8_lit("1"), 0)) + { + flags |= D_BreakpointFlag_BreakOnWrite; + } + if(str8_match(rd_cfg_child_from_string(src_bp, str8_lit("break_on_read"))->first->string, str8_lit("1"), 0)) + { + flags |= D_BreakpointFlag_BreakOnRead; + } + if(str8_match(rd_cfg_child_from_string(src_bp, str8_lit("break_on_execute"))->first->string, str8_lit("1"), 0)) + { + flags |= D_BreakpointFlag_BreakOnExecute; + } + //- rjf: fill breakpoint D_Breakpoint *dst_bp = &breakpoints.v[idx]; + dst_bp->flags = flags; dst_bp->file_path = src_bp_loc.file_path; dst_bp->pt = src_bp_loc.pt; dst_bp->vaddr_expr = src_bp_loc.expr;