From 6be9c71ea992750a7dc60330ee2f9db8a1c6f681 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 7 Oct 2024 21:22:22 -0700 Subject: [PATCH] first pass at meta entity eval commits; breakpoint editing, target editing, watch pin editing --- src/raddbg/raddbg_core.c | 252 ++++++++++++++++++++++++++------------- src/raddbg/raddbg_core.h | 5 + 2 files changed, 173 insertions(+), 84 deletions(-) diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 92a5e76c..328365c6 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -1378,6 +1378,17 @@ rd_entity_change_parent(RD_Entity *entity, RD_Entity *old_parent, RD_Entity *new rd_state->kind_alloc_gens[entity->kind] += 1; } +internal RD_Entity * +rd_entity_child_from_kind_or_alloc(RD_Entity *entity, RD_EntityKind kind) +{ + RD_Entity *child = rd_entity_child_from_kind(entity, kind); + if(rd_entity_is_nil(child)) + { + child = rd_entity_alloc(entity, kind); + } + return child; +} + //- rjf: entity simple equipment internal void @@ -2024,12 +2035,92 @@ rd_eval_space_from_ctrl_entity(CTRL_Entity *entity, E_SpaceKind kind) return space; } +//- rjf: entity -> meta eval + +internal CTRL_MetaEval * +rd_ctrl_meta_eval_from_entity(Arena *arena, RD_Entity *entity) +{ + CTRL_MetaEval *meval = push_array(arena, CTRL_MetaEval, 1); + RD_Entity *exe = rd_entity_child_from_kind(entity, RD_EntityKind_Executable); + RD_Entity *args= rd_entity_child_from_kind(entity, RD_EntityKind_Arguments); + RD_Entity *wdir= rd_entity_child_from_kind(entity, RD_EntityKind_WorkingDirectory); + RD_Entity *entr= rd_entity_child_from_kind(entity, RD_EntityKind_EntryPoint); + RD_Entity *loc = rd_entity_child_from_kind(entity, RD_EntityKind_Location); + RD_Entity *cnd = rd_entity_child_from_kind(entity, RD_EntityKind_Condition); + String8 label_string = push_str8_copy(arena, entity->string); + String8 loc_string = {0}; + if(loc->flags & RD_EntityFlag_HasTextPoint) + { + loc_string = push_str8f(arena, "%S:%I64u:%I64u", loc->string, loc->text_point.line, loc->text_point.column); + } + else if(loc->flags & RD_EntityFlag_HasVAddr) + { + loc_string = push_str8f(arena, "0x%I64x", loc->vaddr); + } + String8 cnd_string = push_str8_copy(arena, cnd->string); + meval->enabled = !entity->disabled; + meval->hit_count = entity->u64; + meval->color = u32_from_rgba(rd_rgba_from_entity(entity)); + meval->label = label_string; + meval->exe = exe->string; + meval->args = args->string; + meval->working_directory = wdir->string; + meval->entry_point = entr->string; + meval->location = loc_string; + meval->condition = cnd_string; + return meval; +} + +internal CTRL_MetaEval * +rd_ctrl_meta_eval_from_ctrl_entity(Arena *arena, CTRL_Entity *entity) +{ + CTRL_MetaEval *meval = push_array(arena, CTRL_MetaEval, 1); + meval->frozen = entity->is_frozen; + meval->vaddr_range = entity->vaddr_range; + meval->color = entity->rgba; + meval->label = entity->string; + meval->id = entity->id; + if(entity->kind == CTRL_EntityKind_Thread) + { + DI_Scope *di_scope = di_scope_open(); + CTRL_Entity *process = ctrl_entity_ancestor_from_kind(entity, CTRL_EntityKind_Process); + CTRL_Unwind base_unwind = d_query_cached_unwind_from_thread(entity); + D_Unwind rich_unwind = d_unwind_from_ctrl_unwind(arena, di_scope, process, &base_unwind); + meval->callstack.count = rich_unwind.frames.total_frame_count; + meval->callstack.v = push_array(arena, CTRL_MetaEvalFrame, meval->callstack.count); + U64 idx = 0; + for(U64 base_idx = 0; base_idx < rich_unwind.frames.concrete_frame_count; base_idx += 1) + { + U64 inline_idx = 0; + for(D_UnwindInlineFrame *f = rich_unwind.frames.v[base_idx].first_inline_frame; f != 0; f = f->next, inline_idx += 1) + { + meval->callstack.v[idx].vaddr = regs_rip_from_arch_block(entity->arch, rich_unwind.frames.v[base_idx].regs); + meval->callstack.v[idx].inline_depth = inline_idx + 1; + idx += 1; + } + meval->callstack.v[idx].vaddr = regs_rip_from_arch_block(entity->arch, rich_unwind.frames.v[base_idx].regs); + idx += 1; + } + di_scope_close(di_scope); + } + if(entity->kind == CTRL_EntityKind_Module) + { + DI_Key dbgi_key = ctrl_dbgi_key_from_module(entity); + meval->label = str8_skip_last_slash(entity->string); + meval->exe = path_normalized_from_string(arena, entity->string); + meval->dbg = path_normalized_from_string(arena, dbgi_key.path); + } + return meval; +} + //- rjf: eval space reads/writes internal B32 rd_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range) { + Temp scratch = scratch_begin(0, 0); B32 result = 0; + CTRL_MetaEval *meval = 0; switch(space.kind) { //- rjf: filesystem reads @@ -2091,88 +2182,10 @@ rd_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range) }break; //- rjf: meta reads (metadata about either control entities or debugger state) - case RD_EvalSpaceKind_MetaCtrlEntity: - case RD_EvalSpaceKind_MetaEntity: + case RD_EvalSpaceKind_MetaCtrlEntity: meval = rd_ctrl_meta_eval_from_ctrl_entity(scratch.arena, rd_ctrl_entity_from_eval_space(space)); goto meta_eval; + case RD_EvalSpaceKind_MetaEntity: meval = rd_ctrl_meta_eval_from_entity(scratch.arena, rd_entity_from_eval_space(space)); goto meta_eval; + meta_eval:; { - Temp scratch = scratch_begin(0, 0); - CTRL_MetaEval *meval = push_array(scratch.arena, CTRL_MetaEval, 1); - - // rjf: ctrl entity -> produce meta eval - if(space.kind == RD_EvalSpaceKind_MetaCtrlEntity) - { - CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(space); - - // rjf: produce meta evaluation - meval->frozen = entity->is_frozen; - meval->vaddr_range = entity->vaddr_range; - meval->color = entity->rgba; - meval->label = entity->string; - meval->id = entity->id; - if(entity->kind == CTRL_EntityKind_Thread) - { - DI_Scope *di_scope = di_scope_open(); - CTRL_Entity *process = ctrl_entity_ancestor_from_kind(entity, CTRL_EntityKind_Process); - CTRL_Unwind base_unwind = d_query_cached_unwind_from_thread(entity); - D_Unwind rich_unwind = d_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind); - meval->callstack.count = rich_unwind.frames.total_frame_count; - meval->callstack.v = push_array(scratch.arena, CTRL_MetaEvalFrame, meval->callstack.count); - U64 idx = 0; - for(U64 base_idx = 0; base_idx < rich_unwind.frames.concrete_frame_count; base_idx += 1) - { - U64 inline_idx = 0; - for(D_UnwindInlineFrame *f = rich_unwind.frames.v[base_idx].first_inline_frame; f != 0; f = f->next, inline_idx += 1) - { - meval->callstack.v[idx].vaddr = regs_rip_from_arch_block(entity->arch, rich_unwind.frames.v[base_idx].regs); - meval->callstack.v[idx].inline_depth = inline_idx + 1; - idx += 1; - } - meval->callstack.v[idx].vaddr = regs_rip_from_arch_block(entity->arch, rich_unwind.frames.v[base_idx].regs); - idx += 1; - } - di_scope_close(di_scope); - } - if(entity->kind == CTRL_EntityKind_Module) - { - DI_Key dbgi_key = ctrl_dbgi_key_from_module(entity); - meval->label = str8_skip_last_slash(entity->string); - meval->exe = path_normalized_from_string(scratch.arena, entity->string); - meval->dbg = path_normalized_from_string(scratch.arena, dbgi_key.path); - } - } - - // rjf: debugger entity -> produce meta eval - if(space.kind == RD_EvalSpaceKind_MetaEntity) - { - RD_Entity *entity = rd_entity_from_eval_space(space); - RD_Entity *exe = rd_entity_child_from_kind(entity, RD_EntityKind_Executable); - RD_Entity *args= rd_entity_child_from_kind(entity, RD_EntityKind_Arguments); - RD_Entity *wdir= rd_entity_child_from_kind(entity, RD_EntityKind_WorkingDirectory); - RD_Entity *entr= rd_entity_child_from_kind(entity, RD_EntityKind_EntryPoint); - RD_Entity *loc = rd_entity_child_from_kind(entity, RD_EntityKind_Location); - RD_Entity *cnd = rd_entity_child_from_kind(entity, RD_EntityKind_Condition); - String8 label_string = push_str8_copy(scratch.arena, entity->string); - String8 loc_string = {0}; - if(loc->flags & RD_EntityFlag_HasTextPoint) - { - loc_string = push_str8f(scratch.arena, "%S:%I64u:%I64u", loc->string, loc->text_point.line, loc->text_point.column); - } - else if(loc->flags & RD_EntityFlag_HasVAddr) - { - loc_string = push_str8f(scratch.arena, "0x%I64x", loc->vaddr); - } - String8 cnd_string = push_str8_copy(scratch.arena, cnd->string); - meval->enabled = !entity->disabled; - meval->hit_count = entity->u64; - meval->color = u32_from_rgba(rd_rgba_from_entity(entity)); - meval->label = label_string; - meval->exe = exe->string; - meval->args = args->string; - meval->working_directory = wdir->string; - meval->entry_point = entr->string; - meval->location = loc_string; - meval->condition = cnd_string; - } - // rjf: copy meta evaluation to scratch arena, to form range of legal reads arena_push(scratch.arena, 0, 64); String8 meval_srlzed = serialized_from_struct(scratch.arena, CTRL_MetaEval, meval); @@ -2196,10 +2209,9 @@ rd_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range) MemoryZero((U8 *)out + bytes_to_read, range_dim - bytes_to_read); } } - - scratch_end(scratch); }break; } + scratch_end(scratch); return result; } @@ -2207,7 +2219,79 @@ internal B32 rd_eval_space_write(void *u, E_Space space, void *in, Rng1U64 range) { B32 result = 0; + switch(space.kind) + { + default:{}break; + + //- rjf: interior control entity writes (inside process address space or + // thread register block) + case RD_EvalSpaceKind_CtrlEntity: + { + CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(space); + switch(entity->kind) + { + default:{}break; + case CTRL_EntityKind_Process: + { + result = ctrl_process_write(entity->handle, range, in); + }break; + case CTRL_EntityKind_Thread: + { + Temp scratch = scratch_begin(0, 0); + U64 regs_size = regs_block_size_from_arch(entity->arch); + Rng1U64 legal_range = r1u64(0, regs_size); + Rng1U64 write_range = intersect_1u64(legal_range, range); + U64 write_size = dim_1u64(write_range); + void *new_regs = ctrl_query_cached_reg_block_from_thread(scratch.arena, d_state->ctrl_entity_store, entity->handle); + MemoryCopy((U8 *)new_regs + write_range.min, in, write_size); + result = ctrl_thread_write_reg_block(entity->handle, new_regs); + scratch_end(scratch); + }break; + } + }break; + + //- rjf: meta-entity writes + case RD_EvalSpaceKind_MetaEntity: + { + Temp scratch = scratch_begin(0, 0); + + // rjf: get entity, produce meta-eval + RD_Entity *entity = rd_entity_from_eval_space(space); + CTRL_MetaEval *meval = rd_ctrl_meta_eval_from_entity(scratch.arena, entity); + + // rjf: copy meta evaluation to scratch arena, to form range of legal reads + arena_push(scratch.arena, 0, 64); + String8 meval_srlzed = serialized_from_struct(scratch.arena, CTRL_MetaEval, meval); + U64 pos_min = arena_pos(scratch.arena); + CTRL_MetaEval *meval_read = struct_from_serialized(scratch.arena, CTRL_MetaEval, meval_srlzed); + U64 pos_opl = arena_pos(scratch.arena); + + // rjf: rebase all pointer values in meta evaluation to be relative to base pointer + struct_rebase_ptrs(CTRL_MetaEval, meval_read, meval_read); + + // rjf: perform write to entity + if(0){} +#define FlatMemberCase(name) else if(range.min == OffsetOf(CTRL_MetaEval, name) && dim_1u64(range) <= sizeof(meval_read->name)) +#define StringMemberCase(name) else if(range.min == (U64)meval_read->name.str) + FlatMemberCase(enabled) {result = 1; rd_entity_equip_disabled(entity, !!((U8 *)in)[0]);} + StringMemberCase(label) {result = 1; rd_entity_equip_name(entity, str8_cstring_capped(in, (U8 *)in + 4096));} + StringMemberCase(exe) {result = 1; rd_entity_equip_name(rd_entity_child_from_kind_or_alloc(entity, RD_EntityKind_Executable), str8_cstring_capped(in, (U8 *)in + 4096));} + StringMemberCase(args) {result = 1; rd_entity_equip_name(rd_entity_child_from_kind_or_alloc(entity, RD_EntityKind_Arguments), str8_cstring_capped(in, (U8 *)in + 4096));} + StringMemberCase(working_directory) {result = 1; rd_entity_equip_name(rd_entity_child_from_kind_or_alloc(entity, RD_EntityKind_WorkingDirectory), str8_cstring_capped(in, (U8 *)in + 4096));} + StringMemberCase(entry_point) {result = 1; rd_entity_equip_name(rd_entity_child_from_kind_or_alloc(entity, RD_EntityKind_EntryPoint), str8_cstring_capped(in, (U8 *)in + 4096));} + StringMemberCase(condition) {result = 1; rd_entity_equip_name(rd_entity_child_from_kind_or_alloc(entity, RD_EntityKind_Condition), str8_cstring_capped(in, (U8 *)in + 4096));} +#undef FlatMemberCase +#undef StringMemberCase + scratch_end(scratch); + }break; + case RD_EvalSpaceKind_MetaCtrlEntity: + { + + }break; + } + return result; #if 0 // TODO(rjf): @msgs + B32 result = 0; RD_Entity *entity = rd_entity_from_eval_space(space); switch(entity->kind) { @@ -2273,8 +2357,8 @@ rd_eval_space_write(void *u, E_Space space, void *in, Rng1U64 range) } }break; } -#endif return result; +#endif } //- rjf: asynchronous streamed reads -> hashes from spaces diff --git a/src/raddbg/raddbg_core.h b/src/raddbg/raddbg_core.h index d1769e55..33b5e992 100644 --- a/src/raddbg/raddbg_core.h +++ b/src/raddbg/raddbg_core.h @@ -1134,6 +1134,7 @@ internal RD_Entity *rd_entity_alloc(RD_Entity *parent, RD_EntityKind kind); internal void rd_entity_mark_for_deletion(RD_Entity *entity); internal void rd_entity_release(RD_Entity *entity); internal void rd_entity_change_parent(RD_Entity *entity, RD_Entity *old_parent, RD_Entity *new_parent, RD_Entity *prev_child); +internal RD_Entity *rd_entity_child_from_kind_or_alloc(RD_Entity *entity, RD_EntityKind kind); //- rjf: entity simple equipment internal void rd_entity_equip_txt_pt(RD_Entity *entity, TxtPt point); @@ -1192,6 +1193,10 @@ internal E_Space rd_eval_space_from_entity(RD_Entity *entity); internal CTRL_Entity *rd_ctrl_entity_from_eval_space(E_Space space); internal E_Space rd_eval_space_from_ctrl_entity(CTRL_Entity *entity, E_SpaceKind kind); +//- rjf: entity -> meta eval +internal CTRL_MetaEval *rd_ctrl_meta_eval_from_entity(Arena *arena, RD_Entity *entity); +internal CTRL_MetaEval *rd_ctrl_meta_eval_from_ctrl_entity(Arena *arena, CTRL_Entity *entity); + //- rjf: eval space reads/writes internal B32 rd_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range); internal B32 rd_eval_space_write(void *u, E_Space space, void *in, Rng1U64 range);