mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-07-09 11:01:37 -07:00
pipe breakpoint-condition-touched meta-evaluations to control thread; allow evaluation of meta-evaluations in conditional breakpoints
This commit is contained in:
+64
-8
@@ -1260,6 +1260,7 @@ ctrl_init(void)
|
||||
ctrl_state->ctrl_thread_entity_store = ctrl_entity_store_alloc();
|
||||
ctrl_state->dmn_event_arena = arena_alloc();
|
||||
ctrl_state->user_entry_point_arena = arena_alloc();
|
||||
ctrl_state->user_meta_eval_arena = arena_alloc();
|
||||
for(CTRL_ExceptionCodeKind k = (CTRL_ExceptionCodeKind)0; k < CTRL_ExceptionCodeKind_COUNT; k = (CTRL_ExceptionCodeKind)(k+1))
|
||||
{
|
||||
if(ctrl_exception_code_kind_default_enable_table[k])
|
||||
@@ -3190,7 +3191,15 @@ ctrl_thread__entry_point(void *p)
|
||||
{
|
||||
log_infof("user2ctrl_msg:{kind:\"%S\"}\n", ctrl_string_from_msg_kind(msg->kind));
|
||||
}
|
||||
MemoryCopyArray(ctrl_state->exception_code_filters, msg->exception_code_filters);
|
||||
|
||||
//- rjf: unpack per-message parameterizations & store
|
||||
{
|
||||
MemoryCopyArray(ctrl_state->exception_code_filters, msg->exception_code_filters);
|
||||
arena_clear(ctrl_state->user_meta_eval_arena);
|
||||
ctrl_state->user_meta_evals = *deep_copy_from_struct(ctrl_state->user_meta_eval_arena, CTRL_MetaEvalArray, &msg->meta_evals);
|
||||
}
|
||||
|
||||
//- rjf: process message
|
||||
switch(msg->kind)
|
||||
{
|
||||
case CTRL_MsgKind_Null:
|
||||
@@ -4104,6 +4113,8 @@ ctrl_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range)
|
||||
switch(space.kind)
|
||||
{
|
||||
default:{}break;
|
||||
|
||||
//- rjf: intra-entity reads (process memory or thread registers)
|
||||
case CTRL_EvalSpaceKind_Entity:
|
||||
{
|
||||
CTRL_Entity *entity = (CTRL_Entity *)space.u64_0;
|
||||
@@ -4129,6 +4140,42 @@ ctrl_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range)
|
||||
}break;
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: meta evaluations
|
||||
case CTRL_EvalSpaceKind_Meta:
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
U64 meta_eval_idx = space.u64s[0];
|
||||
if(meta_eval_idx < ctrl_state->user_meta_evals.count)
|
||||
{
|
||||
CTRL_MetaEval *meval = &ctrl_state->user_meta_evals.v[meta_eval_idx];
|
||||
|
||||
// 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 actual read
|
||||
Rng1U64 legal_range = r1u64(0, pos_opl-pos_min);
|
||||
if(contains_1u64(legal_range, range.min))
|
||||
{
|
||||
result = 1;
|
||||
U64 range_dim = dim_1u64(range);
|
||||
U64 bytes_to_read = Min(range_dim, (legal_range.max - range.min));
|
||||
MemoryCopy(out, ((U8 *)meval_read) + range.min, bytes_to_read);
|
||||
if(bytes_to_read < range_dim)
|
||||
{
|
||||
MemoryZero((U8 *)out + bytes_to_read, range_dim - bytes_to_read);
|
||||
}
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -5031,6 +5078,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
ctx->modules_count = eval_modules_count;
|
||||
ctx->primary_module = eval_modules_primary;
|
||||
}
|
||||
e_select_type_ctx(&type_ctx);
|
||||
|
||||
// rjf: build eval parse context
|
||||
E_ParseCtx parse_ctx = zero_struct;
|
||||
@@ -5049,13 +5097,26 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
ctx->locals_map = e_push_locals_map_from_rdi_voff(temp.arena, eval_modules_primary->rdi, thread_rip_voff);
|
||||
ctx->member_map = e_push_member_map_from_rdi_voff(temp.arena, eval_modules_primary->rdi, thread_rip_voff);
|
||||
}
|
||||
e_select_parse_ctx(&parse_ctx);
|
||||
|
||||
// rjf: build eval IR context
|
||||
E_IRCtx ir_ctx = zero_struct;
|
||||
{
|
||||
// TODO(rjf): pipe this here from frontend
|
||||
ir_ctx.macro_map = &e_string2expr_map_nil;
|
||||
E_IRCtx *ctx = &ir_ctx;
|
||||
ctx->macro_map = push_array(temp.arena, E_String2ExprMap, 1);
|
||||
ctx->macro_map[0] = e_string2expr_map_make(temp.arena, 512);
|
||||
E_TypeKey meval_type_key = e_type_key_cons_base(type(CTRL_MetaEval));
|
||||
for EachIndex(idx, ctrl_state->user_meta_evals.count)
|
||||
{
|
||||
E_Space space = e_space_make(CTRL_EvalSpaceKind_Meta);
|
||||
E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, 0);
|
||||
expr->space = space;
|
||||
expr->mode = E_Mode_Offset;
|
||||
expr->type_key = meval_type_key;
|
||||
e_string2expr_map_insert(temp.arena, ctx->macro_map, ctrl_state->user_meta_evals.v[idx].label, expr);
|
||||
}
|
||||
}
|
||||
e_select_ir_ctx(&ir_ctx);
|
||||
|
||||
// rjf: build eval interpretation context
|
||||
E_InterpretCtx interpret_ctx = zero_struct;
|
||||
@@ -5071,11 +5132,6 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
ctx->module_base[0]= module->vaddr_range.min;
|
||||
ctx->tls_base = push_array(temp.arena, U64, 1);
|
||||
}
|
||||
|
||||
// rjf: equip contexts
|
||||
e_select_type_ctx(&type_ctx);
|
||||
e_select_parse_ctx(&parse_ctx);
|
||||
e_select_ir_ctx(&ir_ctx);
|
||||
e_select_interpret_ctx(&interpret_ctx);
|
||||
|
||||
// rjf: evaluate
|
||||
|
||||
@@ -817,7 +817,7 @@ struct CTRL_State
|
||||
Arena *user_entry_point_arena;
|
||||
String8List user_entry_points;
|
||||
Arena *user_meta_eval_arena;
|
||||
CTRL_MetaEvalArray *user_meta_evals;
|
||||
CTRL_MetaEvalArray user_meta_evals;
|
||||
U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64];
|
||||
U64 process_counter;
|
||||
|
||||
|
||||
@@ -15393,6 +15393,7 @@ rd_frame(void)
|
||||
//- rjf: gather targets
|
||||
//
|
||||
D_TargetArray targets = {0};
|
||||
ProfScope("gather targets")
|
||||
{
|
||||
RD_EntityList target_entities = rd_query_cached_entity_list_with_kind(RD_EntityKind_Target);
|
||||
targets.count = target_entities.count;
|
||||
@@ -15415,6 +15416,7 @@ rd_frame(void)
|
||||
//- rjf: gather breakpoints
|
||||
//
|
||||
D_BreakpointArray breakpoints = {0};
|
||||
ProfScope("gather breakpoints")
|
||||
{
|
||||
RD_EntityList bp_entities = rd_query_cached_entity_list_with_kind(RD_EntityKind_Breakpoint);
|
||||
breakpoints.count = bp_entities.count;
|
||||
@@ -15457,11 +15459,96 @@ rd_frame(void)
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: gather meta evaluations
|
||||
//- rjf: gather needed meta evaluations
|
||||
//
|
||||
CTRL_MetaEvalArray meta_evals = {0};
|
||||
ProfScope("gather needed meta evaluations")
|
||||
{
|
||||
// TODO(rjf): @msgs
|
||||
typedef struct MetaEvalNode MetaEvalNode;
|
||||
struct MetaEvalNode
|
||||
{
|
||||
MetaEvalNode *next;
|
||||
CTRL_MetaEval *meval;
|
||||
};
|
||||
|
||||
//- rjf: walk all breakpoints, gather touched meta-evals
|
||||
U64 meval_count = 0;
|
||||
MetaEvalNode *first_meval = 0;
|
||||
MetaEvalNode *last_meval = 0;
|
||||
for EachIndex(idx, breakpoints.count)
|
||||
{
|
||||
if(breakpoints.v[idx].condition.size != 0)
|
||||
{
|
||||
//- rjf: walk conditional breakpoint expression tree - for each leaf identifier,
|
||||
// determine if it resolves to a meta-evaluation. if it does, compute the meta
|
||||
// evaluation data & store
|
||||
typedef struct ExprWalkTask ExprWalkTask;
|
||||
struct ExprWalkTask
|
||||
{
|
||||
ExprWalkTask *next;
|
||||
E_Expr *expr;
|
||||
};
|
||||
E_Expr *expr = e_parse_expr_from_text(scratch.arena, breakpoints.v[idx].condition);
|
||||
ExprWalkTask start_task = {0, expr};
|
||||
ExprWalkTask *first_task = &start_task;
|
||||
for(ExprWalkTask *t = first_task; t != 0; t = t->next)
|
||||
{
|
||||
if(t->expr->kind == E_ExprKind_LeafIdent)
|
||||
{
|
||||
E_Expr *macro_expr = e_string2expr_lookup(e_ir_ctx->macro_map, t->expr->string);
|
||||
if(macro_expr != &e_expr_nil)
|
||||
{
|
||||
E_Eval eval = e_eval_from_expr(scratch.arena, macro_expr);
|
||||
switch(eval.space.kind)
|
||||
{
|
||||
default:{}break;
|
||||
case RD_EvalSpaceKind_MetaEntity:
|
||||
{
|
||||
RD_Entity *entity = rd_entity_from_eval_space(eval.space);
|
||||
if(!rd_entity_is_nil(entity))
|
||||
{
|
||||
MetaEvalNode *meval_node = push_array(scratch.arena, MetaEvalNode, 1);
|
||||
meval_node->meval = rd_ctrl_meta_eval_from_entity(scratch.arena, entity);
|
||||
SLLQueuePush(first_meval, last_meval, meval_node);
|
||||
meval_count += 1;
|
||||
}
|
||||
}break;
|
||||
case RD_EvalSpaceKind_MetaCtrlEntity:
|
||||
{
|
||||
CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(eval.space);
|
||||
if(entity != &ctrl_entity_nil)
|
||||
{
|
||||
MetaEvalNode *meval_node = push_array(scratch.arena, MetaEvalNode, 1);
|
||||
meval_node->meval = rd_ctrl_meta_eval_from_ctrl_entity(scratch.arena, entity);
|
||||
SLLQueuePush(first_meval, last_meval, meval_node);
|
||||
meval_count += 1;
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(E_Expr *child = t->expr->first; child != &e_expr_nil; child = child->next)
|
||||
{
|
||||
ExprWalkTask *task = push_array(scratch.arena, ExprWalkTask, 1);
|
||||
task->expr = child;
|
||||
task->next = t->next;
|
||||
t->next = task;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: list -> array
|
||||
meta_evals.count = meval_count;
|
||||
meta_evals.v = push_array(scratch.arena, CTRL_MetaEval, meta_evals.count);
|
||||
{
|
||||
U64 idx = 0;
|
||||
for(MetaEvalNode *n = first_meval; n != 0; n = n->next)
|
||||
{
|
||||
MemoryCopyStruct(&meta_evals.v[idx], n->meval);
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user