From 8602e5b23e243bfdac1b4b59355553375c3826fb Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Wed, 31 Jan 2024 12:24:57 -0800 Subject: [PATCH] first pass at thread-locals view --- src/df/gfx/df_gfx.c | 88 +++++++++++++++++++++++++++++++++++++++++++ src/df/gfx/df_views.c | 82 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 169 insertions(+), 1 deletion(-) diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index 755dfb0e..b3d262f6 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -7413,6 +7413,94 @@ df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DBGI_Scope *scop list.count += 1; } }break; + + ////////////////////////////// + //- rjf: all tlocals -> produce rows for visible range + // + case DF_EvalVizBlockKind_AllThreadLocals: + { + DF_Entity *thread = df_entity_from_handle(ctrl_ctx->thread); + DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); + U64 thread_rip_unwind_vaddr = df_query_cached_rip_from_thread_unwind(thread, ctrl_ctx->unwind_count); + DF_Entity *module = df_module_from_process_vaddr(process, thread_rip_unwind_vaddr); + for(U64 idx = visible_idx_range.min; idx < visible_idx_range.max; idx += 1) + { + // rjf: unpack global info + RADDBG_ThreadVariable *thread_var = raddbg_element_from_idx(parse_ctx->rdbg, thread_variables, idx); + RADDBG_TypeNode *type_node = raddbg_element_from_idx(parse_ctx->rdbg, type_nodes, thread_var->type_idx); + U64 name_size = 0; + U8 *name_base = raddbg_string_from_idx(parse_ctx->rdbg, thread_var->name_string_idx, &name_size); + String8 name = str8(name_base, name_size); + + // rjf: get keys for this row + DF_ExpandKey parent_key = block->parent_key; + DF_ExpandKey key = block->key; + key.child_num = idx+1; + + // rjf: get eval for this tlocal + DF_Eval eval = df_eval_from_string(arena, scope, ctrl_ctx, parse_ctx, name); + + // rjf: get view rules + String8 view_rule_string = df_eval_view_rule_from_key(eval_view, key); + DF_CfgTable view_rule_table = df_cfg_table_from_inheritance(scratch.arena, &block->cfg_table); + df_cfg_table_push_unparsed_string(scratch.arena, &view_rule_table, view_rule_string, DF_CfgSrc_User); + + // rjf: apply view rules to eval + { + eval = df_dynamically_typed_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, eval); + eval = df_eval_from_eval_cfg_table(arena, scope, ctrl_ctx, parse_ctx, eval, &view_rule_table); + } + + // rjf: build row + String8List display_strings = df_single_line_eval_value_strings_from_eval(scratch.arena, DF_EvalVizStringFlag_ReadOnlyDisplayRules, parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, default_radix, font, font_size, 500, 0, eval, &view_rule_table); + String8List edit_strings = df_single_line_eval_value_strings_from_eval(scratch.arena, 0, parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, default_radix, font, font_size, 500, 0, eval, &view_rule_table); + DF_EvalVizRow *row = push_array(arena, DF_EvalVizRow, 1); + row->eval = eval; + row->expr = name; + row->display_value = str8_list_join(arena, &display_strings, 0); + row->edit_value = str8_list_join(arena, &edit_strings, 0); + row->value_ui_rule_node = value_ui_rule_node; + row->value_ui_rule_spec = value_ui_rule_spec; + row->expand_ui_rule_node = expand_ui_rule_node; + row->expand_ui_rule_spec = expand_ui_rule_spec; + if(tg_kind_from_key(eval.type_key) != TG_Kind_Null) + { + for(TG_Key t = eval.type_key;; t = tg_unwrapped_direct_from_graph_raddbg_key(parse_ctx->type_graph, parse_ctx->rdbg, t)) + { + TG_Kind kind = tg_kind_from_key(t); + if(kind == TG_Kind_Null) + { + break; + } + if(block->eval.mode != EVAL_EvalMode_NULL && ((TG_Kind_FirstBasic <= kind && kind <= TG_Kind_LastBasic) || kind == TG_Kind_Ptr || kind == TG_Kind_LRef || kind == TG_Kind_RRef)) + { + row->flags |= DF_EvalVizRowFlag_CanEditValue; + } + if(expandability_required || + kind == TG_Kind_Struct || + kind == TG_Kind_Union || + kind == TG_Kind_Class || + kind == TG_Kind_Array) + { + row->flags |= DF_EvalVizRowFlag_CanExpand; + } + if(row->flags & DF_EvalVizRowFlag_CanExpand) + { + break; + } + if(block->eval.mode == EVAL_EvalMode_NULL) + { + break; + } + } + } + row->depth = block->depth; + row->parent_key = parent_key; + row->key = key; + SLLQueuePush(list.first, list.last, row); + list.count += 1; + } + }break; } } scratch_end(scratch); diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 32f5ee7a..03d52c69 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -822,7 +822,84 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF // case DF_EvalWatchViewFillKind_ThreadLocals: { - // TODO(rjf) + // rjf: unpack + DF_Entity *thread = df_entity_from_handle(ctrl_ctx->thread); + DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); + U64 thread_rip_unwind_vaddr = df_query_cached_rip_from_thread_unwind(thread, ctrl_ctx->unwind_count); + DF_Entity *module = df_module_from_process_vaddr(process, thread_rip_unwind_vaddr); + + // rjf: build block for all tlocals + DF_ExpandKey parent_key = df_expand_key_make(5381, 0); + DF_ExpandKey root_key = df_expand_key_make(df_hash_from_expand_key(parent_key), 0); + RADDBG_Parsed *rdbg = parse_ctx->rdbg; + DF_EvalVizBlock *tlocals_block = push_array(arena, DF_EvalVizBlock, 1); + SLLQueuePush(blocks.first, blocks.last, tlocals_block); + tlocals_block->kind = DF_EvalVizBlockKind_AllThreadLocals; + tlocals_block->visual_idx_range = tlocals_block->semantic_idx_range = r1u64(1, rdbg->thread_variables_count); + tlocals_block->parent_key = parent_key; + tlocals_block->key = root_key; + blocks.count += 1; + blocks.total_visual_row_count += dim_1u64(tlocals_block->visual_idx_range); + blocks.total_semantic_row_count += dim_1u64(tlocals_block->semantic_idx_range); + + // rjf: split tlocals block per-expansion + df_expand_set_expansion(eval_view->arena, &eval_view->expand_tree_table, df_expand_key_zero(), parent_key, 1); + DF_ExpandNode *root_node = df_expand_node_from_key(&eval_view->expand_tree_table, parent_key); + for(DF_ExpandNode *child = root_node->first; child != 0; child = child->next) + { + U64 child_num = child->key.child_num; + U64 child_idx = child_num-1; + if(child_idx >= rdbg->thread_variables_count) + { + continue; + } + + // rjf: truncate existing memblock + tlocals_block->visual_idx_range.max = child_idx; + tlocals_block->semantic_idx_range.max = child_idx; + + // rjf: build inheriting cfg table + DF_CfgTable child_cfg = {0}; + { + String8 view_rule_string = df_eval_view_rule_from_key(eval_view, df_expand_key_make(df_hash_from_expand_key(parent_key), child_num)); + if(view_rule_string.size != 0) + { + df_cfg_table_push_unparsed_string(arena, &child_cfg, view_rule_string, DF_CfgSrc_User); + } + } + + // rjf: unpack tlocal + RADDBG_ThreadVariable *thread_var = raddbg_element_from_idx(parse_ctx->rdbg, thread_variables, child_idx); + RADDBG_TypeNode *type_node = raddbg_element_from_idx(parse_ctx->rdbg, type_nodes, thread_var->type_idx); + U64 name_size = 0; + U8 *name_base = raddbg_string_from_idx(parse_ctx->rdbg, thread_var->name_string_idx, &name_size); + String8 name = str8(name_base, name_size); + + // rjf: produce eval for the expanded tlocal + DF_Eval eval = df_eval_from_string(arena, scope, ctrl_ctx, parse_ctx, name); + + // rjf: recurse for sub-block + { + blocks.total_visual_row_count -= 1; + blocks.total_semantic_row_count -= 1; + df_append_viz_blocks_for_parent__rec(arena, scope, eval_view, ctrl_ctx, parse_ctx, parent_key, child->key, name, eval, &child_cfg, 0, &blocks); + } + + // rjf: make new memblock for remainder (if any) + if(child_idx+1 < rdbg->thread_variables_count) + { + DF_EvalVizBlock *next_tlocals_block = push_array(arena, DF_EvalVizBlock, 1); + next_tlocals_block->kind = DF_EvalVizBlockKind_AllThreadLocals; + next_tlocals_block->visual_idx_range = r1u64(child_idx+1, rdbg->thread_variables_count); + next_tlocals_block->semantic_idx_range= r1u64(child_idx+1, rdbg->thread_variables_count); + next_tlocals_block->depth = 0; + next_tlocals_block->parent_key = parent_key; + next_tlocals_block->key = root_key; + SLLQueuePush(blocks.first, blocks.last, next_tlocals_block); + blocks.count += 1; + tlocals_block = next_tlocals_block; + } + } }break; //////////////////////////// @@ -6807,6 +6884,9 @@ DF_VIEW_CMD_FUNCTION_DEF(ThreadLocals) {} DF_VIEW_UI_FUNCTION_DEF(ThreadLocals) { ProfBeginFunction(); + DF_EvalWatchViewState *ewv = df_view_user_state(view, DF_EvalWatchViewState); + df_eval_watch_view_init(ewv, view, DF_EvalWatchViewFillKind_ThreadLocals); + df_eval_watch_view_build(ws, panel, view, ewv, 0, 10, rect); ProfEnd(); }