From 086ca98181177923a04033d30aeb1222fcf7c644 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 27 Sep 2024 16:27:55 -0700 Subject: [PATCH] callstack unwind selection in watch window-ified callstack view --- src/ctrl/ctrl_core.h | 2 +- src/raddbg/raddbg_views.c | 163 ++++++++++++++++++++++++++++---------- src/raddbg/raddbg_views.h | 11 ++- 3 files changed, 130 insertions(+), 46 deletions(-) diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index 1a14f23f..4a291870 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -25,7 +25,7 @@ struct CTRL_MetaEvalFrame ptr_type(CTRL_MetaEvalFrame__vaddr_type, type(void), .flags = TypeFlag_IsExternal, .size = sizeof(U64)); struct_members(CTRL_MetaEvalFrame) { - member_lit_comp(CTRL_MetaEvalFrame, type(U64), vaddr), + member_lit_comp(CTRL_MetaEvalFrame, &CTRL_MetaEvalFrame__vaddr_type, vaddr), member_lit_comp(CTRL_MetaEvalFrame, type(U64), inline_depth), }; struct_type(CTRL_MetaEvalFrame); diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index aee43c36..9aa68107 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -843,6 +843,61 @@ rd_collection_info_from_num(EV_BlockRangeList *block_ranges, S64 num) return info; } +internal RD_WatchViewCallStackFrameInfo +rd_callstack_frame_info_from_num(EV_BlockRangeList *block_ranges, S64 num) +{ + Temp scratch = scratch_begin(0, 0); + DI_Scope *di_scope = di_scope_open(); + EV_Block *block = ev_block_range_from_num(block_ranges, num).block; + CTRL_Entity *thread = &ctrl_entity_nil; + for(E_Expr *expr = block->expr, *next = &e_expr_nil; expr != &e_expr_nil; expr = next) + { + next = &e_expr_nil; + switch(expr->kind) + { + default:{}break; + case E_ExprKind_Ref:{next = expr->ref;}break; + case E_ExprKind_Cast:{next = expr->last;}break; + case E_ExprKind_MemberAccess:{next = expr->first;}break; + case E_ExprKind_ArrayIndex:{next = expr->first;}break; + case E_ExprKind_LeafIdent: + { + E_Eval eval = e_eval_from_expr(scratch.arena, expr); + CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(eval.space); + if(entity->kind == CTRL_EntityKind_Thread) + { + thread = entity; + goto done; + } + }break; + } + } + done:; + RD_WatchViewCallStackFrameInfo info = {thread}; + if(thread != &ctrl_entity_nil) + { + EV_Key key = ev_key_from_num(block_ranges, num); + U64 block_relative_num = block->expand_view_rule_info->expr_expand_num_from_id(key.child_id, block->expand_view_rule_info_user_data); + CTRL_Unwind base_unwind = d_query_cached_unwind_from_thread(thread); + D_Unwind rich_unwind = d_unwind_from_ctrl_unwind(scratch.arena, di_scope, ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process), &base_unwind); + U64 frame_num = 1; + for(U64 base_frame_idx = 0; base_frame_idx < rich_unwind.frames.concrete_frame_count; base_frame_idx += 1, frame_num += 1) + { + if(frame_num <= block_relative_num && block_relative_num < frame_num+1+rich_unwind.frames.v[base_frame_idx].inline_frame_count) + { + info.thread = thread; + info.unwind_index = base_frame_idx; + info.inline_depth = block_relative_num - frame_num; + break; + } + frame_num += rich_unwind.frames.v[base_frame_idx].inline_frame_count; + } + } + di_scope_close(di_scope); + scratch_end(scratch); + return info; +} + //- rjf: row -> kind internal RD_WatchViewRowKind @@ -923,6 +978,7 @@ rd_string_from_eval_viz_row_column(Arena *arena, EV_View *ev, EV_Row *row, RD_Wa { expr = e_expr_ref_member_access(arena, expr, n->string); } + expr = ev_expr_from_expr_view_rules(scratch.arena, expr, view_rules); E_Eval eval = e_eval_from_expr(arena, expr); result = rd_value_string_from_eval(arena, string_flags, default_radix, font, font_size, max_size_px, eval, row->member, view_rules); scratch_end(scratch); @@ -1430,7 +1486,11 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo EV_Row *row = rows.first; for(S64 y = selection_tbl.min.y; y <= selection_tbl.max.y && row != 0; y += 1, row = row->next) { + // rjf: unpack row info RD_WatchViewRowKind row_kind = rd_watch_view_row_kind_from_row(flags, row); + RD_WatchViewCallStackFrameInfo callstack_frame_info = rd_callstack_frame_info_from_num(&block_ranges, y); + + // rjf: loop through X selections and perform operations for each for(S64 x = selection_tbl.min.x; x <= selection_tbl.max.x; x += 1) { //- rjf: determine operation for this cell @@ -1439,11 +1499,16 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo OpKind_Null, OpKind_DoExpand, OpKind_GoToLocation, + OpKind_SelectUnwind, OpKind_DoTabOpen, } OpKind; OpKind kind = OpKind_DoExpand; - switch(row_kind) + if(callstack_frame_info.thread != &ctrl_entity_nil) + { + kind = OpKind_SelectUnwind; + } + else switch(row_kind) { default:{}break; @@ -1502,6 +1567,13 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo case OpKind_GoToLocation: { + }break; + case OpKind_SelectUnwind: + { + rd_cmd(RD_CmdKind_SelectThread, .thread = callstack_frame_info.thread->handle); + rd_cmd(RD_CmdKind_SelectUnwind, + .unwind_count = callstack_frame_info.unwind_index, + .inline_depth = callstack_frame_info.inline_depth); }break; case OpKind_DoTabOpen: { @@ -2195,8 +2267,7 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo row_is_fresh = 1; } if(slice.byte_bad_flags[idx] != 0) - { - row_is_bad = 1; + {row_is_bad = 1; } } } @@ -2661,14 +2732,14 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo }break; case RD_WatchViewColumnKind_CallStackFrameSelection: { -#if 0 // TODO(rjf): @blocks - if(semantic_num - 1 == rd_regs()->unwind_count - rd_regs()->inline_depth) + RD_WatchViewCallStackFrameInfo callstack_frame_info = rd_callstack_frame_info_from_num(&block_ranges, global_row_idx); + if(ctrl_handle_match(callstack_frame_info.thread->handle, rd_regs()->thread) && + callstack_frame_info.unwind_index == rd_regs()->unwind_count && + callstack_frame_info.inline_depth == rd_regs()->inline_depth) { cell_icon = RD_IconKind_RightArrow; - CTRL_Entity *thread = ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->thread); - cell_base_color = rd_rgba_from_ctrl_entity(thread); + cell_base_color = rd_rgba_from_ctrl_entity(callstack_frame_info.thread); } -#endif }break; } @@ -2801,47 +2872,51 @@ rd_watch_view_build(RD_WatchViewState *ewv, RD_WatchViewFlags flags, String8 roo pressed = 1; } - // rjf: double-click -> start editing - if(ui_double_clicked(sig) && cell_can_edit) + // rjf: double-click actions + if(ui_double_clicked(sig)) { ui_kill_action(); - rd_cmd(RD_CmdKind_Edit); - } - - // rjf: double-click, not editable -> go-to-location - if(ui_double_clicked(sig) && !cell_can_edit) - { - U64 vaddr = cell_eval.value.u64; - CTRL_Entity *process = rd_ctrl_entity_from_eval_space(cell_eval.space); - CTRL_Entity *module = ctrl_module_from_process_vaddr(process, vaddr); - DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); - U64 voff = ctrl_voff_from_vaddr(module, vaddr); - D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, voff); - String8 file_path = {0}; - TxtPt pt = {0}; - if(lines.first != 0) + + // rjf: has callstack info? -> select unwind + RD_WatchViewCallStackFrameInfo callstack_frame_info = rd_callstack_frame_info_from_num(&block_ranges, global_row_idx); + if(callstack_frame_info.thread != &ctrl_entity_nil) { - file_path = lines.first->v.file_path; - pt = lines.first->v.pt; + rd_cmd(RD_CmdKind_SelectThread, .thread = callstack_frame_info.thread->handle); + rd_cmd(RD_CmdKind_SelectUnwind, + .unwind_count = callstack_frame_info.unwind_index, + .inline_depth = callstack_frame_info.inline_depth); + } + + // rjf: can edit? -> begin editing + else if(cell_can_edit) + { + rd_cmd(RD_CmdKind_Edit); + } + + // rjf: cannot edit, has addr info? -> go to address + else + { + U64 vaddr = cell_eval.value.u64; + CTRL_Entity *process = rd_ctrl_entity_from_eval_space(cell_eval.space); + CTRL_Entity *module = ctrl_module_from_process_vaddr(process, vaddr); + DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); + U64 voff = ctrl_voff_from_vaddr(module, vaddr); + D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, voff); + String8 file_path = {0}; + TxtPt pt = {0}; + if(lines.first != 0) + { + file_path = lines.first->v.file_path; + pt = lines.first->v.pt; + } + rd_cmd(RD_CmdKind_FindCodeLocation, + .process = process->handle, + .vaddr = vaddr, + .file_path = file_path, + .cursor = pt); } - rd_cmd(RD_CmdKind_FindCodeLocation, - .process = process->handle, - .vaddr = vaddr, - .file_path = file_path, - .cursor = pt); } - // rjf: double-click, not editable, callstack frame -> select frame -#if 0 // TODO(rjf): @blocks - if(ui_double_clicked(sig) && !cell_can_edit && semantic_idx < frame_rows_count) - { - FrameRow *frame_row = &frame_rows[semantic_idx]; - rd_cmd(RD_CmdKind_SelectUnwind, - .unwind_count = frame_row->unwind_idx, - .inline_depth = frame_row->inline_depth); - } -#endif - // rjf: hovering with inheritance string -> show tooltip if(ui_hovering(sig) && cell_inheritance_string.size != 0) UI_Tooltip { @@ -5459,7 +5534,7 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(call_stack) rd_watch_view_init(wv); rd_watch_view_column_alloc(wv, RD_WatchViewColumnKind_CallStackFrameSelection, 0.05f); rd_watch_view_column_alloc(wv, RD_WatchViewColumnKind_CallStackFrame, 0.50f, .display_string = str8_lit("Symbol"), .dequote_string = 1); - rd_watch_view_column_alloc(wv, RD_WatchViewColumnKind_Member, 0.20f, .string = str8_lit("vaddr"), .display_string = str8_lit("Address")); + rd_watch_view_column_alloc(wv, RD_WatchViewColumnKind_Member, 0.20f, .string = str8_lit("vaddr"), .display_string = str8_lit("Address"), .view_rule = str8_lit("cast:U64")); rd_watch_view_column_alloc(wv, RD_WatchViewColumnKind_Module, 0.25f, .string = str8_lit("module.str"), .display_string = str8_lit("Module"), .dequote_string = 1, .is_non_code = 1); } rd_watch_view_build(wv, 0, str8_lit("current_thread.callstack.v"), str8_lit("array:current_thread.callstack.count, hex"), 0, 10, rect); diff --git a/src/raddbg/raddbg_views.h b/src/raddbg/raddbg_views.h index 9b02542e..c49a52a6 100644 --- a/src/raddbg/raddbg_views.h +++ b/src/raddbg/raddbg_views.h @@ -125,6 +125,14 @@ struct RD_WatchViewCollectionInfo RD_Entity *entity; }; +typedef struct RD_WatchViewCallStackFrameInfo RD_WatchViewCallStackFrameInfo; +struct RD_WatchViewCallStackFrameInfo +{ + CTRL_Entity *thread; + U64 unwind_index; + U64 inline_depth; +}; + typedef struct RD_WatchViewTextEditState RD_WatchViewTextEditState; struct RD_WatchViewTextEditState { @@ -181,8 +189,9 @@ internal B32 rd_watch_view_point_match(RD_WatchViewPoint a, RD_WatchViewPoint b) internal RD_WatchViewPoint rd_watch_view_point_from_tbl(EV_BlockRangeList *block_ranges, Vec2S64 tbl); internal Vec2S64 rd_tbl_from_watch_view_point(EV_BlockRangeList *block_ranges, RD_WatchViewPoint pt); -//- rjf: table coordinates -> entities in collectons +//- rjf: table coordinates -> backing information internal RD_WatchViewCollectionInfo rd_collection_info_from_num(EV_BlockRangeList *block_ranges, S64 num); +internal RD_WatchViewCallStackFrameInfo rd_callstack_frame_info_from_num(EV_BlockRangeList *block_ranges, S64 num); //- rjf: row -> kind internal RD_WatchViewRowKind rd_watch_view_row_kind_from_row(RD_WatchViewFlags flags, EV_Row *row);