mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-14 08:02:23 -07:00
distinguish cfg (breakpoints, watch pins) source-locations from address locations; expand breakpoint addresses to being full expressions, & use this to implement symbol breakpoints (we now support fancier address resolution breakpoints too)
This commit is contained in:
+192
-162
@@ -3418,11 +3418,11 @@ ctrl_thread__entry_point(void *p)
|
||||
//- rjf: breakpoint resolution
|
||||
|
||||
internal void
|
||||
ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_Handle process, CTRL_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out)
|
||||
ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_EvalScope *eval_scope, CTRL_Handle process, CTRL_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out)
|
||||
{
|
||||
if(user_bps->first == 0) { return; }
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
DI_Scope *di_scope = di_scope_open();
|
||||
DI_Scope *di_scope = eval_scope->di_scope;
|
||||
CTRL_Entity *module_entity = ctrl_entity_from_handle(ctrl_state->ctrl_thread_entity_store, module);
|
||||
CTRL_Entity *debug_info_path_entity = ctrl_entity_child_from_kind(module_entity, CTRL_EntityKind_DebugInfoPath);
|
||||
DI_Key dbgi_key = {debug_info_path_entity->string, debug_info_path_entity->timestamp};
|
||||
@@ -3486,45 +3486,37 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_Handle proc
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: symbol:voff-based breakpoints
|
||||
case CTRL_UserBreakpointKind_SymbolNameAndOffset:
|
||||
//- rjf: expression-based breakpoints
|
||||
case CTRL_UserBreakpointKind_Expression:
|
||||
{
|
||||
String8 symbol_name = bp->string;
|
||||
U64 voff = bp->u64;
|
||||
RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures);
|
||||
RDI_ParsedNameMap map = {0};
|
||||
rdi_parsed_from_name_map(rdi, mapptr, &map);
|
||||
RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, symbol_name.str, symbol_name.size);
|
||||
if(node != 0)
|
||||
String8 expr = bp->string;
|
||||
E_Value value = e_value_from_string(expr);
|
||||
if(value.u64 != 0)
|
||||
{
|
||||
U32 id_count = 0;
|
||||
U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count);
|
||||
for(U32 match_i = 0; match_i < id_count; match_i += 1)
|
||||
{
|
||||
RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, ids[match_i]);
|
||||
U64 proc_voff = rdi_first_voff_from_procedure(rdi, procedure);
|
||||
U64 proc_vaddr = proc_voff + base_vaddr;
|
||||
DMN_Trap trap = {process.dmn_handle, proc_vaddr + voff, (U64)bp};
|
||||
dmn_trap_chunk_list_push(arena, traps_out, 256, &trap);
|
||||
}
|
||||
DMN_Trap trap = {process.dmn_handle, value.u64, (U64)bp};
|
||||
dmn_trap_chunk_list_push(arena, traps_out, 256, &trap);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
di_scope_close(di_scope);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
internal void
|
||||
ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out)
|
||||
ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_EvalScope *eval_scope, CTRL_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out)
|
||||
{
|
||||
for(CTRL_UserBreakpointNode *n = user_bps->first; n != 0; n = n->next)
|
||||
{
|
||||
CTRL_UserBreakpoint *bp = &n->v;
|
||||
if(bp->kind == CTRL_UserBreakpointKind_VirtualAddress)
|
||||
if(bp->kind == CTRL_UserBreakpointKind_Expression)
|
||||
{
|
||||
DMN_Trap trap = {process.dmn_handle, bp->u64, (U64)bp};
|
||||
dmn_trap_chunk_list_push(arena, traps_out, 256, &trap);
|
||||
String8 expr = bp->string;
|
||||
E_Value value = e_value_from_string(expr);
|
||||
if(value.u64 != 0)
|
||||
{
|
||||
DMN_Trap trap = {process.dmn_handle, value.u64, (U64)bp};
|
||||
dmn_trap_chunk_list_push(arena, traps_out, 256, &trap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4497,6 +4489,128 @@ ctrl_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range)
|
||||
return result;
|
||||
}
|
||||
|
||||
//- rjf: control thread eval scopes
|
||||
|
||||
internal CTRL_EvalScope *
|
||||
ctrl_thread__eval_scope_begin(Arena *arena, CTRL_Entity *thread)
|
||||
{
|
||||
CTRL_EvalScope *scope = push_array(arena, CTRL_EvalScope, 1);
|
||||
scope->di_scope = di_scope_open();
|
||||
|
||||
// rjf: unpack thread
|
||||
Arch arch = thread->arch;
|
||||
U64 thread_rip_vaddr = dmn_rip_from_thread(thread->handle.dmn_handle);
|
||||
CTRL_Entity *process = ctrl_process_from_entity(thread);
|
||||
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, thread_rip_vaddr);
|
||||
U64 thread_rip_voff = ctrl_voff_from_vaddr(module, thread_rip_vaddr);
|
||||
|
||||
// rjf: gather evaluation modules
|
||||
U64 eval_modules_count = Max(1, ctrl_state->ctrl_thread_entity_store->entity_kind_counts[CTRL_EntityKind_Module]);
|
||||
E_Module *eval_modules = push_array(arena, E_Module, eval_modules_count);
|
||||
E_Module *eval_modules_primary = &eval_modules[0];
|
||||
eval_modules_primary->rdi = &di_rdi_parsed_nil;
|
||||
eval_modules_primary->vaddr_range = r1u64(0, max_U64);
|
||||
{
|
||||
U64 eval_module_idx = 0;
|
||||
for(CTRL_Entity *machine = ctrl_state->ctrl_thread_entity_store->root->first;
|
||||
machine != &ctrl_entity_nil;
|
||||
machine = machine->next)
|
||||
{
|
||||
if(machine->kind != CTRL_EntityKind_Machine) { continue; }
|
||||
for(CTRL_Entity *process = machine->first;
|
||||
process != &ctrl_entity_nil;
|
||||
process = process->next)
|
||||
{
|
||||
if(process->kind != CTRL_EntityKind_Process) { continue; }
|
||||
for(CTRL_Entity *mod = process->first;
|
||||
mod != &ctrl_entity_nil;
|
||||
mod = mod->next)
|
||||
{
|
||||
if(mod->kind != CTRL_EntityKind_Module) { continue; }
|
||||
CTRL_Entity *dbg_path = ctrl_entity_child_from_kind(mod, CTRL_EntityKind_DebugInfoPath);
|
||||
DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp};
|
||||
eval_modules[eval_module_idx].arch = arch;
|
||||
eval_modules[eval_module_idx].rdi = di_rdi_from_key(scope->di_scope, &dbgi_key, max_U64);
|
||||
eval_modules[eval_module_idx].vaddr_range = mod->vaddr_range;
|
||||
eval_modules[eval_module_idx].space = e_space_make(CTRL_EvalSpaceKind_Entity);
|
||||
eval_modules[eval_module_idx].space.u64_0 = (U64)process;
|
||||
if(mod == module)
|
||||
{
|
||||
eval_modules_primary = &eval_modules[eval_module_idx];
|
||||
}
|
||||
eval_module_idx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: build eval type context
|
||||
{
|
||||
E_TypeCtx *ctx = &scope->type_ctx;
|
||||
ctx->ip_vaddr = thread_rip_vaddr;
|
||||
ctx->ip_voff = thread_rip_voff;
|
||||
ctx->modules = eval_modules;
|
||||
ctx->modules_count = eval_modules_count;
|
||||
ctx->primary_module = eval_modules_primary;
|
||||
}
|
||||
e_select_type_ctx(&scope->type_ctx);
|
||||
|
||||
// rjf: build eval parse context
|
||||
ProfScope("build eval parse context")
|
||||
{
|
||||
E_ParseCtx *ctx = &scope->parse_ctx;
|
||||
ctx->ip_vaddr = thread_rip_vaddr;
|
||||
ctx->ip_voff = thread_rip_voff;
|
||||
ctx->ip_thread_space = e_space_make(CTRL_EvalSpaceKind_Entity);
|
||||
ctx->ip_thread_space.u64_0 = (U64)thread;
|
||||
ctx->modules = eval_modules;
|
||||
ctx->modules_count = eval_modules_count;
|
||||
ctx->primary_module = eval_modules_primary;
|
||||
ctx->regs_map = ctrl_string2reg_from_arch(arch);
|
||||
ctx->reg_alias_map = ctrl_string2alias_from_arch(arch);
|
||||
ctx->locals_map = e_push_locals_map_from_rdi_voff(arena, eval_modules_primary->rdi, thread_rip_voff);
|
||||
ctx->member_map = e_push_member_map_from_rdi_voff(arena, eval_modules_primary->rdi, thread_rip_voff);
|
||||
}
|
||||
e_select_parse_ctx(&scope->parse_ctx);
|
||||
|
||||
// rjf: build eval IR context
|
||||
{
|
||||
E_IRCtx *ctx = &scope->ir_ctx;
|
||||
ctx->macro_map = push_array(arena, E_String2ExprMap, 1);
|
||||
ctx->macro_map[0] = e_string2expr_map_make(arena, 512);
|
||||
ctx->lookup_rule_map = push_array(arena, E_LookupRuleMap, 1);
|
||||
ctx->lookup_rule_map[0] = e_lookup_rule_map_make(arena, 512);
|
||||
ctx->irgen_rule_map = push_array(arena, E_IRGenRuleMap, 1);
|
||||
ctx->irgen_rule_map[0] = e_irgen_rule_map_make(arena, 512);
|
||||
ctx->auto_hook_map = push_array(arena, E_AutoHookMap, 1);
|
||||
ctx->auto_hook_map[0] = e_auto_hook_map_make(arena, 512);
|
||||
}
|
||||
e_select_ir_ctx(&scope->ir_ctx);
|
||||
|
||||
// rjf: build eval interpretation context
|
||||
{
|
||||
E_InterpretCtx *ctx = &scope->interpret_ctx;
|
||||
ctx->space_rw_user_data = ctrl_state->ctrl_thread_entity_store;
|
||||
ctx->space_read = ctrl_eval_space_read;
|
||||
ctx->primary_space = eval_modules_primary->space;
|
||||
ctx->reg_arch = eval_modules_primary->arch;
|
||||
ctx->reg_space = e_space_make(CTRL_EvalSpaceKind_Entity);
|
||||
ctx->reg_space.u64_0 = (U64)thread;
|
||||
ctx->module_base = push_array(arena, U64, 1);
|
||||
ctx->module_base[0]= module->vaddr_range.min;
|
||||
ctx->tls_base = push_array(arena, U64, 1);
|
||||
}
|
||||
e_select_interpret_ctx(&scope->interpret_ctx);
|
||||
|
||||
return scope;
|
||||
}
|
||||
|
||||
internal void
|
||||
ctrl_thread__eval_scope_end(CTRL_EvalScope *scope)
|
||||
{
|
||||
di_scope_close(scope->di_scope);
|
||||
}
|
||||
|
||||
//- rjf: log flusher
|
||||
|
||||
internal void
|
||||
@@ -4828,25 +4942,30 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
//- rjf: gather all initial breakpoints
|
||||
//
|
||||
DMN_TrapChunkList user_traps = {0};
|
||||
for(CTRL_Entity *machine = ctrl_state->ctrl_thread_entity_store->root->first;
|
||||
machine != &ctrl_entity_nil;
|
||||
machine = machine->next)
|
||||
{
|
||||
if(machine->kind != CTRL_EntityKind_Machine) { continue; }
|
||||
for(CTRL_Entity *process = machine->first; process != &ctrl_entity_nil; process = process->next)
|
||||
CTRL_Entity *thread = ctrl_entity_from_handle(ctrl_state->ctrl_thread_entity_store, target_thread);
|
||||
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, thread);
|
||||
for(CTRL_Entity *machine = ctrl_state->ctrl_thread_entity_store->root->first;
|
||||
machine != &ctrl_entity_nil;
|
||||
machine = machine->next)
|
||||
{
|
||||
if(process->kind != CTRL_EntityKind_Process) { continue; }
|
||||
|
||||
// rjf: resolve module-dependent user bps
|
||||
for(CTRL_Entity *module = process->first; module != &ctrl_entity_nil; module = module->next)
|
||||
if(machine->kind != CTRL_EntityKind_Machine) { continue; }
|
||||
for(CTRL_Entity *process = machine->first; process != &ctrl_entity_nil; process = process->next)
|
||||
{
|
||||
if(module->kind != CTRL_EntityKind_Module) { continue; }
|
||||
ctrl_thread__append_resolved_module_user_bp_traps(scratch.arena, process->handle, module->handle, &msg->user_bps, &user_traps);
|
||||
if(process->kind != CTRL_EntityKind_Process) { continue; }
|
||||
|
||||
// rjf: resolve module-dependent user bps
|
||||
for(CTRL_Entity *module = process->first; module != &ctrl_entity_nil; module = module->next)
|
||||
{
|
||||
if(module->kind != CTRL_EntityKind_Module) { continue; }
|
||||
ctrl_thread__append_resolved_module_user_bp_traps(scratch.arena, eval_scope, process->handle, module->handle, &msg->user_bps, &user_traps);
|
||||
}
|
||||
|
||||
// rjf: push virtual-address user breakpoints per-process
|
||||
ctrl_thread__append_resolved_process_user_bp_traps(scratch.arena, eval_scope, process->handle, &msg->user_bps, &user_traps);
|
||||
}
|
||||
|
||||
// rjf: push virtual-address user breakpoints per-process
|
||||
ctrl_thread__append_resolved_process_user_bp_traps(scratch.arena, process->handle, &msg->user_bps, &user_traps);
|
||||
}
|
||||
ctrl_thread__eval_scope_end(eval_scope);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
@@ -5110,39 +5229,48 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
}break;
|
||||
case DMN_EventKind_CreateProcess:
|
||||
{
|
||||
DMN_TrapChunkList new_traps = {0};
|
||||
ctrl_thread__append_resolved_process_user_bp_traps(scratch.arena, ctrl_handle_make(CTRL_MachineID_Local, event->process), &msg->user_bps, &new_traps);
|
||||
log_infof("step_rule: create_process -> resolve traps\n");
|
||||
log_infof("new_traps:\n{\n");
|
||||
for(DMN_TrapChunkNode *n = new_traps.first; n != 0; n = n->next)
|
||||
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, &ctrl_entity_nil);
|
||||
{
|
||||
for(U64 idx = 0; idx < n->count; idx += 1)
|
||||
DMN_TrapChunkList new_traps = {0};
|
||||
ctrl_thread__append_resolved_process_user_bp_traps(scratch.arena, eval_scope, ctrl_handle_make(CTRL_MachineID_Local, event->process), &msg->user_bps, &new_traps);
|
||||
log_infof("step_rule: create_process -> resolve traps\n");
|
||||
log_infof("new_traps:\n{\n");
|
||||
for(DMN_TrapChunkNode *n = new_traps.first; n != 0; n = n->next)
|
||||
{
|
||||
DMN_Trap *trap = &n->v[idx];
|
||||
log_infof("{process:[0x%I64x], vaddr:0x%I64x}\n", trap->process.u64[0], trap->vaddr);
|
||||
for(U64 idx = 0; idx < n->count; idx += 1)
|
||||
{
|
||||
DMN_Trap *trap = &n->v[idx];
|
||||
log_infof("{process:[0x%I64x], vaddr:0x%I64x}\n", trap->process.u64[0], trap->vaddr);
|
||||
}
|
||||
}
|
||||
log_infof("}\n\n");
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &new_traps);
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &user_traps, &new_traps);
|
||||
}
|
||||
log_infof("}\n\n");
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &new_traps);
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &user_traps, &new_traps);
|
||||
ctrl_thread__eval_scope_end(eval_scope);
|
||||
}break;
|
||||
case DMN_EventKind_LoadModule:
|
||||
{
|
||||
DMN_TrapChunkList new_traps = {0};
|
||||
ctrl_thread__append_resolved_module_user_bp_traps(scratch.arena, ctrl_handle_make(CTRL_MachineID_Local, event->process), ctrl_handle_make(CTRL_MachineID_Local, event->module), &msg->user_bps, &new_traps);
|
||||
log_infof("step_rule: load_module -> resolve traps\n");
|
||||
log_infof("new_traps:\n{\n");
|
||||
for(DMN_TrapChunkNode *n = new_traps.first; n != 0; n = n->next)
|
||||
CTRL_Entity *thread = ctrl_entity_from_handle(ctrl_state->ctrl_thread_entity_store, ctrl_handle_make(CTRL_MachineID_Local, event->thread));
|
||||
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, thread);
|
||||
{
|
||||
for(U64 idx = 0; idx < n->count; idx += 1)
|
||||
DMN_TrapChunkList new_traps = {0};
|
||||
ctrl_thread__append_resolved_module_user_bp_traps(scratch.arena, eval_scope, ctrl_handle_make(CTRL_MachineID_Local, event->process), ctrl_handle_make(CTRL_MachineID_Local, event->module), &msg->user_bps, &new_traps);
|
||||
log_infof("step_rule: load_module -> resolve traps\n");
|
||||
log_infof("new_traps:\n{\n");
|
||||
for(DMN_TrapChunkNode *n = new_traps.first; n != 0; n = n->next)
|
||||
{
|
||||
DMN_Trap *trap = &n->v[idx];
|
||||
log_infof("{process:[0x%I64x], vaddr:0x%I64x}\n", trap->process.u64[0], trap->vaddr);
|
||||
for(U64 idx = 0; idx < n->count; idx += 1)
|
||||
{
|
||||
DMN_Trap *trap = &n->v[idx];
|
||||
log_infof("{process:[0x%I64x], vaddr:0x%I64x}\n", trap->process.u64[0], trap->vaddr);
|
||||
}
|
||||
}
|
||||
log_infof("}\n\n");
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &new_traps);
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &user_traps, &new_traps);
|
||||
}
|
||||
log_infof("}\n\n");
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &new_traps);
|
||||
dmn_trap_chunk_list_concat_shallow_copy(scratch.arena, &user_traps, &new_traps);
|
||||
ctrl_thread__eval_scope_end(eval_scope);
|
||||
}break;
|
||||
}
|
||||
|
||||
@@ -5463,107 +5591,9 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
// rjf: evaluate hit stop conditions
|
||||
if(conditions.node_count != 0) ProfScope("evaluate hit stop conditions")
|
||||
{
|
||||
DI_Scope *di_scope = di_scope_open();
|
||||
|
||||
// rjf: gather evaluation modules
|
||||
U64 eval_modules_count = Max(1, ctrl_state->ctrl_thread_entity_store->entity_kind_counts[CTRL_EntityKind_Module]);
|
||||
E_Module *eval_modules = push_array(temp.arena, E_Module, eval_modules_count);
|
||||
E_Module *eval_modules_primary = &eval_modules[0];
|
||||
eval_modules_primary->rdi = &di_rdi_parsed_nil;
|
||||
eval_modules_primary->vaddr_range = r1u64(0, max_U64);
|
||||
{
|
||||
U64 eval_module_idx = 0;
|
||||
for(CTRL_Entity *machine = ctrl_state->ctrl_thread_entity_store->root->first;
|
||||
machine != &ctrl_entity_nil;
|
||||
machine = machine->next)
|
||||
{
|
||||
if(machine->kind != CTRL_EntityKind_Machine) { continue; }
|
||||
for(CTRL_Entity *process = machine->first;
|
||||
process != &ctrl_entity_nil;
|
||||
process = process->next)
|
||||
{
|
||||
if(process->kind != CTRL_EntityKind_Process) { continue; }
|
||||
for(CTRL_Entity *mod = process->first;
|
||||
mod != &ctrl_entity_nil;
|
||||
mod = mod->next)
|
||||
{
|
||||
if(mod->kind != CTRL_EntityKind_Module) { continue; }
|
||||
CTRL_Entity *dbg_path = ctrl_entity_child_from_kind(mod, CTRL_EntityKind_DebugInfoPath);
|
||||
DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp};
|
||||
eval_modules[eval_module_idx].arch = arch;
|
||||
eval_modules[eval_module_idx].rdi = di_rdi_from_key(di_scope, &dbgi_key, max_U64);
|
||||
eval_modules[eval_module_idx].vaddr_range = mod->vaddr_range;
|
||||
eval_modules[eval_module_idx].space = e_space_make(CTRL_EvalSpaceKind_Entity);
|
||||
eval_modules[eval_module_idx].space.u64_0 = (U64)process;
|
||||
if(mod == module)
|
||||
{
|
||||
eval_modules_primary = &eval_modules[eval_module_idx];
|
||||
}
|
||||
eval_module_idx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: loop through all conditions, check all
|
||||
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(temp.arena, thread);
|
||||
for(String8Node *condition_n = conditions.first; condition_n != 0; condition_n = condition_n->next)
|
||||
{
|
||||
// rjf: build eval type context
|
||||
E_TypeCtx type_ctx = zero_struct;
|
||||
{
|
||||
E_TypeCtx *ctx = &type_ctx;
|
||||
ctx->ip_vaddr = thread_rip_vaddr;
|
||||
ctx->ip_voff = thread_rip_voff;
|
||||
ctx->modules = eval_modules;
|
||||
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;
|
||||
ProfScope("build eval parse context")
|
||||
{
|
||||
E_ParseCtx *ctx = &parse_ctx;
|
||||
ctx->ip_vaddr = thread_rip_vaddr;
|
||||
ctx->ip_voff = thread_rip_voff;
|
||||
ctx->ip_thread_space = e_space_make(CTRL_EvalSpaceKind_Entity);
|
||||
ctx->ip_thread_space.u64_0 = (U64)thread;
|
||||
ctx->modules = eval_modules;
|
||||
ctx->modules_count = eval_modules_count;
|
||||
ctx->primary_module = eval_modules_primary;
|
||||
ctx->regs_map = ctrl_string2reg_from_arch(arch);
|
||||
ctx->reg_alias_map = ctrl_string2alias_from_arch(arch);
|
||||
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;
|
||||
{
|
||||
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_select_ir_ctx(&ir_ctx);
|
||||
|
||||
// rjf: build eval interpretation context
|
||||
E_InterpretCtx interpret_ctx = zero_struct;
|
||||
{
|
||||
E_InterpretCtx *ctx = &interpret_ctx;
|
||||
ctx->space_rw_user_data = ctrl_state->ctrl_thread_entity_store;
|
||||
ctx->space_read = ctrl_eval_space_read;
|
||||
ctx->primary_space = eval_modules_primary->space;
|
||||
ctx->reg_arch = eval_modules_primary->arch;
|
||||
ctx->reg_space = e_space_make(CTRL_EvalSpaceKind_Entity);
|
||||
ctx->reg_space.u64_0 = (U64)thread;
|
||||
ctx->module_base = push_array(temp.arena, U64, 1);
|
||||
ctx->module_base[0]= module->vaddr_range.min;
|
||||
ctx->tls_base = push_array(temp.arena, U64, 1);
|
||||
}
|
||||
e_select_interpret_ctx(&interpret_ctx);
|
||||
|
||||
// rjf: evaluate
|
||||
E_Eval eval = zero_struct;
|
||||
ProfScope("evaluate expression")
|
||||
@@ -5586,7 +5616,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
break;
|
||||
}
|
||||
}
|
||||
di_scope_close(di_scope);
|
||||
ctrl_thread__eval_scope_end(eval_scope);
|
||||
}
|
||||
|
||||
// rjf: gather trap net hits
|
||||
|
||||
+20
-4
@@ -263,8 +263,7 @@ typedef enum CTRL_UserBreakpointKind
|
||||
{
|
||||
CTRL_UserBreakpointKind_Null,
|
||||
CTRL_UserBreakpointKind_FileNameAndLineColNumber,
|
||||
CTRL_UserBreakpointKind_SymbolNameAndOffset,
|
||||
CTRL_UserBreakpointKind_VirtualAddress,
|
||||
CTRL_UserBreakpointKind_Expression,
|
||||
CTRL_UserBreakpointKind_COUNT
|
||||
}
|
||||
CTRL_UserBreakpointKind;
|
||||
@@ -636,6 +635,19 @@ struct CTRL_DbgDirNode
|
||||
U64 module_direct_count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Control Thread Evaluation Scopes
|
||||
|
||||
typedef struct CTRL_EvalScope CTRL_EvalScope;
|
||||
struct CTRL_EvalScope
|
||||
{
|
||||
DI_Scope *di_scope;
|
||||
E_TypeCtx type_ctx;
|
||||
E_ParseCtx parse_ctx;
|
||||
E_IRCtx ir_ctx;
|
||||
E_InterpretCtx interpret_ctx;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Wakeup Hook Function Types
|
||||
|
||||
@@ -933,8 +945,8 @@ internal CTRL_EventList ctrl_c2u_pop_events(Arena *arena);
|
||||
internal void ctrl_thread__entry_point(void *p);
|
||||
|
||||
//- rjf: breakpoint resolution
|
||||
internal void ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_Handle process, CTRL_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
|
||||
internal void ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
|
||||
internal void ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_EvalScope *eval_scope, CTRL_Handle process, CTRL_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
|
||||
internal void ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_EvalScope *eval_scope, CTRL_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
|
||||
|
||||
//- rjf: module lifetime open/close work
|
||||
internal void ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_range, String8 path);
|
||||
@@ -946,6 +958,10 @@ internal DMN_Event *ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_
|
||||
//- rjf: eval helpers
|
||||
internal B32 ctrl_eval_space_read(void *u, E_Space space, void *out, Rng1U64 vaddr_range);
|
||||
|
||||
//- rjf: control thread eval scopes
|
||||
internal CTRL_EvalScope *ctrl_thread__eval_scope_begin(Arena *arena, CTRL_Entity *thread);
|
||||
internal void ctrl_thread__eval_scope_end(CTRL_EvalScope *scope);
|
||||
|
||||
//- rjf: log flusher
|
||||
internal void ctrl_thread__flush_info_log(String8 string);
|
||||
internal void ctrl_thread__end_and_flush_info_log(void);
|
||||
|
||||
@@ -61,7 +61,7 @@ d_breakpoint_array_copy(Arena *arena, D_BreakpointArray *src)
|
||||
for(U64 idx = 0; idx < dst.count; idx += 1)
|
||||
{
|
||||
dst.v[idx].file_path = push_str8_copy(arena, dst.v[idx].file_path);
|
||||
dst.v[idx].symbol_name = push_str8_copy(arena, dst.v[idx].symbol_name);
|
||||
dst.v[idx].vaddr_expr = push_str8_copy(arena, dst.v[idx].vaddr_expr);
|
||||
dst.v[idx].condition = push_str8_copy(arena, dst.v[idx].condition);
|
||||
}
|
||||
return dst;
|
||||
@@ -1902,8 +1902,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
D_Breakpoint *bp = &breakpoints->v[idx];
|
||||
str8_list_push(scratch.arena, &strings, bp->file_path);
|
||||
str8_list_push(scratch.arena, &strings, str8_struct(&bp->pt));
|
||||
str8_list_push(scratch.arena, &strings, bp->symbol_name);
|
||||
str8_list_push(scratch.arena, &strings, str8_struct(&bp->vaddr));
|
||||
str8_list_push(scratch.arena, &strings, bp->vaddr_expr);
|
||||
str8_list_push(scratch.arena, &strings, bp->condition);
|
||||
}
|
||||
}
|
||||
@@ -2248,7 +2247,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
}
|
||||
else if(params->vaddr != 0)
|
||||
{
|
||||
run_extra_bps.v[0].vaddr = params->vaddr;
|
||||
run_extra_bps.v[0].vaddr_expr = push_str8f(scratch.arena, "0x%I64x", params->vaddr);
|
||||
}
|
||||
d_cmd(D_CmdKind_Run);
|
||||
}break;
|
||||
@@ -2418,20 +2417,11 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: virtual address location -> add breakpoint for address
|
||||
else if(bp->vaddr != 0)
|
||||
// rjf: virtual address expression -> add expression breakpoint
|
||||
else if(bp->vaddr_expr.size != 0)
|
||||
{
|
||||
CTRL_UserBreakpoint ctrl_user_bp = {CTRL_UserBreakpointKind_VirtualAddress};
|
||||
ctrl_user_bp.u64 = bp->vaddr;
|
||||
ctrl_user_bp.condition = bp->condition;
|
||||
ctrl_user_breakpoint_list_push(scratch.arena, &msg->user_bps, &ctrl_user_bp);
|
||||
}
|
||||
|
||||
// rjf: symbol name location -> add breakpoint for symbol name
|
||||
else if(bp->symbol_name.size != 0)
|
||||
{
|
||||
CTRL_UserBreakpoint ctrl_user_bp = {CTRL_UserBreakpointKind_SymbolNameAndOffset};
|
||||
ctrl_user_bp.string = bp->symbol_name;
|
||||
CTRL_UserBreakpoint ctrl_user_bp = {CTRL_UserBreakpointKind_Expression};
|
||||
ctrl_user_bp.string = bp->vaddr_expr;
|
||||
ctrl_user_bp.condition = bp->condition;
|
||||
ctrl_user_breakpoint_list_push(scratch.arena, &msg->user_bps, &ctrl_user_bp);
|
||||
}
|
||||
|
||||
@@ -33,8 +33,7 @@ struct D_Breakpoint
|
||||
{
|
||||
String8 file_path;
|
||||
TxtPt pt;
|
||||
String8 symbol_name;
|
||||
U64 vaddr;
|
||||
String8 vaddr_expr;
|
||||
String8 condition;
|
||||
};
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//- GENERATED CODE
|
||||
|
||||
C_LINKAGE_BEGIN
|
||||
RD_VocabInfo rd_vocab_info_table[293] =
|
||||
RD_VocabInfo rd_vocab_info_table[295] =
|
||||
{
|
||||
{str8_lit_comp("auto_view_rule"), str8_lit_comp("auto_view_rules"), str8_lit_comp("Auto View Rule"), str8_lit_comp("Auto View Rules"), RD_IconKind_Binoculars},
|
||||
{str8_lit_comp("file_path_map"), str8_lit_comp("file_path_maps"), str8_lit_comp("File Path Map"), str8_lit_comp("File Path Maps"), RD_IconKind_FileOutline},
|
||||
@@ -14,6 +14,8 @@ RD_VocabInfo rd_vocab_info_table[293] =
|
||||
{str8_lit_comp("breakpoint"), str8_lit_comp("breakpoints"), str8_lit_comp("Breakpoint"), str8_lit_comp("Breakpoints"), RD_IconKind_CircleFilled},
|
||||
{str8_lit_comp("condition"), str8_lit_comp("conditions"), str8_lit_comp("Condition"), str8_lit_comp("Conditions"), RD_IconKind_Null},
|
||||
{str8_lit_comp("location"), str8_lit_comp("locations"), str8_lit_comp("Location"), str8_lit_comp("Locations"), RD_IconKind_Null},
|
||||
{str8_lit_comp("source_location"), str8_lit_comp("source_locations"), str8_lit_comp("Source Location"), str8_lit_comp("Source Locations"), RD_IconKind_Null},
|
||||
{str8_lit_comp("address_location"), str8_lit_comp("address_locations"), str8_lit_comp("Address Location"), str8_lit_comp("Address Locations"), RD_IconKind_Null},
|
||||
{str8_lit_comp("target"), str8_lit_comp("targets"), str8_lit_comp("Target"), str8_lit_comp("Targets"), RD_IconKind_Target},
|
||||
{str8_lit_comp("executable"), str8_lit_comp("executables"), str8_lit_comp("Executable"), str8_lit_comp("Executables"), RD_IconKind_Module},
|
||||
{str8_lit_comp("arguments"), str8_lit_comp("arguments"), str8_lit_comp("Arguments"), str8_lit_comp("Arguments"), RD_IconKind_Null},
|
||||
@@ -305,8 +307,8 @@ RD_NameSchemaInfo rd_name_schema_info_table[12] =
|
||||
{
|
||||
{str8_lit_comp("settings"), str8_lit_comp("x:\n{\n @default(1) 'hover_animations': bool,\n @default(1) 'press_animations': bool,\n @default(0) 'focus_animations': bool,\n @default(1) 'tooltip_animations': bool,\n @default(1) 'menu_animations': bool,\n @default(1) 'scrolling_animations': bool,\n @default(1) 'background_blur': bool,\n @default(1) 'thread_lines': bool,\n @default(1) 'breakpoint_lines': bool,\n @default(1) 'thread_glow': bool,\n @default(1) 'breakpoint_glow': bool,\n @default(0) 'opaque_backgrounds': bool,\n @default(1) 'smooth_main_text': bool,\n @default(0) 'smooth_code_text': bool,\n @default(1) 'hint_main_text': bool,\n @default(1) 'hint_code_text': bool,\n @default(2) 'tab_width': @range[1, 32] u64,\n @can_be_per_window 'main_font_size': @range[6, 72] u64,\n @can_be_per_window 'code_font_size': @range[1, 32] u64,\n}\n")},
|
||||
{str8_lit_comp("target"), str8_lit_comp("@commands(launch_and_run, launch_and_init, select_cfg, remove_cfg)\n@collection_commands(add_target)\nx:\n{\n 'label': code_string,\n 'executable': path,\n 'arguments': string,\n 'working_directory': path,\n 'entry_point': code_string,\n 'stdout_path': path,\n 'stderr_path': path,\n 'stdin_path': path,\n 'debug_subprocesses': bool,\n 'environment': query,\n}\n")},
|
||||
{str8_lit_comp("breakpoint"), str8_lit_comp("@commands(enable_cfg, remove_cfg)\n@collection_commands(add_breakpoint, add_address_breakpoint, add_function_breakpoint)\nx:\n{\n 'label': code_string,\n 'condition': code_string,\n 'location': location,\n 'hit_count': u64,\n 'disabled': bool,\n}\n")},
|
||||
{str8_lit_comp("watch_pin"), str8_lit_comp("@commands(remove_cfg)\n@collection_commands(add_watch_pin)\nx:\n{\n 'expression': code_string,\n 'view_rule': code_string,\n 'location': location,\n}\n")},
|
||||
{str8_lit_comp("breakpoint"), str8_lit_comp("@commands(enable_cfg, remove_cfg)\n@collection_commands(add_breakpoint, add_address_breakpoint, add_function_breakpoint)\nx:\n{\n 'label': code_string,\n 'condition': code_string,\n 'source_location': path_pt,\n 'address_location': code_string,\n 'hit_count': u64,\n 'disabled': bool,\n}\n")},
|
||||
{str8_lit_comp("watch_pin"), str8_lit_comp("@commands(remove_cfg)\n@collection_commands(add_watch_pin)\nx:\n{\n 'expression': code_string,\n 'view_rule': code_string,\n 'source_location': path_pt,\n 'address_location': code_string,\n}\n")},
|
||||
{str8_lit_comp("file_path_map"), str8_lit_comp("@collection_commands(add_file_path_map) @commands(remove_cfg) x:{'source':path, 'dest':path}")},
|
||||
{str8_lit_comp("auto_view_rule"), str8_lit_comp("@collection_commands(add_auto_view_rule) @commands(remove_cfg) x:{'type':code_string, 'view_rule':code_string}")},
|
||||
{str8_lit_comp("recent_project"), str8_lit_comp("x:{'path':path}")},
|
||||
@@ -528,8 +530,8 @@ RD_CmdKindInfo rd_cmd_kind_info_table[213] =
|
||||
{ str8_lit_comp("duplicate_cfg"), str8_lit_comp("Duplicates a config tree."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}},
|
||||
{ str8_lit_comp("relocate_cfg"), str8_lit_comp("Relocates a config tree."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}},
|
||||
{ str8_lit_comp("add_breakpoint"), str8_lit_comp("Places a breakpoint at a given location (file path and line number, address, or symbol name)."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}},
|
||||
{ str8_lit_comp("add_address_breakpoint"), str8_lit_comp("Places a breakpoint on the specified address."), str8_lit_comp(""), str8_lit_comp("$breakpoints,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Vaddr, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}},
|
||||
{ str8_lit_comp("add_function_breakpoint"), str8_lit_comp("Places a breakpoint on the first address(es) of the specified function."), str8_lit_comp(""), str8_lit_comp("$breakpoints,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_String, str8_lit_comp("query:procedures"), str8_lit_comp("symbol_lister"), CTRL_EntityKind_Null}},
|
||||
{ str8_lit_comp("add_address_breakpoint"), str8_lit_comp("Places a breakpoint on the specified address."), str8_lit_comp(""), str8_lit_comp("$breakpoints,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Expr, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}},
|
||||
{ str8_lit_comp("add_function_breakpoint"), str8_lit_comp("Places a breakpoint on the first address(es) of the specified function."), str8_lit_comp(""), str8_lit_comp("$breakpoints,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Expr, str8_lit_comp("query:procedures"), str8_lit_comp("symbol_lister"), CTRL_EntityKind_Null}},
|
||||
{ str8_lit_comp("toggle_breakpoint"), str8_lit_comp("Places or removes a breakpoint at a given location (file path and line number, address, or symbol name)."), str8_lit_comp(""), str8_lit_comp("$text_pt,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}},
|
||||
{ str8_lit_comp("enable_breakpoint"), str8_lit_comp("Enables a breakpoint."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:breakpoints"), str8_lit_comp(""), CTRL_EntityKind_Null}},
|
||||
{ str8_lit_comp("disable_breakpoint"), str8_lit_comp("Disables a breakpoint."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:breakpoints"), str8_lit_comp(""), CTRL_EntityKind_Null}},
|
||||
|
||||
@@ -631,7 +631,7 @@ RD_Query query;
|
||||
.os_event = rd_regs()->os_event,\
|
||||
|
||||
C_LINKAGE_BEGIN
|
||||
extern RD_VocabInfo rd_vocab_info_table[293];
|
||||
extern RD_VocabInfo rd_vocab_info_table[295];
|
||||
extern RD_NameSchemaInfo rd_name_schema_info_table[12];
|
||||
extern Rng1U64 rd_reg_slot_range_table[40];
|
||||
extern String8 rd_binding_version_remap_old_name_table[8];
|
||||
|
||||
+14
-10
@@ -26,6 +26,8 @@ RD_VocabTable:
|
||||
{breakpoint _ "Breakpoint" _ CircleFilled }
|
||||
{condition _ "Condition" _ Null }
|
||||
{location _ "Location" _ Null }
|
||||
{source_location _ "Source Location" _ Null }
|
||||
{address_location _ "Address Location" _ Null }
|
||||
{target _ "Target" _ Target }
|
||||
{executable _ "Executable" _ Module }
|
||||
{arguments arguments "Arguments" "Arguments" Null }
|
||||
@@ -180,11 +182,12 @@ RD_VocabTable:
|
||||
@collection_commands(add_breakpoint, add_address_breakpoint, add_function_breakpoint)
|
||||
x:
|
||||
{
|
||||
'label': code_string,
|
||||
'condition': code_string,
|
||||
'location': location,
|
||||
'hit_count': u64,
|
||||
'disabled': bool,
|
||||
'label': code_string,
|
||||
'condition': code_string,
|
||||
'source_location': path_pt,
|
||||
'address_location': code_string,
|
||||
'hit_count': u64,
|
||||
'disabled': bool,
|
||||
}
|
||||
```,
|
||||
}
|
||||
@@ -197,9 +200,10 @@ RD_VocabTable:
|
||||
@collection_commands(add_watch_pin)
|
||||
x:
|
||||
{
|
||||
'expression': code_string,
|
||||
'view_rule': code_string,
|
||||
'location': location,
|
||||
'expression': code_string,
|
||||
'view_rule': code_string,
|
||||
'source_location': path_pt,
|
||||
'address_location': code_string,
|
||||
}
|
||||
```,
|
||||
}
|
||||
@@ -542,8 +546,8 @@ RD_CmdTable: // | | | |
|
||||
|
||||
//- rjf: breakpoints
|
||||
{AddBreakpoint 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 CircleFilled "add_breakpoint" "Add Breakpoint" "Places a breakpoint at a given location (file path and line number, address, or symbol name)." "" "" }
|
||||
{AddAddressBreakpoint 1 0 "" Vaddr null Nil Null 0 0 0 0 1 1 1 CircleFilled "add_address_breakpoint" "Add Address Breakpoint" "Places a breakpoint on the specified address." "" "$breakpoints," }
|
||||
{AddFunctionBreakpoint 1 0 "query:procedures" String symbol_lister Nil Null 0 0 0 0 1 1 1 CircleFilled "add_function_breakpoint" "Add Function Breakpoint" "Places a breakpoint on the first address(es) of the specified function." "" "$breakpoints," }
|
||||
{AddAddressBreakpoint 1 0 "" Expr null Nil Null 0 0 0 0 1 1 1 CircleFilled "add_address_breakpoint" "Add Address Breakpoint" "Places a breakpoint on the specified address." "" "$breakpoints," }
|
||||
{AddFunctionBreakpoint 1 0 "query:procedures" Expr symbol_lister Nil Null 0 0 0 0 1 1 1 CircleFilled "add_function_breakpoint" "Add Function Breakpoint" "Places a breakpoint on the first address(es) of the specified function." "" "$breakpoints," }
|
||||
{ToggleBreakpoint 1 1 "" Null null Nil Null 0 0 0 0 0 0 0 CircleFilled "toggle_breakpoint" "Toggle Breakpoint" "Places or removes a breakpoint at a given location (file path and line number, address, or symbol name)." "" "$text_pt," }
|
||||
{EnableBreakpoint 1 1 "query:breakpoints" Cfg null Breakpoint Null 0 0 0 0 0 0 1 CheckFilled "enable_breakpoint" "Enable Breakpoint" "Enables a breakpoint." "" "" }
|
||||
{DisableBreakpoint 1 1 "query:breakpoints" Cfg null Breakpoint Null 0 0 0 0 0 0 1 CheckHollow "disable_breakpoint" "Disable Breakpoint" "Disables a breakpoint." "" "" }
|
||||
|
||||
+73
-95
@@ -1627,12 +1627,12 @@ rd_cfg_tree_list_from_string(Arena *arena, String8 string)
|
||||
rd_cfg_insert_child(dst_active_parent_n, dst_active_parent_n->last, dst_n);
|
||||
}
|
||||
rec = md_node_rec_depth_first_pre(src_n, tln);
|
||||
if(dst_active_parent_n == &rd_nil_cfg)
|
||||
{
|
||||
dst_root_n = dst_n;
|
||||
}
|
||||
if(rec.push_count > 0)
|
||||
{
|
||||
if(dst_active_parent_n == &rd_nil_cfg)
|
||||
{
|
||||
dst_root_n = dst_n;
|
||||
}
|
||||
dst_active_parent_n = dst_n;
|
||||
}
|
||||
else for(S32 pop_idx = 0; pop_idx < rec.pop_count; pop_idx += 1)
|
||||
@@ -2094,8 +2094,9 @@ rd_location_from_cfg(RD_Cfg *cfg)
|
||||
{
|
||||
RD_Location dst_loc = {0};
|
||||
{
|
||||
RD_Cfg *src_loc = rd_cfg_child_from_string(cfg, str8_lit("location"));
|
||||
if(src_loc->first != &rd_nil_cfg && src_loc->first->first != &rd_nil_cfg)
|
||||
RD_Cfg *src_loc = rd_cfg_child_from_string(cfg, str8_lit("source_location"));
|
||||
RD_Cfg *addr_loc = rd_cfg_child_from_string(cfg, str8_lit("address_location"));
|
||||
if(src_loc != &rd_nil_cfg)
|
||||
{
|
||||
dst_loc.file_path = src_loc->first->string;
|
||||
try_s64_from_str8_c_rules(src_loc->first->first->string, &dst_loc.pt.line);
|
||||
@@ -2104,19 +2105,9 @@ rd_location_from_cfg(RD_Cfg *cfg)
|
||||
dst_loc.pt.column = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(addr_loc != &rd_nil_cfg)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
MD_TokenizeResult tokenize = md_tokenize_from_text(scratch.arena, src_loc->first->string);
|
||||
if(tokenize.tokens.count == 1 && tokenize.tokens.v[0].flags & (MD_TokenFlag_Identifier|MD_TokenFlag_StringLiteral))
|
||||
{
|
||||
dst_loc.name = src_loc->first->string;
|
||||
}
|
||||
else if(tokenize.tokens.count == 1 && tokenize.tokens.v[0].flags & MD_TokenFlag_Numeric)
|
||||
{
|
||||
try_u64_from_str8_c_rules(src_loc->first->string, &dst_loc.vaddr);
|
||||
}
|
||||
scratch_end(scratch);
|
||||
dst_loc.expr = addr_loc->first->string;
|
||||
}
|
||||
}
|
||||
return dst_loc;
|
||||
@@ -2547,7 +2538,7 @@ rd_eval_blob_from_cfg(Arena *arena, RD_Cfg *cfg)
|
||||
MD_Node *member_schema = md_child_from_string(schema, child_name, 0);
|
||||
String8 member_type_name = member_schema->first->string;
|
||||
RD_Cfg *child = rd_cfg_child_from_string(cfg, child_name);
|
||||
if(str8_match(member_type_name, str8_lit("location"), 0))
|
||||
if(str8_match(member_type_name, str8_lit("path_pt"), 0))
|
||||
{
|
||||
U64 off = type->byte_size + variable_width_parts.total_size;
|
||||
str8_list_push(scratch.arena, &fixed_width_parts, push_str8_copy(scratch.arena, str8_struct(&off)));
|
||||
@@ -5292,11 +5283,17 @@ rd_view_ui(Rng2F32 rect)
|
||||
}
|
||||
|
||||
// rjf: can edit? -> begin editing
|
||||
else if(cell_info.flags & RD_WatchCellFlag_CanEdit)
|
||||
else if(!(sig.f & UI_SignalFlag_KeyboardPressed) && cell_info.flags & RD_WatchCellFlag_CanEdit)
|
||||
{
|
||||
rd_cmd(RD_CmdKind_Edit);
|
||||
}
|
||||
|
||||
// rjf: can expand? -> expand
|
||||
else if(sig.f & UI_SignalFlag_KeyboardPressed && row_is_expandable)
|
||||
{
|
||||
next_row_expanded = !row_expanded;
|
||||
}
|
||||
|
||||
// rjf: can't edit, but has address info? -> go to address
|
||||
else if(cell_info.eval.space.kind == RD_EvalSpaceKind_CtrlEntity)
|
||||
{
|
||||
@@ -11838,6 +11835,10 @@ rd_regs_fill_slot_from_string(RD_RegSlot slot, String8 string)
|
||||
rd_regs()->cursor = pair.pt;
|
||||
}
|
||||
}break;
|
||||
case RD_RegSlot_Expr:
|
||||
{
|
||||
rd_regs()->expr = push_str8_copy(rd_frame_arena(), string);
|
||||
}break;
|
||||
case RD_RegSlot_Cursor:
|
||||
{
|
||||
U64 v = 0;
|
||||
@@ -13048,7 +13049,7 @@ rd_frame(void)
|
||||
E_TypeKey code_string_type_key = {0};
|
||||
E_TypeKey path_type_key = {0};
|
||||
E_TypeKey string_type_key = {0};
|
||||
E_TypeKey location_type_key = {0};
|
||||
E_TypeKey path_pt_type_key = {0};
|
||||
{
|
||||
E_MemberList vaddr_range_members_list = {0};
|
||||
e_member_list_push_new(scratch.arena, &vaddr_range_members_list, .type_key = e_type_key_basic(E_TypeKind_U64), .name = str8_lit("min"), .off = 0);
|
||||
@@ -13060,7 +13061,7 @@ rd_frame(void)
|
||||
code_string_type_key = e_type_key_cons_ptr(arch_from_context(), e_type_key_basic(E_TypeKind_U8), 1, E_TypeFlag_IsCodeText);
|
||||
path_type_key = e_type_key_cons_ptr(arch_from_context(), e_type_key_basic(E_TypeKind_U8), 1, E_TypeFlag_IsPathText);
|
||||
string_type_key = e_type_key_cons_ptr(arch_from_context(), e_type_key_basic(E_TypeKind_U8), 1, E_TypeFlag_IsPlainText);
|
||||
location_type_key = e_type_key_cons_ptr(arch_from_context(), e_type_key_basic(E_TypeKind_U8), 1, E_TypeFlag_IsPlainText|E_TypeFlag_IsCodeText|E_TypeFlag_IsPathText);
|
||||
path_pt_type_key = e_type_key_cons_ptr(arch_from_context(), e_type_key_basic(E_TypeKind_U8), 1, E_TypeFlag_IsPathText);
|
||||
}
|
||||
|
||||
//- rjf: build types for each evallable meta name
|
||||
@@ -13077,7 +13078,7 @@ rd_frame(void)
|
||||
{ str8_lit("code_string"), code_string_type_key },
|
||||
{ str8_lit("path"), path_type_key },
|
||||
{ str8_lit("string"), string_type_key },
|
||||
{ str8_lit("location"), location_type_key },
|
||||
{ str8_lit("path_pt"), path_pt_type_key },
|
||||
};
|
||||
E_TypeKey evallable_meta_types[ArrayCount(evallable_meta_names)] = {0};
|
||||
for EachElement(idx, evallable_meta_names)
|
||||
@@ -15822,25 +15823,38 @@ Z(getting_started)
|
||||
case RD_CmdKind_RelocateCfg:
|
||||
{
|
||||
RD_Cfg *cfg = rd_cfg_from_id(rd_regs()->cfg);
|
||||
RD_Cfg *loc = rd_cfg_child_from_string_or_alloc(cfg, str8_lit("location"));
|
||||
for(RD_Cfg *child = loc->first, *next = &rd_nil_cfg; child != &rd_nil_cfg; child = next)
|
||||
|
||||
// rjf: release old location info
|
||||
{
|
||||
next = child->next;
|
||||
rd_cfg_release(child);
|
||||
RD_Cfg *src_loc = rd_cfg_child_from_string(cfg, str8_lit("source_location"));
|
||||
RD_Cfg *addr_loc = rd_cfg_child_from_string(cfg, str8_lit("address_location"));
|
||||
rd_cfg_release(src_loc);
|
||||
rd_cfg_release(addr_loc);
|
||||
}
|
||||
if(rd_regs()->cursor.line != 0)
|
||||
|
||||
// rjf: attach new location info
|
||||
{
|
||||
RD_Cfg *file = rd_cfg_new(loc, rd_regs()->file_path);
|
||||
RD_Cfg *line = rd_cfg_newf(file, "%I64d", rd_regs()->cursor.line);
|
||||
rd_cfg_newf(line, "%I64d", rd_regs()->cursor.column);
|
||||
}
|
||||
else if(rd_regs()->vaddr != 0)
|
||||
{
|
||||
rd_cfg_newf(loc, "0x%I64x", rd_regs()->vaddr);
|
||||
}
|
||||
else if(rd_regs()->string.size != 0)
|
||||
{
|
||||
rd_cfg_new(loc, rd_regs()->string);
|
||||
String8 file_path = rd_regs()->file_path;
|
||||
TxtPt pt = rd_regs()->cursor;
|
||||
String8 expr_string = rd_regs()->expr;
|
||||
U64 vaddr = rd_regs()->vaddr;
|
||||
if(expr_string.size == 0 && vaddr != 0)
|
||||
{
|
||||
expr_string = push_str8f(scratch.arena, "0x%I64x", vaddr);
|
||||
}
|
||||
if(file_path.size != 0 && pt.line != 0)
|
||||
{
|
||||
RD_Cfg *src_loc = rd_cfg_new(cfg, str8_lit("source_location"));
|
||||
RD_Cfg *file = rd_cfg_new(src_loc, file_path);
|
||||
RD_Cfg *line = rd_cfg_newf(file, "%I64d", pt.line);
|
||||
RD_Cfg *col = rd_cfg_newf(line, "%I64d", pt.column);
|
||||
(void)col;
|
||||
}
|
||||
else if(expr_string.size != 0)
|
||||
{
|
||||
RD_Cfg *vaddr_loc = rd_cfg_new(cfg, str8_lit("address_location"));
|
||||
rd_cfg_new(vaddr_loc, expr_string);
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
@@ -15850,9 +15864,13 @@ Z(getting_started)
|
||||
{
|
||||
String8 file_path = rd_regs()->file_path;
|
||||
TxtPt pt = rd_regs()->cursor;
|
||||
String8 string = rd_regs()->string;
|
||||
U64 vaddr = rd_regs()->vaddr;
|
||||
if(file_path.size != 0 || string.size != 0 || vaddr != 0)
|
||||
String8 expr = rd_regs()->expr;
|
||||
if(expr.size == 0 && vaddr != 0)
|
||||
{
|
||||
expr = push_str8f(scratch.arena, "0x%I64x", vaddr);
|
||||
}
|
||||
if(file_path.size != 0 || expr.size != 0)
|
||||
{
|
||||
B32 removed_already_existing = 0;
|
||||
if(kind == RD_CmdKind_ToggleBreakpoint)
|
||||
@@ -15861,13 +15879,10 @@ Z(getting_started)
|
||||
for(RD_CfgNode *n = bps.first; n != 0; n = n->next)
|
||||
{
|
||||
RD_Cfg *bp = n->v;
|
||||
RD_Cfg *loc = rd_cfg_child_from_string(bp, str8_lit("location"));
|
||||
S64 loc_line = 0;
|
||||
U64 loc_vaddr = 0;
|
||||
B32 loc_matches_file_pt = (file_path.size != 0 && path_match_normalized(loc->first->string, file_path) && try_s64_from_str8_c_rules(loc->first->first->string, &loc_line) && loc_line == pt.line);
|
||||
B32 loc_matches_string = (string.size != 0 && str8_match(loc->first->string, string, 0));
|
||||
B32 loc_matches_vaddr = (vaddr != 0 && try_u64_from_str8_c_rules(loc->first->string, &loc_vaddr) && loc_vaddr == vaddr);
|
||||
if(loc_matches_file_pt || loc_matches_string || loc_matches_vaddr)
|
||||
RD_Location loc = rd_location_from_cfg(bp);
|
||||
B32 loc_matches_file_pt = (file_path.size != 0 && path_match_normalized(loc.file_path, file_path) && loc.pt.line == pt.line);
|
||||
B32 loc_matches_expr = (expr.size != 0 && str8_match(expr, loc.expr, 0));
|
||||
if(loc_matches_file_pt || loc_matches_expr)
|
||||
{
|
||||
rd_cfg_release(bp);
|
||||
removed_already_existing = 1;
|
||||
@@ -15879,30 +15894,14 @@ Z(getting_started)
|
||||
{
|
||||
RD_Cfg *project = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("project"));
|
||||
RD_Cfg *bp = rd_cfg_new(project, str8_lit("breakpoint"));
|
||||
RD_Cfg *loc = rd_cfg_new(bp, str8_lit("location"));
|
||||
if(vaddr != 0)
|
||||
{
|
||||
rd_cfg_newf(loc, "0x%I64x", vaddr);
|
||||
}
|
||||
else if(string.size != 0)
|
||||
{
|
||||
rd_cfg_new(loc, string);
|
||||
}
|
||||
else if(file_path.size != 0)
|
||||
{
|
||||
RD_Cfg *file_path_cfg = rd_cfg_new(loc, file_path);
|
||||
rd_cfg_newf(file_path_cfg, "%I64d", pt.line);
|
||||
}
|
||||
rd_cmd(RD_CmdKind_RelocateCfg, .cfg = bp->id);
|
||||
}
|
||||
}
|
||||
}break;
|
||||
case RD_CmdKind_AddAddressBreakpoint:
|
||||
{
|
||||
rd_cmd(RD_CmdKind_AddBreakpoint, .string = str8_zero());
|
||||
}break;
|
||||
case RD_CmdKind_AddFunctionBreakpoint:
|
||||
{
|
||||
rd_cmd(RD_CmdKind_AddBreakpoint, .vaddr = 0);
|
||||
rd_cmd(RD_CmdKind_AddBreakpoint);
|
||||
}break;
|
||||
|
||||
//- rjf: watch pins
|
||||
@@ -15922,17 +15921,13 @@ Z(getting_started)
|
||||
{
|
||||
RD_Cfg *wp = n->v;
|
||||
RD_Cfg *expr = rd_cfg_child_from_string(wp, str8_lit("expression"));
|
||||
RD_Cfg *loc = rd_cfg_child_from_string(wp, str8_lit("location"));
|
||||
S64 loc_line = 0;
|
||||
U64 loc_vaddr = 0;
|
||||
B32 loc_matches_file_pt = (file_path.size != 0 && path_match_normalized(loc->first->string, file_path) && try_s64_from_str8_c_rules(loc->first->first->string, &loc_line) && loc_line == pt.line);
|
||||
B32 loc_matches_vaddr = (vaddr != 0 && try_u64_from_str8_c_rules(loc->first->string, &loc_vaddr) && loc_vaddr == vaddr);
|
||||
B32 loc_matches_expr = (expr_string.size != 0 && str8_match(expr->first->string, expr_string, 0));
|
||||
if(loc_matches_expr && (loc_matches_file_pt || loc_matches_vaddr))
|
||||
RD_Location loc = rd_location_from_cfg(wp);
|
||||
B32 loc_matches_file_pt = (file_path.size != 0 && path_match_normalized(loc.file_path, file_path) && loc.pt.line == pt.line);
|
||||
B32 loc_matches_expr = (expr_string.size != 0 && str8_match(expr_string, loc.expr, 0));
|
||||
if((loc_matches_file_pt || loc_matches_expr) && str8_match(expr->first->string, expr_string, 0))
|
||||
{
|
||||
rd_cfg_release(wp);
|
||||
removed_already_existing = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15942,18 +15937,9 @@ Z(getting_started)
|
||||
RD_Cfg *wp = rd_cfg_new(project, str8_lit("watch_pin"));
|
||||
RD_Cfg *expr = rd_cfg_new(wp, str8_lit("expression"));
|
||||
RD_Cfg *view_rule = rd_cfg_new(wp, str8_lit("view_rule"));
|
||||
RD_Cfg *loc = rd_cfg_new(wp, str8_lit("location"));
|
||||
rd_cfg_new(expr, expr_string);
|
||||
rd_cfg_new(view_rule, view_rule_string);
|
||||
if(vaddr != 0)
|
||||
{
|
||||
rd_cfg_newf(loc, "0x%I64x", vaddr);
|
||||
}
|
||||
else if(file_path.size != 0)
|
||||
{
|
||||
RD_Cfg *file_path_cfg = rd_cfg_new(loc, file_path);
|
||||
rd_cfg_newf(file_path_cfg, "%I64d", pt.line);
|
||||
}
|
||||
rd_cmd(RD_CmdKind_RelocateCfg, .cfg = wp->id);
|
||||
}
|
||||
}break;
|
||||
|
||||
@@ -16790,8 +16776,7 @@ Z(getting_started)
|
||||
D_Breakpoint *dst_bp = &breakpoints.v[idx];
|
||||
dst_bp->file_path = src_bp_loc.file_path;
|
||||
dst_bp->pt = src_bp_loc.pt;
|
||||
dst_bp->symbol_name = src_bp_loc.name;
|
||||
dst_bp->vaddr = src_bp_loc.vaddr;
|
||||
dst_bp->vaddr_expr = src_bp_loc.expr;
|
||||
dst_bp->condition = non_ctrl_thread_static_condition;
|
||||
idx += 1;
|
||||
}
|
||||
@@ -16937,6 +16922,7 @@ Z(getting_started)
|
||||
try_u64_from_str8_c_rules(hit_count_root->first->string, &hit_count);
|
||||
RD_Location loc = rd_location_from_cfg(bp);
|
||||
D_LineList loc_lines = d_lines_from_file_path_line_num(scratch.arena, loc.file_path, loc.pt.line);
|
||||
E_Value loc_value = e_value_from_string(loc.expr);
|
||||
if(loc_lines.first != 0)
|
||||
{
|
||||
for(D_LineNode *n = loc_lines.first; n != 0; n = n->next)
|
||||
@@ -16948,18 +16934,10 @@ Z(getting_started)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(loc.vaddr != 0 && vaddr == loc.vaddr)
|
||||
else if(loc_value.u64 != 0 && vaddr == loc_value.u64)
|
||||
{
|
||||
hit_count += 1;
|
||||
}
|
||||
else if(loc.name.size != 0)
|
||||
{
|
||||
U64 symb_voff = d_voff_from_dbgi_key_symbol_name(&dbgi_key, loc.name);
|
||||
if(symb_voff == voff)
|
||||
{
|
||||
hit_count += 1;
|
||||
}
|
||||
}
|
||||
rd_cfg_new_replacef(hit_count_root, "%I64u", hit_count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,8 +339,7 @@ struct RD_Location
|
||||
{
|
||||
String8 file_path;
|
||||
TxtPt pt;
|
||||
U64 vaddr;
|
||||
String8 name;
|
||||
String8 expr;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
@@ -319,9 +319,10 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla
|
||||
{
|
||||
RD_Cfg *bp = n->v;
|
||||
RD_Location loc = rd_location_from_cfg(bp);
|
||||
if(contains_1u64(dasm_vaddr_range, loc.vaddr))
|
||||
E_Value loc_value = e_value_from_string(loc.expr);
|
||||
if(contains_1u64(dasm_vaddr_range, loc_value.u64))
|
||||
{
|
||||
U64 off = loc.vaddr - dasm_vaddr_range.min;
|
||||
U64 off = loc_value.u64 - dasm_vaddr_range.min;
|
||||
U64 idx = dasm_line_array_idx_from_code_off__linear_scan(dasm_lines, off);
|
||||
S64 line_num = (S64)idx+1;
|
||||
if(contains_1s64(visible_line_num_range, line_num))
|
||||
@@ -341,9 +342,10 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla
|
||||
{
|
||||
RD_Cfg *wp = n->v;
|
||||
RD_Location loc = rd_location_from_cfg(wp);
|
||||
if(contains_1u64(dasm_vaddr_range, loc.vaddr))
|
||||
E_Value loc_value = e_value_from_string(loc.expr);
|
||||
if(contains_1u64(dasm_vaddr_range, loc_value.u64))
|
||||
{
|
||||
U64 off = loc.vaddr - dasm_vaddr_range.min;
|
||||
U64 off = loc_value.u64 - dasm_vaddr_range.min;
|
||||
U64 idx = dasm_line_array_idx_from_code_off__linear_scan(dasm_lines, off);
|
||||
S64 line_num = (S64)idx+1;
|
||||
if(contains_1s64(visible_line_num_range, line_num))
|
||||
|
||||
@@ -250,6 +250,18 @@ rd_title_fstrs_from_cfg(Arena *arena, RD_Cfg *cfg)
|
||||
start_secondary();
|
||||
}
|
||||
|
||||
//- rjf: push address location
|
||||
if(loc.expr.size != 0)
|
||||
{
|
||||
RD_Font(RD_FontSlot_Code)
|
||||
{
|
||||
DR_FStrList fstrs = rd_fstrs_from_code_string(arena, 1.f, 0, params.color, loc.expr);
|
||||
dr_fstrs_concat_in_place(&result, &fstrs);
|
||||
}
|
||||
dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" "));
|
||||
start_secondary();
|
||||
}
|
||||
|
||||
//- rjf: push target executable name
|
||||
if(target.exe.size != 0)
|
||||
{
|
||||
@@ -291,7 +303,7 @@ rd_title_fstrs_from_cfg(Arena *arena, RD_Cfg *cfg)
|
||||
{
|
||||
String8 hit_count_value_string = rd_cfg_child_from_string(cfg, str8_lit("hit_count"))->first->string;
|
||||
U64 hit_count = 0;
|
||||
if(try_u64_from_str8_c_rules(hit_count_value_string, &hit_count))
|
||||
if(try_u64_from_str8_c_rules(hit_count_value_string, &hit_count) && hit_count != 0)
|
||||
{
|
||||
String8 hit_count_text = push_str8f(arena, "(%I64u hit%s)", hit_count, hit_count == 1 ? "" : "s");
|
||||
dr_fstrs_push_new(arena, &result, ¶ms, hit_count_text);
|
||||
|
||||
Reference in New Issue
Block a user