checkpoint in implementing dynamic type resolution in the eval system, for taking a base-class-ptr & by-default patching in the appropriate debug-info-determined derived type

This commit is contained in:
Ryan Fleury
2024-01-16 17:33:17 -08:00
parent adbe42c907
commit d849b83acb
5 changed files with 130 additions and 18 deletions
+1 -1
View File
@@ -47,7 +47,7 @@ set cl_debug= call cl /Od /D_DEBUG %cl_common%
set cl_release= call cl /O2 /DNDEBUG %cl_common%
set clang_debug= call clang -g -O0 -D_DEBUG %clang_common%
set clang_release= call clang -g -O3 -DNDEBUG %clang_common%
set cl_link= /link /natvis:"%~dp0\src\natvis\base.natvis"
set cl_link= /link /INCREMENTAL:NO /natvis:"%~dp0\src\natvis\base.natvis"
set clang_link= -Xlinker /natvis:"%~dp0\src\natvis\base.natvis"
set cl_out= /out:
set clang_out= -o
+109 -17
View File
@@ -2869,23 +2869,6 @@ df_trap_net_from_thread__step_into_line(Arena *arena, DF_Entity *thread)
{
trap_addr = point->jump_dest_vaddr;
flags &= ~CTRL_TrapFlag_SingleStepAfterHit;
// rjf: read instruction one layer deep after a jump and determine if
// it is just jumping to an unconditional jump (e.g. a function
// dispatch table) - if so, then just follow one more layer
String8 dst_machine_code = {0};
dst_machine_code.str = push_array_no_zero(scratch.arena, U8, max_instruction_size_from_arch(arch));
dst_machine_code.size = ctrl_process_read(process->ctrl_machine_id, process->ctrl_handle, r1u64(trap_addr, trap_addr+max_instruction_size_from_arch(arch)), dst_machine_code.str);
if(dst_machine_code.size != 0)
{
DF_Inst inst = df_single_inst_from_machine_code(scratch.arena, arch, 0, dst_machine_code);
if((inst.flags & DF_InstFlag_UnconditionalJump ||
inst.flags & DF_InstFlag_Call) &&
inst.rel_voff != 0)
{
trap_addr = (U64)(trap_addr + (S64)((S32)inst.rel_voff));
}
}
}
}
@@ -3649,6 +3632,7 @@ df_set_thread_rip(DF_Entity *thread, U64 vaddr)
df_state->unwind_cache_invalidated = 1;
df_state->locals_cache_invalidated = 1;
df_state->member_cache_invalidated = 1;
df_state->local_dynamic_type_override_cache_invalidated = 1;
}
// rjf: early mutation of unwind cache for immediate frontend effect
@@ -3914,6 +3898,7 @@ df_eval_parse_ctx_from_module_voff(DBGI_Scope *scope, DF_Entity *module, U64 vof
EVAL_String2NumMap *reg_alias_map = ctrl_string2alias_from_arch(arch);
EVAL_String2NumMap *locals_map = df_query_cached_locals_map_from_binary_voff(binary, voff);
EVAL_String2NumMap *member_map = df_query_cached_member_map_from_binary_voff(binary, voff);
EVAL_String2NumMap *local_dynamic_type_override_map = df_query_cached_local_dynamic_type_override_map_from_module_voff(module, voff);
//- rjf: build ctx
EVAL_ParseCtx ctx = zero_struct;
@@ -3926,6 +3911,7 @@ df_eval_parse_ctx_from_module_voff(DBGI_Scope *scope, DF_Entity *module, U64 vof
ctx.reg_alias_map = reg_alias_map;
ctx.locals_map = locals_map;
ctx.member_map = member_map;
ctx.local_dynamic_type_override_map = local_dynamic_type_override_map;
}
scratch_end(scratch);
return ctx;
@@ -4038,6 +4024,7 @@ df_eval_parse_ctx_from_src_loc(DBGI_Scope *scope, DF_Entity *file, TxtPt pt)
ctx.reg_alias_map = &eval_string2num_map_nil;
ctx.locals_map = &eval_string2num_map_nil;
ctx.member_map = &eval_string2num_map_nil;
ctx.local_dynamic_type_override_map = &eval_string2num_map_nil;
}
scratch_end(scratch);
@@ -4225,6 +4212,49 @@ internal DF_Eval
df_eval_from_eval_cfg_table(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_Eval eval, DF_CfgTable *cfg)
{
ProfBeginFunction();
#if 0
//- rjf: pointer-to-struct -> read result & find "derived class" for "real"
// type of evaluation
{
TG_Kind kind = tg_kind_from_key(eval.type_key);
if(kind == TG_Kind_Ptr)
{
TG_Key direct_key = tg_direct_from_graph_raddbg_key(parse_ctx->type_graph, parse_ctx->rdbg, eval.type_key);
TG_Kind direct_kind = tg_kind_from_key(direct_key);
if((direct_kind == TG_Kind_Struct || direct_kind == TG_Kind_Class) && parse_ctx->rdbg->global_vmap != 0)
{
DF_Eval ptr_addr_eval = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, eval);
U64 vaddr = ptr_addr_eval.imm_u64;
String8 ptr_val_memory = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(vaddr, vaddr+bit_size_from_arch(parse_ctx->arch)/8));
if(ptr_val_memory.size >= bit_size_from_arch(parse_ctx->arch)/8)
{
U64 vtable_ptr_maybe = 0;
MemoryCopy(&vtable_ptr_maybe, ptr_val_memory.str, bit_size_from_arch(parse_ctx->arch)/8);
U64 voff = df_voff_from_vaddr(module, vtable_ptr_maybe);
U64 global_idx = raddbg_vmap_idx_from_voff(parse_ctx->rdbg->global_vmap, parse_ctx->rdbg->global_vmap_count, voff);
if(0 < global_idx && global_idx < parse_ctx->rdbg->global_variable_count)
{
RADDBG_GlobalVariable *global_var = &parse_ctx->rdbg->global_variables[global_idx];
if(global_var->link_flags & RADDBG_LinkFlag_TypeScoped &&
0 < global_var->container_idx && global_var->container_idx < parse_ctx->rdbg->udt_count)
{
RADDBG_UDT *udt = &parse_ctx->rdbg->udts[global_var->container_idx];
if(0 < udt->self_type_idx && udt->self_type_idx < parse_ctx->rdbg->type_node_count)
{
RADDBG_TypeNode *type = &parse_ctx->rdbg->type_nodes[udt->self_type_idx];
TG_Key derived_type_key = tg_key_ext(tg_kind_from_raddbg_type_kind(type->kind), (U64)udt->self_type_idx);
eval.type_key = tg_cons_type_make(parse_ctx->type_graph, TG_Kind_Ptr, derived_type_key, 0);
}
}
}
}
}
}
}
#endif
//- rjf: apply view rules
for(DF_CfgVal *val = cfg->first_val; val != 0 && val != &df_g_nil_cfg_val; val = val->linear_next)
{
DF_CoreViewRuleSpec *spec = df_core_view_rule_spec_from_string(val->string);
@@ -6035,6 +6065,56 @@ df_query_cached_member_map_from_binary_voff(DF_Entity *binary, U64 voff)
return map;
}
internal EVAL_String2NumMap *
df_query_cached_local_dynamic_type_override_map_from_module_voff(DF_Entity *module, U64 voff)
{
ProfBeginFunction();
EVAL_String2NumMap *map = &eval_string2num_map_nil;
{
DF_RunLocalsCache *cache = &df_state->local_dynamic_type_override_cache;
if(cache->table_size == 0)
{
cache->table_size = 256;
cache->table = push_array(cache->arena, DF_RunLocalsCacheSlot, cache->table_size);
}
DF_Handle handle = df_handle_from_entity(module);
U64 hash = df_hash_from_string(str8_struct(&handle));
U64 slot_idx = hash % cache->table_size;
DF_RunLocalsCacheSlot *slot = &cache->table[slot_idx];
DF_RunLocalsCacheNode *node = 0;
for(DF_RunLocalsCacheNode *n = slot->first; n != 0; n = n->hash_next)
{
if(df_handle_match(n->binary, handle) && n->voff == voff)
{
node = n;
break;
}
}
if(node == 0)
{
DBGI_Scope *scope = dbgi_scope_open();
#if 0
EVAL_String2NumMap *map = df_push_member_map_from_binary_voff(cache->arena, scope, binary, voff);
if(map->slots_count != 0)
{
node = push_array(cache->arena, DF_RunLocalsCacheNode, 1);
node->binary = handle;
node->voff = voff;
node->locals_map = map;
SLLQueuePush_N(slot->first, slot->last, node, hash_next);
}
#endif
dbgi_scope_close(scope);
}
if(node != 0)
{
map = node->locals_map;
}
}
ProfEnd();
return map;
}
//- rjf: top-level command dispatch
internal void
@@ -6099,6 +6179,7 @@ df_core_init(String8 user_path, String8 profile_path, DF_StateDeltaHistory *hist
df_state->unwind_cache.arena = arena_alloc();
df_state->locals_cache.arena = arena_alloc();
df_state->member_cache.arena = arena_alloc();
df_state->local_dynamic_type_override_cache.arena = arena_alloc();
// rjf: set up eval view cache
df_state->eval_view_cache.slots_count = 4096;
@@ -6502,6 +6583,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
df_state->unwind_cache_invalidated = 1;
df_state->locals_cache_invalidated = 1;
df_state->member_cache_invalidated = 1;
df_state->local_dynamic_type_override_cache_invalidated = 1;
}
//- rjf: refresh unwind cache
@@ -6553,6 +6635,16 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
cache->table = 0;
}
//- rjf: clear local -> dynamic type override cache
if(df_state->local_dynamic_type_override_cache_invalidated && !df_ctrl_targets_running())
{
df_state->local_dynamic_type_override_cache_invalidated = 0;
DF_RunLocalsCache *cache = &df_state->local_dynamic_type_override_cache;
arena_clear(cache->arena);
cache->table_size = 0;
cache->table = 0;
}
scratch_end(scratch);
}
+3
View File
@@ -1135,6 +1135,8 @@ struct DF_State
DF_RunLocalsCache locals_cache;
B32 member_cache_invalidated;
DF_RunLocalsCache member_cache;
B32 local_dynamic_type_override_cache_invalidated;
DF_RunLocalsCache local_dynamic_type_override_cache;
// rjf: eval view cache
DF_EvalViewCache eval_view_cache;
@@ -1655,6 +1657,7 @@ internal U64 df_query_cached_rip_from_thread(DF_Entity *thread);
internal U64 df_query_cached_rip_from_thread_unwind(DF_Entity *thread, U64 unwind_count);
internal EVAL_String2NumMap *df_query_cached_locals_map_from_binary_voff(DF_Entity *binary, U64 voff);
internal EVAL_String2NumMap *df_query_cached_member_map_from_binary_voff(DF_Entity *binary, U64 voff);
internal EVAL_String2NumMap *df_query_cached_local_dynamic_type_override_map_from_module_voff(DF_Entity *module, U64 voff);
//- rjf: top-level command dispatch
internal void df_push_cmd__root(DF_CmdParams *params, DF_CmdSpec *spec);
+16
View File
@@ -778,6 +778,7 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8
case EVAL_TokenKind_Identifier:
{
B32 mapped_identifier = 0;
B32 identifier_type_is_possibly_dynamically_overridden = 0;
B32 identifier_looks_like_type_expr = 0;
RADDBG_LocationKind loc_kind = RADDBG_LocationKind_NULL;
RADDBG_LocationRegister loc_reg = {0};
@@ -808,6 +809,7 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8
ctx->rdbg->type_nodes != 0)
{
mapped_identifier = 1;
identifier_type_is_possibly_dynamically_overridden = 1;
RADDBG_Local *local_var = &ctx->rdbg->locals[local_num-1];
// rjf: grab location info
@@ -978,6 +980,20 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8
}
}
//- rjf: identifier refers to type which may be possibly overridden -> look up into
// identifier -> dynamic type table & patch
if(identifier_type_is_possibly_dynamically_overridden)
{
U64 base_type_num = eval_num_from_string(ctx->local_dynamic_type_override_map, token_string);
if(base_type_num != 0)
{
U64 type_idx = base_type_num;
RADDBG_TypeNode *type_node = &ctx->rdbg->type_nodes[type_idx];
TG_Key base_type_key = tg_key_ext(tg_kind_from_raddbg_type_kind(type_node->kind), type_idx);
type_key = tg_cons_type_make(ctx->type_graph, TG_Kind_Ptr, base_type_key, 0);
}
}
//- rjf: attach on map
if(mapped_identifier != 0)
{
+1
View File
@@ -98,6 +98,7 @@ struct EVAL_ParseCtx
EVAL_String2NumMap *reg_alias_map;
EVAL_String2NumMap *locals_map;
EVAL_String2NumMap *member_map;
EVAL_String2NumMap *local_dynamic_type_override_map;
};
////////////////////////////////