diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 1807a1e3..f38dfc76 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -189,7 +189,7 @@ ctrl_handle_list_copy(Arena *arena, CTRL_HandleList *src) internal String8 ctrl_string_from_handle(Arena *arena, CTRL_Handle handle) { - String8 result = push_str8f(arena, "$0x%I64x$0x%I64x", handle.machine_id, handle.dmn_handle.u64[0]); + String8 result = push_str8f(arena, "$%I64x$%I64x", handle.machine_id, handle.dmn_handle.u64[0]); return result; } @@ -203,14 +203,11 @@ ctrl_handle_from_string(String8 string) String8List parts = str8_split(scratch.arena, string, &split, 1, 0); if(parts.first && parts.first->next) { - CTRL_MachineID machine_id = 0; + CTRL_MachineID machine_id = u64_from_str8(parts.first->string, 16); DMN_Handle dmn_handle = {0}; - if(try_u64_from_str8_c_rules(parts.first->string, &machine_id) && - try_u64_from_str8_c_rules(parts.first->next->string, &dmn_handle.u64[0])) - { - handle.machine_id = machine_id; - handle.dmn_handle = dmn_handle; - } + dmn_handle.u64[0] = u64_from_str8(parts.first->next->string, 16); + handle.machine_id = machine_id; + handle.dmn_handle = dmn_handle; } scratch_end(scratch); } diff --git a/src/eval/eval_ir.c b/src/eval/eval_ir.c index 991e3281..1dd39122 100644 --- a/src/eval/eval_ir.c +++ b/src/eval/eval_ir.c @@ -1523,8 +1523,50 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 E_Space mapped_bytecode_space = zero_struct; String8 mapped_bytecode = {0}; + //- rjf: try to map name as parent expression signifier ('$') + if(qualifier.size == 0 && !string_mapped && str8_match(string, str8_lit("$"), 0) && parent != 0 && (parent->root != &e_irnode_nil || parent->msgs.first != 0)) + { + E_IRTreeAndType *parent_irtree = parent; + if(disallow_autohooks) + { + for(E_IRTreeAndType *prev = parent_irtree->prev; prev != 0; prev = prev->prev) + { + parent_irtree = prev; + } + } + E_OpList oplist = e_oplist_from_irtree(arena, parent_irtree->root); + string_mapped = 1; + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = parent_irtree->mode; + mapped_type_key = parent_irtree->type_key; + disallow_autohooks = 1; + E_MsgList msgs = e_msg_list_copy(arena, &parent_irtree->msgs); + e_msg_list_concat_in_place(&result.msgs, &msgs); + } + + //- rjf: try to map name as implicit access of overridden expression ('$.member_name', where the $. prefix is omitted) + if(qualifier.size == 0 && !string_mapped && parent != 0 && parent->root != &e_irnode_nil) + { + for(E_IRTreeAndType *prev = parent; prev != 0; prev = prev->prev) + { + E_Expr *access = e_expr_irext_member_access(scratch.arena, &e_expr_nil, prev, string); + E_IRTreeAndType access_irtree = e_push_irtree_and_type_from_expr(scratch.arena, prev, disallow_autohooks, 1, access); + if(access_irtree.root != &e_irnode_nil) + { + string_mapped = 1; + E_OpList oplist = e_oplist_from_irtree(scratch.arena, access_irtree.root); + mapped_type_key = access_irtree.type_key; + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = access_irtree.mode; + e_msg_list_concat_in_place(&result.msgs, &access_irtree.msgs); + break; + } + } + } + //- rjf: form namespaceified fallback versions of this lookup string String8List namespaceified_strings = {0}; + if(!string_mapped) { E_Module *module = e_base_ctx->primary_module; RDI_Parsed *rdi = module->rdi; @@ -1549,47 +1591,6 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, B32 } } - //- rjf: try to map name as parent expression signifier ('$') - if(!string_mapped && str8_match(string, str8_lit("$"), 0) && parent != 0 && (parent->root != &e_irnode_nil || parent->msgs.first != 0)) - { - E_IRTreeAndType *parent_irtree = parent; - if(disallow_autohooks) - { - for(E_IRTreeAndType *prev = parent_irtree->prev; prev != 0; prev = prev->prev) - { - parent_irtree = prev; - } - } - E_OpList oplist = e_oplist_from_irtree(arena, parent_irtree->root); - string_mapped = 1; - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = parent_irtree->mode; - mapped_type_key = parent_irtree->type_key; - disallow_autohooks = 1; - E_MsgList msgs = e_msg_list_copy(arena, &parent_irtree->msgs); - e_msg_list_concat_in_place(&result.msgs, &msgs); - } - - //- rjf: try to map name as implicit access of overridden expression ('$.member_name', where the $. prefix is omitted) - if(!string_mapped && parent != 0 && parent->root != &e_irnode_nil) - { - for(E_IRTreeAndType *prev = parent; prev != 0; prev = prev->prev) - { - E_Expr *access = e_expr_irext_member_access(scratch.arena, &e_expr_nil, prev, string); - E_IRTreeAndType access_irtree = e_push_irtree_and_type_from_expr(scratch.arena, prev, disallow_autohooks, 1, access); - if(access_irtree.root != &e_irnode_nil) - { - string_mapped = 1; - E_OpList oplist = e_oplist_from_irtree(scratch.arena, access_irtree.root); - mapped_type_key = access_irtree.type_key; - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = access_irtree.mode; - e_msg_list_concat_in_place(&result.msgs, &access_irtree.msgs); - break; - } - } - } - //- rjf: try to map name as member - if found, string__redirected := "this", and turn // on later implicit-member-lookup generation B32 string_is_implicit_member_name = 0; diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 5a1f24d2..27c652c9 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -12518,6 +12518,7 @@ rd_frame(void) E_TypeKey collection_type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = collection_name, .flags = E_TypeFlag_StubSingleLineExpansion, + .access = E_TYPE_ACCESS_FUNCTION_NAME(unattached_processes), .expand = { .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(unattached_processes), diff --git a/src/raddbg/raddbg_eval.c b/src/raddbg/raddbg_eval.c index fe7de6e7..7d11331e 100644 --- a/src/raddbg/raddbg_eval.c +++ b/src/raddbg/raddbg_eval.c @@ -574,7 +574,6 @@ E_TYPE_ACCESS_FUNCTION_DEF(control) return result; } - //////////////////////////////// //~ rjf: Config Collection Type Hooks @@ -1144,6 +1143,53 @@ struct RD_UnattachedProcessesAccel U64 infos_count; }; +E_TYPE_ACCESS_FUNCTION_DEF(unattached_processes) +{ + E_IRTreeAndType result = {&e_irnode_nil}; + if(expr->kind == E_ExprKind_MemberAccess) + { + Temp scratch = scratch_begin(&arena, 1); + + // rjf: extract pid / name id from access string + U64 pid = 0; + U64 string_id = 0; + { + String8 pid_string = {0}; + String8 name_id_string = {0}; + U8 split_char = '$'; + String8List parts = str8_split(scratch.arena, expr->first->next->string, &split_char, 1, 0); + if(parts.first != 0 && parts.first->next != 0) + { + pid_string = parts.first->string; + name_id_string = parts.first->next->string; + pid = u64_from_str8(pid_string, 16); + string_id = u64_from_str8(name_id_string, 16); + } + } + + // rjf: get machine entity from space + E_OpList oplist = e_oplist_from_irtree(scratch.arena, lhs_irtree->root); + String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); + E_Interpretation interpret = e_interpret(bytecode); + CTRL_Entity *machine = rd_ctrl_entity_from_eval_space(interpret.space); + + // rjf: build evaluation for this unattached process + if(machine != &ctrl_entity_nil) + { + E_IRNode *value_irnode = e_push_irnode(arena, RDI_EvalOp_ConstU128); + value_irnode->value.u128.u64[0] = pid; + value_irnode->value.u128.u64[1] = string_id; + E_Space space = rd_eval_space_from_ctrl_entity(machine, RD_EvalSpaceKind_MetaUnattachedProcess); + result.root = e_irtree_set_space(arena, space, value_irnode); + result.type_key = e_type_key_basic(E_TypeKind_U128); + result.mode = E_Mode_Value; + } + + scratch_end(scratch); + } + return result; +} + E_TYPE_EXPAND_INFO_FUNCTION_DEF(unattached_processes) { E_TypeExpandInfo info = {0}; @@ -1239,13 +1285,9 @@ E_TYPE_EXPAND_RANGE_FUNCTION_DEF(unattached_processes) E_TypeKey unattached_process_type = e_type_key_cons(.kind = E_TypeKind_U128, .name = str8_lit("unattached_process")); for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) { -#if 0 // TODO(rjf): @eval - E_Expr *expr = e_push_expr(arena, E_ExprKind_LeafValue, 0); - expr->type_key = unattached_process_type; - expr->value.u128.u64[0] = accel->infos[idx].pid; - expr->value.u128.u64[1] = e_id_from_string(accel->infos[idx].name); - expr->space = rd_eval_space_from_ctrl_entity(accel->machines[idx], RD_EvalSpaceKind_MetaUnattachedProcess); -#endif + CTRL_Entity *machine = accel->machines[idx]; + String8 string = ctrl_string_from_handle(arena, machine->handle); + evals_out[out_idx] = e_eval_wrapf(eval, "query:control.%S.unattached_processes.$%I64x$%I64x", string, accel->infos[idx].pid, e_id_from_string(accel->infos[idx].name)); } } diff --git a/src/raddbg/raddbg_eval.h b/src/raddbg/raddbg_eval.h index fdf8785b..67418101 100644 --- a/src/raddbg/raddbg_eval.h +++ b/src/raddbg/raddbg_eval.h @@ -82,6 +82,7 @@ E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(watches); //////////////////////////////// //~ rjf: `unattached_processes` Type Hooks +E_TYPE_ACCESS_FUNCTION_DEF(unattached_processes); E_TYPE_EXPAND_INFO_FUNCTION_DEF(unattached_processes); E_TYPE_EXPAND_RANGE_FUNCTION_DEF(unattached_processes); diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index 81c2cb64..378d0dd7 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -99,6 +99,10 @@ // useful, since different tabs can have a different set of expressions. // `Watch` tabs can now also be labeled, so you can visually distinguish // many `Watch` tabs more easily. +// - **Evaluation drag/drop.** Evaluations in a watch tree can be dragged and +// dropped. This can be used to create new top-level rows in a `Watch` tab, +// or to drag evaluations between `Watch` tabs, or to drag evaluations to +// source or disassembly views and pin the evaluation to some location there. // - **Settings expressions.** Debugger settings have been upgraded to be // stored as expressions, rather than being locked to a specific value. // These expressions are evaluated, like any other expression, and their