mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-07-12 04:21:25 -07:00
merge
This commit is contained in:
+428
-309
@@ -43,6 +43,21 @@ ctrl_event_cause_from_dmn_event_kind(DMN_EventKind event_kind)
|
||||
return cause;
|
||||
}
|
||||
|
||||
internal CTRL_ExceptionKind
|
||||
ctrl_exception_kind_from_dmn(DMN_ExceptionKind kind)
|
||||
{
|
||||
CTRL_ExceptionKind result = CTRL_ExceptionKind_Null;
|
||||
switch(kind)
|
||||
{
|
||||
default:{}break;
|
||||
case DMN_ExceptionKind_MemoryRead: {result = CTRL_ExceptionKind_MemoryRead;}break;
|
||||
case DMN_ExceptionKind_MemoryWrite: {result = CTRL_ExceptionKind_MemoryWrite;}break;
|
||||
case DMN_ExceptionKind_MemoryExecute: {result = CTRL_ExceptionKind_MemoryExecute;}break;
|
||||
case DMN_ExceptionKind_CppThrow: {result = CTRL_ExceptionKind_CppThrow;}break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
ctrl_string_from_event_kind(CTRL_EventKind kind)
|
||||
{
|
||||
@@ -91,6 +106,21 @@ ctrl_string_from_msg_kind(CTRL_MsgKind kind)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal CTRL_EntityKind
|
||||
ctrl_entity_kind_from_string(String8 string)
|
||||
{
|
||||
CTRL_EntityKind result = CTRL_EntityKind_Null;
|
||||
for EachNonZeroEnumVal(CTRL_EntityKind, k)
|
||||
{
|
||||
if(str8_match(ctrl_entity_kind_code_name_table[k], string, 0))
|
||||
{
|
||||
result = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Machine/Handle Pair Type Functions
|
||||
|
||||
@@ -136,6 +166,37 @@ ctrl_handle_list_copy(Arena *arena, CTRL_HandleList *src)
|
||||
return dst;
|
||||
}
|
||||
|
||||
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]);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal CTRL_Handle
|
||||
ctrl_handle_from_string(String8 string)
|
||||
{
|
||||
CTRL_Handle handle = {0};
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
U8 split = '$';
|
||||
String8List parts = str8_split(scratch.arena, string, &split, 1, 0);
|
||||
if(parts.first && parts.first->next)
|
||||
{
|
||||
CTRL_MachineID machine_id = 0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Trap Type Functions
|
||||
|
||||
@@ -201,7 +262,6 @@ ctrl_msg_deep_copy(Arena *arena, CTRL_Msg *dst, CTRL_Msg *src)
|
||||
dst->env_string_list = str8_list_copy(arena, &src->env_string_list);
|
||||
dst->traps = ctrl_trap_list_copy(arena, &src->traps);
|
||||
dst->user_bps = ctrl_user_breakpoint_list_copy(arena, &src->user_bps);
|
||||
dst->meta_evals = *deep_copy_from_struct(arena, CTRL_MetaEvalArray, &src->meta_evals);
|
||||
}
|
||||
|
||||
//- rjf: list building
|
||||
@@ -332,10 +392,6 @@ ctrl_serialized_string_from_msg_list(Arena *arena, CTRL_MsgList *msgs)
|
||||
str8_serial_push_struct(scratch.arena, &msgs_srlzed, &bp->condition.size);
|
||||
str8_serial_push_data(scratch.arena, &msgs_srlzed, bp->condition.str, bp->condition.size);
|
||||
}
|
||||
|
||||
// rjf: write meta-eval-info array
|
||||
String8 meta_evals_srlzed = serialized_from_struct(scratch.arena, CTRL_MetaEvalArray, &msg->meta_evals);
|
||||
str8_serial_push_string(scratch.arena, &msgs_srlzed, meta_evals_srlzed);
|
||||
}
|
||||
}
|
||||
String8 string = str8_serial_end(arena, &msgs_srlzed);
|
||||
@@ -459,12 +515,6 @@ ctrl_msg_list_from_serialized_string(Arena *arena, String8 string)
|
||||
bp->condition.str = push_array_no_zero(arena, U8, bp->condition.size);
|
||||
read_off += str8_deserial_read(string, read_off, bp->condition.str, bp->condition.size, 1);
|
||||
}
|
||||
|
||||
// rjf: read meta-eval-info array
|
||||
String8 meta_evals_data = str8_skip(string, read_off);
|
||||
U64 meta_evals_size = 0;
|
||||
msg->meta_evals = *struct_from_serialized(arena, CTRL_MetaEvalArray, meta_evals_data, .advance_out = &meta_evals_size);
|
||||
read_off += meta_evals_size;
|
||||
}
|
||||
}
|
||||
return msgs;
|
||||
@@ -639,95 +689,100 @@ ctrl_entity_store_release(CTRL_EntityStore *cache)
|
||||
//- rjf: string allocation/deletion
|
||||
|
||||
internal U64
|
||||
ctrl_name_bucket_idx_from_string_size(U64 size)
|
||||
ctrl_name_bucket_num_from_string_size(U64 size)
|
||||
{
|
||||
U64 size_rounded = u64_up_to_pow2(size+1);
|
||||
size_rounded = ClampBot((1<<4), size_rounded);
|
||||
U64 bucket_idx = 0;
|
||||
switch(size_rounded)
|
||||
U64 bucket_num = 0;
|
||||
if(size > 0)
|
||||
{
|
||||
case 1<<4: {bucket_idx = 0;}break;
|
||||
case 1<<5: {bucket_idx = 1;}break;
|
||||
case 1<<6: {bucket_idx = 2;}break;
|
||||
case 1<<7: {bucket_idx = 3;}break;
|
||||
case 1<<8: {bucket_idx = 4;}break;
|
||||
case 1<<9: {bucket_idx = 5;}break;
|
||||
case 1<<10:{bucket_idx = 6;}break;
|
||||
default:{bucket_idx = ArrayCount(((CTRL_EntityStore *)0)->free_string_chunks)-1;}break;
|
||||
for EachElement(idx, ctrl_entity_string_bucket_chunk_sizes)
|
||||
{
|
||||
if(size <= ctrl_entity_string_bucket_chunk_sizes[idx])
|
||||
{
|
||||
bucket_num = idx+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bucket_idx;
|
||||
return bucket_num;
|
||||
}
|
||||
|
||||
internal String8
|
||||
ctrl_entity_string_alloc(CTRL_EntityStore *store, String8 string)
|
||||
{
|
||||
if(string.size == 0) {return str8_zero();}
|
||||
U64 bucket_idx = ctrl_name_bucket_idx_from_string_size(string.size);
|
||||
CTRL_EntityStringChunkNode *node = store->free_string_chunks[bucket_idx];
|
||||
|
||||
// rjf: pull from bucket free list
|
||||
if(node != 0)
|
||||
//- rjf: allocate node
|
||||
CTRL_EntityStringChunkNode *node = 0;
|
||||
{
|
||||
if(bucket_idx == ArrayCount(store->free_string_chunks)-1)
|
||||
U64 bucket_num = ctrl_name_bucket_num_from_string_size(string.size);
|
||||
if(bucket_num == ArrayCount(ctrl_entity_string_bucket_chunk_sizes))
|
||||
{
|
||||
node = 0;
|
||||
CTRL_EntityStringChunkNode *prev = 0;
|
||||
for(CTRL_EntityStringChunkNode *n = store->free_string_chunks[bucket_idx];
|
||||
n != 0;
|
||||
prev = n, n = n->next)
|
||||
CTRL_EntityStringChunkNode *best_node = 0;
|
||||
CTRL_EntityStringChunkNode *best_node_prev = 0;
|
||||
U64 best_node_size = max_U64;
|
||||
{
|
||||
if(n->size >= string.size)
|
||||
for(CTRL_EntityStringChunkNode *n = store->free_string_chunks[bucket_num-1], *prev = 0; n != 0; (prev = n, n = n->next))
|
||||
{
|
||||
if(prev == 0)
|
||||
if(n->size >= string.size && n->size < best_node_size)
|
||||
{
|
||||
store->free_string_chunks[bucket_idx] = n->next;
|
||||
best_node = n;
|
||||
best_node_prev = prev;
|
||||
best_node_size = n->size;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev->next = n->next;
|
||||
}
|
||||
node = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(best_node != 0)
|
||||
{
|
||||
node = best_node;
|
||||
if(best_node_prev)
|
||||
{
|
||||
best_node_prev->next = best_node->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
store->free_string_chunks[bucket_num-1] = best_node->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
U64 chunk_size = u64_up_to_pow2(string.size);
|
||||
node = (CTRL_EntityStringChunkNode *)push_array(store->arena, U8, chunk_size);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(bucket_num != 0)
|
||||
{
|
||||
SLLStackPop(store->free_string_chunks[bucket_idx]);
|
||||
node = store->free_string_chunks[bucket_num-1];
|
||||
if(node != 0)
|
||||
{
|
||||
SLLStackPop(store->free_string_chunks[bucket_num-1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = (CTRL_EntityStringChunkNode *)push_array(store->arena, U8, ctrl_entity_string_bucket_chunk_sizes[bucket_num-1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: no found node -> allocate new
|
||||
if(node == 0)
|
||||
//- rjf: fill node
|
||||
String8 result = {0};
|
||||
if(node != 0)
|
||||
{
|
||||
U64 chunk_size = 0;
|
||||
if(bucket_idx < ArrayCount(store->free_string_chunks)-1)
|
||||
{
|
||||
chunk_size = 1<<(bucket_idx+4);
|
||||
}
|
||||
else
|
||||
{
|
||||
chunk_size = u64_up_to_pow2(string.size);
|
||||
}
|
||||
U8 *chunk_memory = push_array(store->arena, U8, chunk_size);
|
||||
node = (CTRL_EntityStringChunkNode *)chunk_memory;
|
||||
node->size = chunk_size;
|
||||
result.str = (U8 *)node;
|
||||
result.size = string.size;
|
||||
MemoryCopy(result.str, string.str, result.size);
|
||||
}
|
||||
|
||||
// rjf: fill string & return
|
||||
String8 allocated_string = str8((U8 *)node, string.size);
|
||||
MemoryCopy((U8 *)node, string.str, string.size);
|
||||
return allocated_string;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
ctrl_entity_string_release(CTRL_EntityStore *store, String8 string)
|
||||
{
|
||||
if(string.size == 0) {return;}
|
||||
U64 bucket_idx = ctrl_name_bucket_idx_from_string_size(string.size);
|
||||
CTRL_EntityStringChunkNode *node = (CTRL_EntityStringChunkNode *)string.str;
|
||||
node->size = u64_up_to_pow2(string.size);
|
||||
SLLStackPush(store->free_string_chunks[bucket_idx], node);
|
||||
U64 bucket_num = ctrl_name_bucket_num_from_string_size(string.size);
|
||||
if(1 <= bucket_num && bucket_num <= ArrayCount(rd_name_bucket_chunk_sizes))
|
||||
{
|
||||
U64 bucket_idx = bucket_num-1;
|
||||
CTRL_EntityStringChunkNode *node = (CTRL_EntityStringChunkNode *)string.str;
|
||||
SLLStackPush(store->free_string_chunks[bucket_idx], node);
|
||||
node->size = u64_up_to_pow2(string.size);
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: entity construction/deletion
|
||||
@@ -1305,7 +1360,6 @@ 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();
|
||||
ctrl_state->dbg_dir_arena = arena_alloc();
|
||||
for(CTRL_ExceptionCodeKind k = (CTRL_ExceptionCodeKind)0; k < CTRL_ExceptionCodeKind_COUNT; k = (CTRL_ExceptionCodeKind)(k+1))
|
||||
{
|
||||
@@ -1370,6 +1424,7 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B3
|
||||
|
||||
//- rjf: try to read from cache
|
||||
B32 is_good = 0;
|
||||
B32 process_node_exists = 0;
|
||||
B32 is_stale = 1;
|
||||
OS_MutexScopeR(process_stripe->rw_mutex)
|
||||
{
|
||||
@@ -1377,6 +1432,7 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B3
|
||||
{
|
||||
if(ctrl_handle_match(n->handle, process))
|
||||
{
|
||||
process_node_exists = 1;
|
||||
U64 range_slot_idx = range_hash%n->range_hash_slots_count;
|
||||
CTRL_ProcessMemoryRangeHashSlot *range_slot = &n->range_hash_slots[range_slot_idx];
|
||||
for(CTRL_ProcessMemoryRangeHashNode *range_n = range_slot->first; range_n != 0; range_n = range_n->next)
|
||||
@@ -1395,7 +1451,7 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B3
|
||||
}
|
||||
|
||||
//- rjf: not good -> create process cache node if necessary
|
||||
if(!is_good)
|
||||
if(!is_good && !process_node_exists)
|
||||
{
|
||||
OS_MutexScopeW(process_stripe->rw_mutex)
|
||||
{
|
||||
@@ -2994,44 +3050,118 @@ ctrl_unwind_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_Handle threa
|
||||
internal CTRL_CallStack
|
||||
ctrl_call_stack_from_unwind(Arena *arena, DI_Scope *di_scope, CTRL_Entity *process, CTRL_Unwind *base_unwind)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
Arch arch = process->arch;
|
||||
CTRL_CallStack result = {0};
|
||||
result.concrete_frame_count = base_unwind->frames.count;
|
||||
result.total_frame_count = result.concrete_frame_count;
|
||||
result.frames = push_array(arena, CTRL_CallStackFrame, result.concrete_frame_count);
|
||||
for(U64 idx = 0; idx < result.concrete_frame_count; idx += 1)
|
||||
{
|
||||
CTRL_UnwindFrame *src = &base_unwind->frames.v[idx];
|
||||
CTRL_CallStackFrame *dst = &result.frames[idx];
|
||||
U64 rip_vaddr = regs_rip_from_arch_block(arch, src->regs);
|
||||
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr);
|
||||
U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr);
|
||||
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module);
|
||||
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 0);
|
||||
RDI_Scope *scope = rdi_scope_from_voff(rdi, rip_voff);
|
||||
|
||||
// rjf: fill concrete frame info
|
||||
dst->regs = src->regs;
|
||||
dst->rdi = rdi;
|
||||
dst->procedure = rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx);
|
||||
|
||||
// rjf: push inline frames
|
||||
for(RDI_Scope *s = scope;
|
||||
s->inline_site_idx != 0;
|
||||
s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx))
|
||||
typedef struct FrameNode FrameNode;
|
||||
struct FrameNode
|
||||
{
|
||||
RDI_InlineSite *site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx);
|
||||
CTRL_CallStackInlineFrame *inline_frame = push_array(arena, CTRL_CallStackInlineFrame, 1);
|
||||
DLLPushFront(dst->first_inline_frame, dst->last_inline_frame, inline_frame);
|
||||
inline_frame->inline_site = site;
|
||||
dst->inline_frame_count += 1;
|
||||
result.inline_frame_count += 1;
|
||||
result.total_frame_count += 1;
|
||||
FrameNode *next;
|
||||
CTRL_CallStackFrame v;
|
||||
};
|
||||
|
||||
//- rjf: gather all frames
|
||||
FrameNode *first_frame = 0;
|
||||
FrameNode *last_frame = 0;
|
||||
U64 frame_count = 0;
|
||||
for(U64 base_frame_idx = 0; base_frame_idx < base_unwind->frames.count; base_frame_idx += 1)
|
||||
{
|
||||
// rjf: unpack
|
||||
CTRL_UnwindFrame *src = &base_unwind->frames.v[base_frame_idx];
|
||||
U64 rip_vaddr = regs_rip_from_arch_block(arch, src->regs);
|
||||
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr);
|
||||
U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr);
|
||||
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module);
|
||||
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 0);
|
||||
RDI_Scope *scope = rdi_scope_from_voff(rdi, rip_voff);
|
||||
|
||||
// rjf: build inline frames (minus parent & inline depth)
|
||||
FrameNode *first_inline_frame = 0;
|
||||
FrameNode *last_inline_frame = 0;
|
||||
U64 inline_frame_count = 0;
|
||||
for(RDI_Scope *s = scope;
|
||||
s->inline_site_idx != 0;
|
||||
s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx))
|
||||
{
|
||||
FrameNode *dst_inline = push_array(scratch.arena, FrameNode, 1);
|
||||
if(first_inline_frame == 0)
|
||||
{
|
||||
first_inline_frame = dst_inline;
|
||||
}
|
||||
last_inline_frame = dst_inline;
|
||||
SLLQueuePush(first_frame, last_frame, dst_inline);
|
||||
dst_inline->v.unwind_count = base_frame_idx;
|
||||
dst_inline->v.regs = src->regs;
|
||||
dst_inline->v.rdi = rdi;
|
||||
dst_inline->v.inline_site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx);
|
||||
frame_count += 1;
|
||||
inline_frame_count += 1;
|
||||
}
|
||||
|
||||
// rjf: build concrete frame
|
||||
FrameNode *dst_base = push_array(scratch.arena, FrameNode, 1);
|
||||
SLLQueuePush(first_frame, last_frame, dst_base);
|
||||
dst_base->v.unwind_count = base_frame_idx;
|
||||
dst_base->v.regs = src->regs;
|
||||
dst_base->v.rdi = rdi;
|
||||
dst_base->v.procedure = rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx);
|
||||
frame_count += 1;
|
||||
|
||||
// rjf: hook up inline frames to point to concrete frame, and to account for inline depth
|
||||
U64 inline_frame_idx = 0;
|
||||
for(FrameNode *inline_frame = first_inline_frame; inline_frame != 0; inline_frame = inline_frame->next, inline_frame_idx += 1)
|
||||
{
|
||||
inline_frame->v.parent_num = frame_count;
|
||||
inline_frame->v.inline_depth = inline_frame_count - inline_frame_idx;
|
||||
if(inline_frame == last_inline_frame)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: package
|
||||
result.count = frame_count;
|
||||
result.frames = push_array(arena, CTRL_CallStackFrame, result.count);
|
||||
{
|
||||
U64 idx = 0;
|
||||
for(FrameNode *n = first_frame; n != 0; n = n->next, idx += 1)
|
||||
{
|
||||
MemoryCopyStruct(&result.frames[idx], &n->v);
|
||||
}
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal CTRL_CallStackFrame *
|
||||
ctrl_call_stack_frame_from_unwind_and_inline_depth(CTRL_CallStack *call_stack, U64 unwind_count, U64 inline_depth)
|
||||
{
|
||||
CTRL_CallStackFrame *f = 0;
|
||||
{
|
||||
U64 base_frame_idx = 0;
|
||||
for(U64 idx = 0; idx < call_stack->count; idx += 1)
|
||||
{
|
||||
if(call_stack->frames[idx].parent_num == 0)
|
||||
{
|
||||
if(base_frame_idx == unwind_count)
|
||||
{
|
||||
f = &call_stack->frames[idx];
|
||||
break;
|
||||
}
|
||||
base_frame_idx += 1;
|
||||
}
|
||||
}
|
||||
if(f != 0 && call_stack->frames + inline_depth < f)
|
||||
{
|
||||
f -= inline_depth;
|
||||
}
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Halting All Attached Processes
|
||||
|
||||
@@ -3242,8 +3372,6 @@ ctrl_thread__entry_point(void *p)
|
||||
//- 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
|
||||
@@ -3331,11 +3459,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};
|
||||
@@ -3399,45 +3527,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4404,42 +4524,134 @@ ctrl_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range)
|
||||
//- 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;
|
||||
}
|
||||
|
||||
//- 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
|
||||
@@ -4771,25 +4983,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);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
@@ -5053,39 +5270,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;
|
||||
}
|
||||
|
||||
@@ -5406,118 +5632,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_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;
|
||||
{
|
||||
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->frame_base = push_array(temp.arena, U64, 1);
|
||||
ctx->tls_base = push_array(temp.arena, U64, 1);
|
||||
}
|
||||
e_select_interpret_ctx(&interpret_ctx, type_ctx.primary_module->rdi, type_ctx.ip_voff);
|
||||
|
||||
// rjf: evaluate
|
||||
E_Eval eval = zero_struct;
|
||||
ProfScope("evaluate expression")
|
||||
@@ -5540,7 +5657,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
|
||||
@@ -5848,6 +5965,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
event->entity = ctrl_handle_make(CTRL_MachineID_Local, stop_event->thread);
|
||||
event->parent = ctrl_handle_make(CTRL_MachineID_Local, stop_event->process);
|
||||
event->exception_code = stop_event->code;
|
||||
event->exception_kind = ctrl_exception_kind_from_dmn(stop_event->exception_kind);
|
||||
event->vaddr_rng = r1u64(stop_event->address, stop_event->address);
|
||||
event->rip_vaddr = stop_event->instruction_pointer;
|
||||
ctrl_c2u_push_events(&evts);
|
||||
@@ -5922,6 +6040,7 @@ ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
|
||||
event->entity = ctrl_handle_make(CTRL_MachineID_Local, stop_event->thread);
|
||||
event->parent = ctrl_handle_make(CTRL_MachineID_Local, stop_event->process);
|
||||
event->exception_code = stop_event->code;
|
||||
event->exception_kind = ctrl_exception_kind_from_dmn(stop_event->exception_kind);
|
||||
event->vaddr_rng = r1u64(stop_event->address, stop_event->address);
|
||||
event->rip_vaddr = stop_event->instruction_pointer;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user