From 404ad620ef76fc2527b154fec38eae54f5fafc6e Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Sat, 15 Feb 2025 13:32:46 -0800 Subject: [PATCH] more convergence; split scheduler into machines, process, and threads tabs. most people just care about threads, and so that should be the default/common case --- src/raddbg/generated/raddbg.meta.c | 6 +- src/raddbg/generated/raddbg.meta.h | 2 +- src/raddbg/raddbg.mdesk | 4 +- src/raddbg/raddbg_core.c | 194 +++++++++++++++++++++++++++-- src/raddbg/raddbg_views.c | 7 +- 5 files changed, 201 insertions(+), 12 deletions(-) diff --git a/src/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index 0d3ece11..433a1468 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[283] = +RD_VocabInfo rd_vocab_info_table[285] = { {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}, @@ -53,7 +53,9 @@ RD_VocabInfo rd_vocab_info_table[283] = {str8_lit_comp("vtx_size"), str8_lit_comp("vtx_sizes"), str8_lit_comp("Vertex Buffer Size"), str8_lit_comp("Vertex Buffer Sizes"), RD_IconKind_Null}, {str8_lit_comp("label"), str8_lit_comp("labels"), str8_lit_comp("Label"), str8_lit_comp("Labels"), RD_IconKind_Null}, {str8_lit_comp("thread"), str8_lit_comp("threads"), str8_lit_comp("Thread"), str8_lit_comp("Threads"), RD_IconKind_Thread}, -{str8_lit_comp("process"), str8_lit_comp("processes"), str8_lit_comp("Process"), str8_lit_comp("Processes"), RD_IconKind_Threads}, +{str8_lit_comp("threads"), str8_lit_comp(""), str8_lit_comp("Threads"), str8_lit_comp(""), RD_IconKind_Threads}, +{str8_lit_comp("process"), str8_lit_comp("processes"), str8_lit_comp("Process"), str8_lit_comp("Processes"), RD_IconKind_Scheduler}, +{str8_lit_comp("processes"), str8_lit_comp(""), str8_lit_comp("Processes"), str8_lit_comp(""), RD_IconKind_Scheduler}, {str8_lit_comp("machine"), str8_lit_comp("machines"), str8_lit_comp("Machine"), str8_lit_comp("Machines"), RD_IconKind_Machine}, {str8_lit_comp("module"), str8_lit_comp("modules"), str8_lit_comp("Module"), str8_lit_comp("Modules"), RD_IconKind_Module}, {str8_lit_comp("getting_started"), str8_lit_comp(""), str8_lit_comp("Getting Started"), str8_lit_comp(""), RD_IconKind_QuestionMark}, diff --git a/src/raddbg/generated/raddbg.meta.h b/src/raddbg/generated/raddbg.meta.h index f1e41461..ac4d4898 100644 --- a/src/raddbg/generated/raddbg.meta.h +++ b/src/raddbg/generated/raddbg.meta.h @@ -555,7 +555,7 @@ RD_Query query; .os_event = rd_regs()->os_event,\ C_LINKAGE_BEGIN -extern RD_VocabInfo rd_vocab_info_table[283]; +extern RD_VocabInfo rd_vocab_info_table[285]; extern RD_NameSchemaInfo rd_name_schema_info_table[10]; extern Rng1U64 rd_reg_slot_range_table[38]; extern String8 rd_binding_version_remap_old_name_table[8]; diff --git a/src/raddbg/raddbg.mdesk b/src/raddbg/raddbg.mdesk index da45f4af..d4644d21 100644 --- a/src/raddbg/raddbg.mdesk +++ b/src/raddbg/raddbg.mdesk @@ -65,7 +65,9 @@ RD_VocabTable: {vtx_size _ "Vertex Buffer Size" _ Null } {label _ "Label" _ Null } {thread _ "Thread" _ Thread } - {process processes "Process" "Processes" Threads } + {threads "" "Threads" "" Threads } + {process processes "Process" "Processes" Scheduler } + {processes "" "Processes" "" Scheduler } {machine _ "Machine" _ Machine } {module _ "Module" _ Module } {getting_started "" "Getting Started" "" QuestionMark } diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index b3b80cf4..4678613c 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -560,6 +560,161 @@ E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(top_level_cfg) return num; } +//////////////////////////////// +//~ rjf: Machine Eval Hooks + +E_LOOKUP_INFO_FUNCTION_DEF(machine) +{ + E_LookupInfo result = E_LOOKUP_INFO_FUNCTION_NAME(default)(arena, lhs, filter); + result.named_expr_count += 1; + return result; +} + +E_LOOKUP_ACCESS_FUNCTION_DEF(machine) +{ + Temp scratch = scratch_begin(&arena, 1); + E_LookupAccess result = E_LOOKUP_ACCESS_FUNCTION_NAME(default)(arena, kind, lhs, rhs, user_data); + if(kind == E_ExprKind_MemberAccess && rhs->kind == E_ExprKind_LeafMember && str8_match(rhs->string, str8_lit("processes"), 0)) + { + E_Eval eval = e_eval_from_expr(scratch.arena, lhs); + CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(eval.space); + result.irtree_and_type.root = e_irtree_set_space(arena, e_space_make(RD_EvalSpaceKind_MetaCtrlEntity), e_irtree_leaf_u128(arena, u128_make(entity->handle.machine_id, entity->handle.dmn_handle.u64[0]))); + result.irtree_and_type.type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("machine_processes")); + result.irtree_and_type.mode = E_Mode_Offset; + } + scratch_end(scratch); + return result; +} + +E_LOOKUP_RANGE_FUNCTION_DEF(machine) +{ + Temp scratch = scratch_begin(&arena, 1); + E_LOOKUP_RANGE_FUNCTION_NAME(default)(arena, lhs, idx_range, exprs, exprs_strings, user_data); + E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(scratch.arena, lhs); + E_Type *lhs_type = e_type_from_key__cached(lhs_irtree.type_key); + String8 extras[] = + { + str8_lit("processes"), + }; + Rng1U64 extras_idx_range = r1u64(lhs_type->count, lhs_type->count + ArrayCount(extras)); + Rng1U64 extras_read_range = intersect_1u64(extras_idx_range, idx_range); + U64 extras_count = dim_1u64(extras_read_range); + for(U64 extras_idx = 0; extras_idx < extras_count; extras_idx += 1) + { + U64 out_idx = extras_idx_range.min - idx_range.min + extras_idx; + exprs[out_idx] = e_expr_irext_member_access(arena, lhs, &lhs_irtree, extras[extras_idx]); + } + scratch_end(scratch); +} + +//////////////////////////////// +//~ rjf: Process Eval Hooks + +E_LOOKUP_INFO_FUNCTION_DEF(process) +{ + E_LookupInfo result = E_LOOKUP_INFO_FUNCTION_NAME(default)(arena, lhs, filter); + result.named_expr_count += 1; + return result; +} + +E_LOOKUP_ACCESS_FUNCTION_DEF(process) +{ + Temp scratch = scratch_begin(&arena, 1); + E_LookupAccess result = E_LOOKUP_ACCESS_FUNCTION_NAME(default)(arena, kind, lhs, rhs, user_data); + if(kind == E_ExprKind_MemberAccess && rhs->kind == E_ExprKind_LeafMember && str8_match(rhs->string, str8_lit("modules"), 0)) + { + E_Eval eval = e_eval_from_expr(scratch.arena, lhs); + CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(eval.space); + result.irtree_and_type.root = e_irtree_set_space(arena, rd_eval_space_from_ctrl_entity(entity, RD_EvalSpaceKind_MetaCtrlEntity), e_irtree_leaf_u128(arena, u128_make(entity->handle.machine_id, entity->handle.dmn_handle.u64[0]))); + result.irtree_and_type.type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("process_modules")); + result.irtree_and_type.mode = E_Mode_Offset; + } + if(kind == E_ExprKind_MemberAccess && rhs->kind == E_ExprKind_LeafMember && str8_match(rhs->string, str8_lit("threads"), 0)) + { + E_Eval eval = e_eval_from_expr(scratch.arena, lhs); + CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(eval.space); + result.irtree_and_type.root = e_irtree_set_space(arena, e_space_make(RD_EvalSpaceKind_MetaCtrlEntity), e_irtree_leaf_u128(arena, u128_make(entity->handle.machine_id, entity->handle.dmn_handle.u64[0]))); + result.irtree_and_type.type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("process_threads")); + result.irtree_and_type.mode = E_Mode_Offset; + } + scratch_end(scratch); + return result; +} + +E_LOOKUP_RANGE_FUNCTION_DEF(process) +{ + Temp scratch = scratch_begin(&arena, 1); + E_LOOKUP_RANGE_FUNCTION_NAME(default)(arena, lhs, idx_range, exprs, exprs_strings, user_data); + E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(scratch.arena, lhs); + E_Type *lhs_type = e_type_from_key__cached(lhs_irtree.type_key); + String8 extras[] = + { + str8_lit("modules"), + //str8_lit("threads"), + }; + Rng1U64 extras_idx_range = r1u64(lhs_type->count, lhs_type->count + ArrayCount(extras)); + Rng1U64 extras_read_range = intersect_1u64(extras_idx_range, idx_range); + U64 extras_count = dim_1u64(extras_read_range); + for(U64 extras_idx = 0; extras_idx < extras_count; extras_idx += 1) + { + U64 out_idx = extras_idx_range.min - idx_range.min + extras_idx; + exprs[out_idx] = e_expr_irext_member_access(arena, lhs, &lhs_irtree, extras[0]); + } + scratch_end(scratch); +} + +typedef struct RD_ProcessLookupAccel RD_ProcessLookupAccel; +struct RD_ProcessLookupAccel +{ + CTRL_EntityArray children; +}; + +E_LOOKUP_INFO_FUNCTION_DEF(process_modules) +{ + E_LookupInfo result = {0}; + Temp scratch = scratch_begin(&arena, 1); + { + E_OpList oplist = e_oplist_from_irtree(scratch.arena, lhs->root); + String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); + E_Interpretation interpret = e_interpret(bytecode); + CTRL_Entity *process = rd_ctrl_entity_from_eval_space(interpret.space); + CTRL_EntityList modules = {0}; + for(CTRL_Entity *child = process->first; child != &ctrl_entity_nil; child = child->next) + { + if(child->kind == CTRL_EntityKind_Module) + { + ctrl_entity_list_push(scratch.arena, &modules, child); + } + } + RD_ProcessLookupAccel *accel = push_array(arena, RD_ProcessLookupAccel, 1); + accel->children = ctrl_entity_array_from_list(arena, &modules); + result.user_data = accel; + result.idxed_expr_count = modules.count; + } + scratch_end(scratch); + return result; +} + +E_LOOKUP_ACCESS_FUNCTION_DEF(process_modules) +{ + E_LookupAccess result = {{&e_irnode_nil}}; + if(kind == E_ExprKind_ArrayIndex) + { + Temp scratch = scratch_begin(&arena, 1); + RD_ProcessLookupAccel *accel = (RD_ProcessLookupAccel *)user_data; + E_Value rhs_value = e_value_from_expr(rhs); + if(0 <= rhs_value.u64 && rhs_value.u64 < accel->children.count) + { + CTRL_Entity *entity = accel->children.v[rhs_value.u64]; + result.irtree_and_type.root = e_irtree_set_space(arena, rd_eval_space_from_ctrl_entity(entity, RD_EvalSpaceKind_MetaCtrlEntity), e_irtree_const_u(arena, 0)); + result.irtree_and_type.type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, str8_lit("module")); + result.irtree_and_type.mode = E_Mode_Offset; + } + scratch_end(scratch); + } + return result; +} + //////////////////////////////// //~ rjf: Thread Eval Hooks @@ -2854,6 +3009,16 @@ rd_title_fstrs_from_ctrl_entity(Arena *arena, CTRL_Entity *entity, Vec4F32 secon dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); } + //- rjf: push frozen icon, if frozen + if((entity->kind == CTRL_EntityKind_Machine || + entity->kind == CTRL_EntityKind_Process || + entity->kind == CTRL_EntityKind_Thread) && + ctrl_entity_tree_is_frozen(entity)) + { + dr_fstrs_push_new(arena, &result, ¶ms, rd_icon_kind_text_table[RD_IconKind_Locked], .font = rd_font_from_slot(RD_FontSlot_Icons), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), .color = rd_rgba_from_theme_color(RD_ThemeColor_TextNegative)); + dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); + } + //- rjf: push containing process prefix if(entity->kind == CTRL_EntityKind_Thread || entity->kind == CTRL_EntityKind_Module) @@ -2867,6 +3032,7 @@ rd_title_fstrs_from_ctrl_entity(Arena *arena, CTRL_Entity *entity, Vec4F32 secon if(process_name.size != 0) { dr_fstrs_push_new(arena, &result, ¶ms, process_name, .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main), .color = process_color); + dr_fstrs_push_new(arena, &result, ¶ms, push_str8f(arena, "(PID: %I64u)", process->id), .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main), .color = secondary_color, .size = size*0.9f); dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" / "), .color = secondary_color); } } @@ -2878,6 +3044,13 @@ rd_title_fstrs_from_ctrl_entity(Arena *arena, CTRL_Entity *entity, Vec4F32 secon .raster_flags = rd_raster_flags_from_slot(name_is_code ? RD_FontSlot_Code : RD_FontSlot_Main), .color = color); + //- rjf: push PID + if(entity->kind == CTRL_EntityKind_Process) + { + dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" ")); + dr_fstrs_push_new(arena, &result, ¶ms, push_str8f(arena, " (PID: %I64u)", entity->id), .font = rd_font_from_slot(RD_FontSlot_Main), .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Main), .color = secondary_color, .size = size*0.85f); + } + //- rjf: threads get callstack extras if(entity->kind == CTRL_EntityKind_Thread && include_extras) { @@ -12588,8 +12761,8 @@ rd_frame(void) } evallable_ctrl_table[] = { - { str8_lit("machine") }, - { str8_lit("process") }, + { str8_lit("machine"), .info = E_LOOKUP_INFO_FUNCTION_NAME(machine), .access = E_LOOKUP_ACCESS_FUNCTION_NAME(machine), .range = E_LOOKUP_RANGE_FUNCTION_NAME(machine) }, + { str8_lit("process"), .info = E_LOOKUP_INFO_FUNCTION_NAME(process), .access = E_LOOKUP_ACCESS_FUNCTION_NAME(process), .range = E_LOOKUP_RANGE_FUNCTION_NAME(process) }, { str8_lit("thread"), .info = E_LOOKUP_INFO_FUNCTION_NAME(thread), .access = E_LOOKUP_ACCESS_FUNCTION_NAME(thread), .range = E_LOOKUP_RANGE_FUNCTION_NAME(thread) }, { str8_lit("module") }, }; @@ -12669,6 +12842,9 @@ rd_frame(void) e_lookup_rule_map_insert_new(scratch.arena, ctx->lookup_rule_map, str8_lit("call_stack"), .info = E_LOOKUP_INFO_FUNCTION_NAME(call_stack), .access = E_LOOKUP_ACCESS_FUNCTION_NAME(call_stack)); + e_lookup_rule_map_insert_new(scratch.arena, ctx->lookup_rule_map, str8_lit("process_modules"), + .info = E_LOOKUP_INFO_FUNCTION_NAME(process_modules), + .access = E_LOOKUP_ACCESS_FUNCTION_NAME(process_modules)); } //- rjf: add macro for collections with specific lookup rules (but no unique id rules) @@ -14127,7 +14303,9 @@ X(call_stack)\ X(breakpoints)\ X(watch_pins)\ X(targets)\ -X(scheduler)\ +X(threads)\ +X(processes)\ +X(machines)\ X(modules)\ Y(output, text, "query:output")\ Y(disasm, disasm, "")\ @@ -14222,9 +14400,11 @@ Z(getting_started) RD_Cfg *root_1_0 = rd_cfg_new(root_1, str8_lit("0.50")); RD_Cfg *root_1_1 = rd_cfg_new(root_1, str8_lit("0.50")); rd_cfg_insert_child(root_1_0, root_1_0->last, targets); - rd_cfg_insert_child(root_1_1, root_1_1->last, scheduler); + rd_cfg_insert_child(root_1_1, root_1_1->last, threads); + rd_cfg_insert_child(root_1_1, root_1_1->last, processes); + rd_cfg_insert_child(root_1_1, root_1_1->last, machines); rd_cfg_new(targets, str8_lit("selected")); - rd_cfg_new(scheduler, str8_lit("selected")); + rd_cfg_new(threads, str8_lit("selected")); // rjf: root 0_0 split RD_Cfg *root_0_0_0 = rd_cfg_new(root_0_0, str8_lit("0.25")); @@ -14294,11 +14474,11 @@ Z(getting_started) rd_cfg_insert_child(root_0_0, root_0_0->last, watches); rd_cfg_insert_child(root_0_0, root_0_0->last, types); rd_cfg_new(watches, str8_lit("selected")); - rd_cfg_insert_child(root_0_1, root_0_1->last, scheduler); + rd_cfg_insert_child(root_0_1, root_0_1->last, threads); rd_cfg_insert_child(root_0_1, root_0_1->last, targets); rd_cfg_insert_child(root_0_1, root_0_1->last, breakpoints); rd_cfg_insert_child(root_0_1, root_0_1->last, watch_pins); - rd_cfg_new(scheduler, str8_lit("selected")); + rd_cfg_new(threads, str8_lit("selected")); rd_cfg_insert_child(root_0_2, root_0_2->last, disasm); rd_cfg_insert_child(root_0_2, root_0_2->last, output); rd_cfg_new(disasm, str8_lit("selected")); diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index 55736d88..92e3d6b5 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -3398,7 +3398,12 @@ RD_VIEW_UI_FUNCTION_DEF(text) DI_KeyList dbgi_keys = {0}; if(!file_is_missing) { - RD_CodeViewBuildResult result = rd_code_view_build(scratch.arena, cv, RD_CodeViewBuildFlag_All, code_area_rect, data, &info, 0, r1u64(0, 0), di_key_zero()); + RD_CodeViewBuildFlags flags = RD_CodeViewBuildFlag_All; + if(rd_regs()->file_path.size == 0) + { + flags &= ~RD_CodeViewBuildFlag_Margins; + } + RD_CodeViewBuildResult result = rd_code_view_build(scratch.arena, cv, flags, code_area_rect, data, &info, 0, r1u64(0, 0), di_key_zero()); dbgi_keys = result.dbgi_keys; }