mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-11 00:08:07 +00:00
sketch out stepping/eval exemplar testing; step-to-exit first pass
This commit is contained in:
+1
-1
@@ -41,6 +41,6 @@ target:
|
||||
{
|
||||
executable: "build/torture.exe"
|
||||
working_directory: build
|
||||
arguments: "raddbg/*"
|
||||
enabled: 1
|
||||
arguments: "raddbg/* --gui"
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ struct TestResult
|
||||
char *fail_cond;
|
||||
};
|
||||
|
||||
#define TEST_FUNCTION_SIG(name) void name(Arena *arena, CmdLine *cmdline, String8 test_artifacts_path, TestResult *result_out, String8List *test_out)
|
||||
#define TEST_FUNCTION_SIG(name) void name(Arena *arena, CmdLine *cmdline, String8 test_exemplars_path, String8 test_artifacts_path, TestResult *result_out, String8List *test_out)
|
||||
#define TEST_FUNCTION_DEF(name) TEST_FUNCTION_SIG(test__##name)
|
||||
typedef TEST_FUNCTION_SIG(TestFunctionType);
|
||||
|
||||
@@ -76,10 +76,18 @@ TEST_FUNCTION_DEF(name)
|
||||
#define SkippedTest(name) DeclareTest(name, 1)\
|
||||
TEST_FUNCTION_DEF(name)
|
||||
|
||||
#define test_out(string) str8_list_push(arena, test_out, (string))
|
||||
#define test_outf(...) str8_list_pushf(arena, test_out, __VA_ARGS__)
|
||||
|
||||
#define TestCheck(c) do { if (!(c)) {\
|
||||
*result_out = (TestResult){ .fail_file = __FILE__, .fail_line = __LINE__, .fail_cond = Stringify(c) };\
|
||||
if(debugger_is_attached()) { Trap(); }\
|
||||
return;\
|
||||
} } while(0)
|
||||
|
||||
#define TestSkip() do {\
|
||||
*result_out = (TestResult){ .status = TestStatus_Skip };\
|
||||
return;\
|
||||
} while(0)
|
||||
|
||||
#endif // BASE_TEST_H
|
||||
|
||||
@@ -21,6 +21,7 @@ D_CmdTable: // | | | |
|
||||
{StepIntoLine 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepInto "step_into_line" "Step Into (Line)" "Performs a step that goes into calls, at the source code line level." "step,thread" "" }
|
||||
{StepOverLine 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepOver "step_over_line" "Step Over (Line)" "Performs a step that skips calls, at the source code line level." "step,thread" "" }
|
||||
{StepOut 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepOut "step_out" "Step Out" "Runs to the first instruction after the current scope is exited." "" "" }
|
||||
{StepToExit 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepOut "step_to_exit" "Step To Exit" "Runs to the first encountered instruction which will exit the current scope." "" "" }
|
||||
{Halt 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Pause "halt" "Halt" "Halts all attached processes." "pause" "" }
|
||||
{SoftHaltRefresh 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Refresh "soft_halt_refresh" "Soft Halt Refresh" "Interrupts all attached processes to collect data, and then resumes them." "" "" }
|
||||
{SetThreadIP 0 1 0 0 "" Vaddr null Nil Null 0 0 0 0 1 1 1 Null "set_thread_ip" "Set Thread IP" "Sets the specified thread's instruction pointer at the specified address." "" "" }
|
||||
|
||||
@@ -447,6 +447,7 @@ d_trap_net_from_thread__step_over_line(Arena *arena, D_Entity *thread)
|
||||
DASM_InstFlag_UnconditionalJump|
|
||||
DASM_InstFlag_ChangesStackPointer|
|
||||
DASM_InstFlag_Return,
|
||||
0,
|
||||
arch,
|
||||
line_vaddr_rng.min,
|
||||
machine_code);
|
||||
@@ -641,6 +642,7 @@ d_trap_net_from_thread__step_into_line(Arena *arena, D_Entity *thread)
|
||||
DASM_InstFlag_UnconditionalJump|
|
||||
DASM_InstFlag_ChangesStackPointer|
|
||||
DASM_InstFlag_Return,
|
||||
0,
|
||||
arch,
|
||||
line_vaddr_rng.min,
|
||||
machine_code);
|
||||
@@ -807,7 +809,7 @@ d_trap_net_from_thread__step_out_scope(Arena *arena, D_Entity *thread)
|
||||
{
|
||||
result.good_read = 1;
|
||||
String8 code = code_slice.data;
|
||||
DASM_CtrlFlowInfo ctrl_flow_info = dasm_ctrl_flow_info_from_arch_vaddr_code(scratch.arena, DASM_InstFlag_Branch|DASM_InstFlag_UnconditionalJump|DASM_InstFlag_Return, arch, vaddr_range.min, code);
|
||||
DASM_CtrlFlowInfo ctrl_flow_info = dasm_ctrl_flow_info_from_arch_vaddr_code(scratch.arena, DASM_InstFlag_Branch|DASM_InstFlag_UnconditionalJump|DASM_InstFlag_Return, 0, arch, vaddr_range.min, code);
|
||||
|
||||
// rjf: add traps at all jump destinations which do *not* fall into any of the scope's ranges
|
||||
for EachNode(exit_pt_n, DASM_CtrlFlowPointNode, ctrl_flow_info.exit_points.first)
|
||||
@@ -878,6 +880,105 @@ d_trap_net_from_thread__step_out_scope(Arena *arena, D_Entity *thread)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal D_TrapNet
|
||||
d_trap_net_from_thread__step_to_exit(Arena *arena, D_Entity *thread)
|
||||
{
|
||||
D_TrapNet result = {0};
|
||||
{
|
||||
U64 read_endt_us = now_time_us() + 1000000;
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
Access *access = access_open();
|
||||
|
||||
// rjf: unpack thread
|
||||
Arch arch = thread->arch;
|
||||
U64 ip_vaddr = d_cached_ip_from_thread(thread->handle);
|
||||
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
||||
D_Entity *module = d_module_from_process_vaddr(process, ip_vaddr);
|
||||
DI_Key dbgi_key = d_dbgi_key_from_module(module);
|
||||
D_CallStack callstack = d_call_stack_from_thread(access, thread->handle, 1, read_endt_us);
|
||||
|
||||
// rjf: ip => enclosing scope's list(voff_range)
|
||||
Rng1U64List scope_voff_rngs = {0};
|
||||
{
|
||||
U64 ip_voff = d_voff_from_vaddr(module, ip_vaddr);
|
||||
RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 1, 0);
|
||||
if(rdi != &rdi_parsed_nil)
|
||||
{
|
||||
RDI_Scope *scope = rdi_scope_from_voff(rdi, ip_voff);
|
||||
U64 all_scope_voffs_count = 0;
|
||||
U64 *all_scope_voffs = rdi_table_from_name(rdi, ScopeVOffData, &all_scope_voffs_count);
|
||||
for(U64 voff_idx = scope->voff_range_first; voff_idx+1 < scope->voff_range_opl; voff_idx += 1)
|
||||
{
|
||||
Rng1U64 voff_range = r1u64(all_scope_voffs[voff_idx], all_scope_voffs[voff_idx+1]);
|
||||
rng1u64_list_push(scratch.arena, &scope_voff_rngs, voff_range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: place traps at all possible exit points of all scope's ranges
|
||||
result.good_read = 1;
|
||||
for EachNode(n, Rng1U64Node, scope_voff_rngs.first)
|
||||
{
|
||||
Rng1U64 voff_range = n->v;
|
||||
Rng1U64 vaddr_range = d_vaddr_range_from_voff_range(module, voff_range);
|
||||
D_ProcessMemorySlice code_slice = d_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, vaddr_range, 0, read_endt_us);
|
||||
if(!code_slice.any_byte_bad)
|
||||
{
|
||||
result.good_read = 1;
|
||||
String8 code = code_slice.data;
|
||||
DASM_CtrlFlowInfo ctrl_flow_info = dasm_ctrl_flow_info_from_arch_vaddr_code(scratch.arena, DASM_InstFlag_Branch|DASM_InstFlag_UnconditionalJump|DASM_InstFlag_Return, 1, arch, vaddr_range.min, code);
|
||||
|
||||
// rjf: add traps at all jumps whose destinations do *not* fall into any of the scope's ranges
|
||||
for EachNode(exit_pt_n, DASM_CtrlFlowPointNode, ctrl_flow_info.exit_points.first)
|
||||
{
|
||||
U64 jump_vaddr = exit_pt_n->v.vaddr;
|
||||
U64 jump_dest_vaddr = exit_pt_n->v.jump_dest_vaddr;
|
||||
B32 jump_dest_vaddr_is_out_of_scope = 1;
|
||||
for EachNode(scope_n, Rng1U64Node, scope_voff_rngs.first)
|
||||
{
|
||||
if(contains_1u64(scope_n->v, d_voff_from_vaddr(module, jump_dest_vaddr)))
|
||||
{
|
||||
jump_dest_vaddr_is_out_of_scope = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(jump_dest_vaddr_is_out_of_scope)
|
||||
{
|
||||
D_Trap trap = {D_TrapFlag_EndStepping|D_TrapFlag_IgnoreStackPointerCheck, jump_vaddr};
|
||||
d_trap_list_push(arena, &result.traps, &trap);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.good_read = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: use first unwind frame to generate trap
|
||||
if(result.good_read && callstack.concrete_frames_count > 1)
|
||||
{
|
||||
ARCH_Info *arch_info = arch_info_from_arch(thread->arch);
|
||||
U64 vaddr = arch_ip_from_reg_block(arch_info, callstack.concrete_frames[1]->regs);
|
||||
D_Trap trap = {D_TrapFlag_EndStepping|D_TrapFlag_IgnoreStackPointerCheck, vaddr};
|
||||
d_trap_list_push(arena, &result.traps, &trap);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.good_read = 0;
|
||||
}
|
||||
|
||||
// NOTE(rjf): we always want to support missing line info for "step to exit", because
|
||||
// we should always be able to fall back to just using the unwind, so just always
|
||||
// mark this bit as a success.
|
||||
result.good_line_info = 1;
|
||||
access_close(access);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Debug Info Lookups
|
||||
|
||||
@@ -1315,6 +1416,12 @@ d_ctrl_targets_running(void)
|
||||
return d_user_state->ctrl_is_running;
|
||||
}
|
||||
|
||||
internal U64
|
||||
d_stop_count(void)
|
||||
{
|
||||
return d_user_state->stop_count;
|
||||
}
|
||||
|
||||
//- rjf: active entity based queries
|
||||
|
||||
internal DI_KeyList
|
||||
@@ -1610,6 +1717,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
|
||||
case D_EventKind_Stopped:
|
||||
{
|
||||
d_user_state->stop_count += 1;
|
||||
d_user_state->ctrl_is_running = 0;
|
||||
d_user_state->ctrl_thread_run_state = 0;
|
||||
d_user_state->ctrl_soft_halt_issued = 0;
|
||||
@@ -1903,6 +2011,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
case D_CmdKind_StepIntoLine:
|
||||
case D_CmdKind_StepOverLine:
|
||||
case D_CmdKind_StepOut:
|
||||
case D_CmdKind_StepToExit:
|
||||
{
|
||||
D_Entity *thread = d_entity_from_handle(params->thread);
|
||||
if(thread == &d_entity_nil)
|
||||
@@ -1931,6 +2040,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
case D_CmdKind_StepIntoLine: {trap_net = d_trap_net_from_thread__step_into_line(scratch.arena, thread);}break;
|
||||
case D_CmdKind_StepOverLine: {trap_net = d_trap_net_from_thread__step_over_line(scratch.arena, thread);}break;
|
||||
case D_CmdKind_StepOut: {trap_net = d_trap_net_from_thread__step_out_scope(scratch.arena, thread);}break;
|
||||
case D_CmdKind_StepToExit: {trap_net = d_trap_net_from_thread__step_to_exit(scratch.arena, thread);}break;
|
||||
}
|
||||
B32 good_trap_net = (trap_net.good_read || !trap_net.good_line_info);
|
||||
if(good_trap_net && trap_net.traps.count != 0)
|
||||
|
||||
@@ -378,6 +378,7 @@ struct D_UserState
|
||||
D_EntityCtxRWStore *ctrl_entity_store;
|
||||
Arena *ctrl_stop_arena;
|
||||
D_Event ctrl_last_stop_event;
|
||||
U64 stop_count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
@@ -424,6 +425,7 @@ internal D_TrapNet d_trap_net_from_thread__step_over_inst(Arena *arena, D_Entity
|
||||
internal D_TrapNet d_trap_net_from_thread__step_over_line(Arena *arena, D_Entity *thread);
|
||||
internal D_TrapNet d_trap_net_from_thread__step_into_line(Arena *arena, D_Entity *thread);
|
||||
internal D_TrapNet d_trap_net_from_thread__step_out_scope(Arena *arena, D_Entity *thread);
|
||||
internal D_TrapNet d_trap_net_from_thread__step_to_exit(Arena *arena, D_Entity *thread);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Debug Info Lookups
|
||||
@@ -460,6 +462,7 @@ internal U64 d_frame_index(void);
|
||||
internal D_RunKind d_ctrl_last_run_kind(void);
|
||||
internal U64 d_ctrl_last_run_frame_idx(void);
|
||||
internal B32 d_ctrl_targets_running(void);
|
||||
internal U64 d_stop_count(void);
|
||||
|
||||
//- rjf: active entity based queries
|
||||
internal DI_KeyList d_push_active_dbgi_key_list(Arena *arena);
|
||||
|
||||
@@ -20,6 +20,7 @@ D_CmdKind_StepOverInst,
|
||||
D_CmdKind_StepIntoLine,
|
||||
D_CmdKind_StepOverLine,
|
||||
D_CmdKind_StepOut,
|
||||
D_CmdKind_StepToExit,
|
||||
D_CmdKind_Halt,
|
||||
D_CmdKind_SoftHaltRefresh,
|
||||
D_CmdKind_SetThreadIP,
|
||||
|
||||
+2
-2
@@ -28,7 +28,7 @@ dasm_inst_from_code(Arena *arena, Arch arch, U64 vaddr, String8 code, DASM_Synta
|
||||
//~ rjf: Control Flow Analysis
|
||||
|
||||
internal DASM_CtrlFlowInfo
|
||||
dasm_ctrl_flow_info_from_arch_vaddr_code(Arena *arena, DASM_InstFlags exit_points_mask, Arch arch, U64 vaddr, String8 code)
|
||||
dasm_ctrl_flow_info_from_arch_vaddr_code(Arena *arena, DASM_InstFlags exit_points_mask, B32 include_last_inst, Arch arch, U64 vaddr, String8 code)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
DASM_CtrlFlowInfo info = {0};
|
||||
@@ -38,7 +38,7 @@ dasm_ctrl_flow_info_from_arch_vaddr_code(Arena *arena, DASM_InstFlags exit_point
|
||||
U64 inst_vaddr = vaddr+offset;
|
||||
offset += inst.size;
|
||||
info.total_size += inst.size;
|
||||
if(inst.flags & exit_points_mask)
|
||||
if(inst.flags & exit_points_mask || (include_last_inst && offset >= code.size))
|
||||
{
|
||||
DASM_CtrlFlowPoint point = {0};
|
||||
point.inst_flags = inst.flags;
|
||||
|
||||
+1
-1
@@ -183,7 +183,7 @@ internal DASM_Inst dasm_inst_from_code(Arena *arena, Arch arch, U64 vaddr, Strin
|
||||
////////////////////////////////
|
||||
//~ rjf: Control Flow Analysis
|
||||
|
||||
internal DASM_CtrlFlowInfo dasm_ctrl_flow_info_from_arch_vaddr_code(Arena *arena, DASM_InstFlags exit_points_mask, Arch arch, U64 vaddr, String8 code);
|
||||
internal DASM_CtrlFlowInfo dasm_ctrl_flow_info_from_arch_vaddr_code(Arena *arena, DASM_InstFlags exit_points_mask, B32 include_last_inst, Arch arch, U64 vaddr, String8 code);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parameter Type Functions
|
||||
|
||||
@@ -1205,6 +1205,110 @@ md_debug_string_list_from_tree(Arena *arena, MD_Node *root)
|
||||
return strings;
|
||||
}
|
||||
|
||||
internal String8List
|
||||
md_string_list_from_tree(Arena *arena, MD_Node *root)
|
||||
{
|
||||
String8List strings = {0};
|
||||
{
|
||||
char *indentation = " ";
|
||||
S32 depth = 0;
|
||||
B32 delimit_with_newlines = 1;
|
||||
for(MD_Node *node = root, *next = &md_nil_node; !md_node_is_nil(node); node = next)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
// rjf: get next recursion
|
||||
MD_NodeRec rec = md_node_rec_depth_first_pre(node, root);
|
||||
next = rec.next;
|
||||
|
||||
// rjf: sanitize string
|
||||
String8 node_string_sanitized = node->string;
|
||||
{
|
||||
MD_TokenizeResult tokenize = md_tokenize_from_text(scratch.arena, node_string_sanitized);
|
||||
B32 is_simple_string = (tokenize.tokens.count == 1 && (tokenize.tokens.v[0].flags & (MD_TokenFlag_Identifier|
|
||||
MD_TokenFlag_Numeric)));
|
||||
if(tokenize.tokens.count > 0 && !is_simple_string)
|
||||
{
|
||||
node_string_sanitized = str8f(scratch.arena, "\"%S\"", escaped_from_raw_str8(scratch.arena, node_string_sanitized));
|
||||
}
|
||||
if(node_string_sanitized.size == 0 && node->first == &md_nil_node)
|
||||
{
|
||||
node_string_sanitized = s("\"\"");
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: turn off newline delimiting for implicit child sets
|
||||
B32 next_delimit_with_newlines = delimit_with_newlines;
|
||||
if(node->first != &md_nil_node && !(node->flags & (MD_NodeFlag_HasParenLeft|MD_NodeFlag_HasBracketLeft|MD_NodeFlag_HasBraceLeft)))
|
||||
{
|
||||
next_delimit_with_newlines = 0;
|
||||
}
|
||||
|
||||
// rjf: push node line
|
||||
if(node_string_sanitized.size != 0)
|
||||
{
|
||||
str8_list_pushf(arena, &strings, "%.*s%S%S%S", delimit_with_newlines ? depth : 1, indentation, node_string_sanitized,
|
||||
(rec.push_count != 0 && node_string_sanitized.size != 0) ? s(":") : s(""),
|
||||
next_delimit_with_newlines ? s("\n") : s(""));
|
||||
}
|
||||
|
||||
// rjf: children -> open brace
|
||||
if(rec.push_count != 0)
|
||||
{
|
||||
String8 opener_symbol = s("");
|
||||
if(node->flags & MD_NodeFlag_HasParenLeft) { opener_symbol = s("("); }
|
||||
if(node->flags & MD_NodeFlag_HasBracketLeft) { opener_symbol = s("["); }
|
||||
if(node->flags & MD_NodeFlag_HasBraceLeft) { opener_symbol = s("{"); }
|
||||
if(opener_symbol.size != 0)
|
||||
{
|
||||
str8_list_pushf(arena, &strings, "%.*s%S\n", depth, indentation, opener_symbol);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: descend
|
||||
depth += rec.push_count;
|
||||
delimit_with_newlines = next_delimit_with_newlines;
|
||||
|
||||
// rjf: popping -> close braces
|
||||
{
|
||||
MD_Node *popped = node->parent;
|
||||
for(S32 pop_idx = 0; pop_idx < rec.pop_count; pop_idx += 1, popped = popped->parent)
|
||||
{
|
||||
String8 closer_symbol = s("");
|
||||
if(popped->flags & MD_NodeFlag_HasParenRight) { closer_symbol = s(")"); }
|
||||
if(popped->flags & MD_NodeFlag_HasBracketRight) { closer_symbol = s("]"); }
|
||||
if(popped->flags & MD_NodeFlag_HasBraceRight) { closer_symbol = s("}"); }
|
||||
if(!delimit_with_newlines)
|
||||
{
|
||||
str8_list_push(arena, &strings, s("\n"));
|
||||
delimit_with_newlines = 1;
|
||||
}
|
||||
else if(closer_symbol.size != 0)
|
||||
{
|
||||
str8_list_pushf(arena, &strings, "%.*s%S\n", (depth-1-pop_idx), indentation, closer_symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: ascend
|
||||
depth -= rec.pop_count;
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
}
|
||||
return strings;
|
||||
}
|
||||
|
||||
internal String8
|
||||
md_string_from_tree(Arena *arena, MD_Node *root)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8List strings = md_string_list_from_tree(scratch.arena, root);
|
||||
String8 string = str8_list_join(arena, &strings, 0);
|
||||
scratch_end(scratch);
|
||||
return string;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Node Pointer List Functions
|
||||
|
||||
|
||||
@@ -336,6 +336,8 @@ internal MD_ParseResult md_parse_from_text(Arena *arena, String8 filename, Strin
|
||||
//~ rjf: Tree -> Text Functions
|
||||
|
||||
internal String8List md_debug_string_list_from_tree(Arena *arena, MD_Node *root);
|
||||
internal String8List md_string_list_from_tree(Arena *arena, MD_Node *root);
|
||||
internal String8 md_string_from_tree(Arena *arena, MD_Node *root);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Node Pointer List Functions
|
||||
|
||||
@@ -700,12 +700,14 @@ type_coverage_eval_tests(void)
|
||||
int_vector.push_back(6);
|
||||
int_vector.push_back(7);
|
||||
|
||||
#if 0
|
||||
std::unordered_map<std::string, int> people =
|
||||
{
|
||||
{"Peter", 1},
|
||||
{"Oliver", 2},
|
||||
{"Jack", 3},
|
||||
};
|
||||
#endif
|
||||
|
||||
std::vector<int> *pint_vector = &int_vector;
|
||||
std::vector<int> &rint_vector = int_vector;
|
||||
@@ -718,9 +720,9 @@ type_coverage_eval_tests(void)
|
||||
|
||||
SizedKind sized_kind = SizedKind_C;
|
||||
|
||||
variadic_params("foo", 123, 456);
|
||||
|
||||
int x = (int)(Anonymous_D);
|
||||
|
||||
variadic_params("foo", 123, 456);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@@ -3198,7 +3200,6 @@ mule_main(int argc, char** argv)
|
||||
|
||||
mule_init();
|
||||
|
||||
// NOTE(allen): Eval Tests
|
||||
type_coverage_eval_tests();
|
||||
|
||||
mutating_variables_eval_tests();
|
||||
@@ -3231,9 +3232,6 @@ mule_main(int argc, char** argv)
|
||||
|
||||
exception_filter_test();
|
||||
|
||||
markup_tests();
|
||||
|
||||
// NOTE(allen): Stepping Tests
|
||||
control_flow_stepping_tests();
|
||||
|
||||
indirect_call_jump_stepping_tests();
|
||||
@@ -3264,6 +3262,8 @@ mule_main(int argc, char** argv)
|
||||
|
||||
interrupt_stepping_tests();
|
||||
|
||||
markup_tests();
|
||||
|
||||
exception_stepping_tests();
|
||||
|
||||
return(0);
|
||||
|
||||
@@ -62,7 +62,7 @@ str8_lit_comp(""),
|
||||
str8_lit_comp(""),
|
||||
};
|
||||
|
||||
RD_VocabInfo rd_vocab_info_table[364] =
|
||||
RD_VocabInfo rd_vocab_info_table[365] =
|
||||
{
|
||||
{str8_lit_comp("type_view"), str8_lit_comp("type_views"), str8_lit_comp("Type View"), str8_lit_comp("Type Views"), 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},
|
||||
@@ -188,6 +188,7 @@ RD_VocabInfo rd_vocab_info_table[364] =
|
||||
{str8_lit_comp("step_into_line"), str8_lit_comp(""), str8_lit_comp("Step Into (Line)"), str8_lit_comp(""), RD_IconKind_StepInto},
|
||||
{str8_lit_comp("step_over_line"), str8_lit_comp(""), str8_lit_comp("Step Over (Line)"), str8_lit_comp(""), RD_IconKind_StepOver},
|
||||
{str8_lit_comp("step_out"), str8_lit_comp(""), str8_lit_comp("Step Out"), str8_lit_comp(""), RD_IconKind_StepOut},
|
||||
{str8_lit_comp("step_to_exit"), str8_lit_comp(""), str8_lit_comp("Step To Exit"), str8_lit_comp(""), RD_IconKind_StepOut},
|
||||
{str8_lit_comp("halt"), str8_lit_comp(""), str8_lit_comp("Halt"), str8_lit_comp(""), RD_IconKind_Pause},
|
||||
{str8_lit_comp("soft_halt_refresh"), str8_lit_comp(""), str8_lit_comp("Soft Halt Refresh"), str8_lit_comp(""), RD_IconKind_Refresh},
|
||||
{str8_lit_comp("set_thread_ip"), str8_lit_comp(""), str8_lit_comp("Set Thread IP"), str8_lit_comp(""), RD_IconKind_Null},
|
||||
@@ -473,7 +474,7 @@ RD_NameSchemaInfo rd_name_schema_info_table[39] =
|
||||
{str8_lit_comp("thread"), 0, str8_lit_comp("x:{'label':code_string, 'id':u64, @no_expand 'active':bool, 'call_stack':set}")},
|
||||
};
|
||||
|
||||
String8 rd_reg_slot_code_name_table[49] =
|
||||
String8 rd_reg_slot_code_name_table[50] =
|
||||
{
|
||||
{0},
|
||||
str8_lit_comp("machine"),
|
||||
@@ -520,13 +521,14 @@ str8_lit_comp("all_windows"),
|
||||
str8_lit_comp("non_graphical"),
|
||||
str8_lit_comp("prefer_new_tab"),
|
||||
str8_lit_comp("activate_with_single_click"),
|
||||
str8_lit_comp("disable_addresses"),
|
||||
str8_lit_comp("dir2"),
|
||||
str8_lit_comp("string"),
|
||||
str8_lit_comp("cmd_name"),
|
||||
str8_lit_comp("wm_event"),
|
||||
};
|
||||
|
||||
Rng1U64 rd_reg_slot_range_table[49] =
|
||||
Rng1U64 rd_reg_slot_range_table[50] =
|
||||
{
|
||||
{0},
|
||||
{OffsetOf(RD_Regs, machine), OffsetOf(RD_Regs, machine) + sizeof(D_Handle)},
|
||||
@@ -573,13 +575,14 @@ Rng1U64 rd_reg_slot_range_table[49] =
|
||||
{OffsetOf(RD_Regs, non_graphical), OffsetOf(RD_Regs, non_graphical) + sizeof(B32)},
|
||||
{OffsetOf(RD_Regs, prefer_new_tab), OffsetOf(RD_Regs, prefer_new_tab) + sizeof(B32)},
|
||||
{OffsetOf(RD_Regs, activate_with_single_click), OffsetOf(RD_Regs, activate_with_single_click) + sizeof(B32)},
|
||||
{OffsetOf(RD_Regs, disable_addresses), OffsetOf(RD_Regs, disable_addresses) + sizeof(B32)},
|
||||
{OffsetOf(RD_Regs, dir2), OffsetOf(RD_Regs, dir2) + sizeof(Dir2)},
|
||||
{OffsetOf(RD_Regs, string), OffsetOf(RD_Regs, string) + sizeof(String8)},
|
||||
{OffsetOf(RD_Regs, cmd_name), OffsetOf(RD_Regs, cmd_name) + sizeof(String8)},
|
||||
{OffsetOf(RD_Regs, wm_event), OffsetOf(RD_Regs, wm_event) + sizeof(WM_Event *)},
|
||||
};
|
||||
|
||||
RD_CmdKindInfo rd_cmd_kind_info_table[252] =
|
||||
RD_CmdKindInfo rd_cmd_kind_info_table[253] =
|
||||
{
|
||||
{0},
|
||||
{ str8_lit_comp("launch_and_run"), str8_lit_comp("Starts debugging a new instance of a target, then runs."), str8_lit_comp("launch,start,run,target"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:targets"), str8_lit_comp(""), D_EntityKind_Null}},
|
||||
@@ -593,6 +596,7 @@ RD_CmdKindInfo rd_cmd_kind_info_table[252] =
|
||||
{ str8_lit_comp("step_into_line"), str8_lit_comp("Performs a step that goes into calls, at the source code line level."), str8_lit_comp("step,thread"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*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(""), D_EntityKind_Null}},
|
||||
{ str8_lit_comp("step_over_line"), str8_lit_comp("Performs a step that skips calls, at the source code line level."), str8_lit_comp("step,thread"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*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(""), D_EntityKind_Null}},
|
||||
{ str8_lit_comp("step_out"), str8_lit_comp("Runs to the first instruction after the current scope is exited."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*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(""), D_EntityKind_Null}},
|
||||
{ str8_lit_comp("step_to_exit"), str8_lit_comp("Runs to the first encountered instruction which will exit the current scope."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*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(""), D_EntityKind_Null}},
|
||||
{ str8_lit_comp("halt"), str8_lit_comp("Halts all attached processes."), str8_lit_comp("pause"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*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(""), D_EntityKind_Null}},
|
||||
{ str8_lit_comp("soft_halt_refresh"), str8_lit_comp("Interrupts all attached processes to collect data, and then resumes them."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*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(""), D_EntityKind_Null}},
|
||||
{ str8_lit_comp("set_thread_ip"), str8_lit_comp("Sets the specified thread's instruction pointer at the specified address."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*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(""), D_EntityKind_Null}},
|
||||
|
||||
@@ -53,6 +53,7 @@ RD_RegSlot_AllWindows,
|
||||
RD_RegSlot_NonGraphical,
|
||||
RD_RegSlot_PreferNewTab,
|
||||
RD_RegSlot_ActivateWithSingleClick,
|
||||
RD_RegSlot_DisableAddresses,
|
||||
RD_RegSlot_Dir2,
|
||||
RD_RegSlot_String,
|
||||
RD_RegSlot_CmdName,
|
||||
@@ -74,6 +75,7 @@ RD_CmdKind_StepOverInst,
|
||||
RD_CmdKind_StepIntoLine,
|
||||
RD_CmdKind_StepOverLine,
|
||||
RD_CmdKind_StepOut,
|
||||
RD_CmdKind_StepToExit,
|
||||
RD_CmdKind_Halt,
|
||||
RD_CmdKind_SoftHaltRefresh,
|
||||
RD_CmdKind_SetThreadIP,
|
||||
@@ -498,6 +500,7 @@ B32 all_windows;
|
||||
B32 non_graphical;
|
||||
B32 prefer_new_tab;
|
||||
B32 activate_with_single_click;
|
||||
B32 disable_addresses;
|
||||
Dir2 dir2;
|
||||
String8 string;
|
||||
String8 cmd_name;
|
||||
@@ -598,6 +601,7 @@ Z(getting_started)\
|
||||
.non_graphical = rd_regs()->non_graphical,\
|
||||
.prefer_new_tab = rd_regs()->prefer_new_tab,\
|
||||
.activate_with_single_click = rd_regs()->activate_with_single_click,\
|
||||
.disable_addresses = rd_regs()->disable_addresses,\
|
||||
.dir2 = rd_regs()->dir2,\
|
||||
.string = rd_regs()->string,\
|
||||
.cmd_name = rd_regs()->cmd_name,\
|
||||
@@ -606,10 +610,10 @@ Z(getting_started)\
|
||||
C_LINKAGE_BEGIN
|
||||
extern String8 rd_tab_fast_path_view_name_table[25];
|
||||
extern String8 rd_tab_fast_path_query_name_table[25];
|
||||
extern RD_VocabInfo rd_vocab_info_table[364];
|
||||
extern RD_VocabInfo rd_vocab_info_table[365];
|
||||
extern RD_NameSchemaInfo rd_name_schema_info_table[39];
|
||||
extern String8 rd_reg_slot_code_name_table[49];
|
||||
extern Rng1U64 rd_reg_slot_range_table[49];
|
||||
extern String8 rd_reg_slot_code_name_table[50];
|
||||
extern Rng1U64 rd_reg_slot_range_table[50];
|
||||
extern String8 rd_binding_version_remap_old_name_table[9];
|
||||
extern String8 rd_binding_version_remap_new_name_table[9];
|
||||
extern String8 rd_icon_kind_text_table[75];
|
||||
|
||||
@@ -891,6 +891,7 @@ RD_RegTable:
|
||||
{B32 non_graphical NonGraphical }
|
||||
{B32 prefer_new_tab PreferNewTab }
|
||||
{B32 activate_with_single_click ActivateWithSingleClick }
|
||||
{B32 disable_addresses DisableAddresses }
|
||||
{Dir2 dir2 Dir2 }
|
||||
{String8 string String }
|
||||
{String8 cmd_name CmdName }
|
||||
|
||||
+57
-10
@@ -10302,6 +10302,7 @@ rd_init(CmdLine *cmdln)
|
||||
rd_state->arena = arena;
|
||||
rd_state->quit_after_success = (cmd_line_has_flag(cmdln, str8_lit("quit_after_success")) ||
|
||||
cmd_line_has_flag(cmdln, str8_lit("q")));
|
||||
rd_state->override_focus_on_stop = (cmd_line_has_flag(cmdln, s("no_focus_on_stop")));
|
||||
rd_state->user_path_arena = arena_alloc();
|
||||
rd_state->project_path_arena = arena_alloc();
|
||||
rd_state->theme_path_arena = arena_alloc();
|
||||
@@ -12584,6 +12585,7 @@ rd_frame(void)
|
||||
{
|
||||
String8 msg = rd_regs()->string;
|
||||
String8List msg_parts = str8_split(scratch.arena, msg, (U8 *)" ", 1, 0);
|
||||
str8_list_push_front(scratch.arena, &msg_parts, s("ipc_command"));
|
||||
CmdLine msg_cmd_line = cmd_line_from_string_list(scratch.arena, msg_parts);
|
||||
String8 cmd_kind_name = str8_list_first(&msg_cmd_line.inputs);
|
||||
RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_kind_name);
|
||||
@@ -12609,8 +12611,8 @@ rd_frame(void)
|
||||
primary_args_string = str8_list_join(scratch.arena, &primary_args_strings, &(StringJoin){.sep = str8_lit(" ")});
|
||||
}
|
||||
rd_regs_fill_slot_from_string(cmd_kind_info->query.slot, cmd_kind_info->query.expr, primary_args_string);
|
||||
rd_regs()->disable_addresses = 1;
|
||||
rd_push_cmd(cmd_kind_name, rd_regs());
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, "ack:{cmd:%S}\n", cmd_kind_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -12622,15 +12624,32 @@ rd_frame(void)
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, "state:\n{\n");
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " running: %i\n", d_ctrl_targets_running());
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " run_gen: %I64u\n", d_run_gen());
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " ip: 0x%I64x\n", d_ctrl_last_stop_event().rip_vaddr);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " stop_count: %I64u\n", d_stop_count());
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " ip: 0x%I64x\n", d_ctrl_last_stop_event().rip_vaddr);
|
||||
{
|
||||
Access *access = access_open();
|
||||
D_Event evt = d_ctrl_last_stop_event();
|
||||
U64 vaddr = evt.rip_vaddr;
|
||||
D_Entity *thread = d_entity_from_handle(rd_base_regs()->thread);
|
||||
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
||||
D_Entity *module = d_module_from_process_vaddr(process, vaddr);
|
||||
U64 voff = d_voff_from_vaddr(module, vaddr);
|
||||
DI_Key dbgi_key = d_dbgi_key_from_module(module);
|
||||
RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0);
|
||||
RDI_Symbol *procedure = rdi_procedure_from_voff(rdi, voff);
|
||||
String8 name = fully_qualified_str8_from_rdi_symbol(scratch.arena, rdi, procedure);
|
||||
name = escaped_from_raw_str8(scratch.arena, name);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " ip_voff: 0x%I64x\n", voff);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " ip_voff_symbol: \"%S\"\n", name);
|
||||
access_close(access);
|
||||
}
|
||||
{
|
||||
D_Event evt = d_ctrl_last_stop_event();
|
||||
DR_FStrList explanation_fstrs = rd_stop_explanation_fstrs_from_ctrl_event(scratch.arena, &evt);
|
||||
String8 explanation_string = dr_string_from_fstrs(scratch.arena, &explanation_fstrs);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " stop_event:\n {\n");
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " arch: %S\n", string_from_arch(evt.arch));
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " vaddr_range_min: 0x%I64x\n", evt.vaddr_rng.min);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " vaddr_range_max: 0x%I64x\n", evt.vaddr_rng.max);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " vaddr_range: [0x%I64x, 0x%I64x)\n", evt.vaddr_rng.min, evt.vaddr_rng.max);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " ip_vaddr: 0x%I64x\n", evt.rip_vaddr);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " stack_base: 0x%I64x\n", evt.stack_base);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " tls_root: 0x%I64x\n", evt.tls_root);
|
||||
@@ -12643,6 +12662,25 @@ rd_frame(void)
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " explanation: \"%S\"\n", escaped_from_raw_str8(scratch.arena, explanation_string));
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " }\n");
|
||||
}
|
||||
{
|
||||
Access *access = access_open();
|
||||
D_Event evt = d_ctrl_last_stop_event();
|
||||
U64 vaddr = evt.rip_vaddr;
|
||||
D_Entity *thread = d_entity_from_handle(rd_base_regs()->thread);
|
||||
D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
||||
D_Entity *module = d_module_from_process_vaddr(process, vaddr);
|
||||
U64 voff = d_voff_from_vaddr(module, vaddr);
|
||||
DI_Key dbgi_key = d_dbgi_key_from_module(module);
|
||||
RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0);
|
||||
E_String2NumMap *locals_map = e_push_locals_map_from_rdi_voff(scratch.arena, rdi, voff);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " locals:\n {\n");
|
||||
for(E_String2NumMapNode *n = locals_map->first; n != 0; n = n->order_next)
|
||||
{
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " %S\n", n->string);
|
||||
}
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " }\n");
|
||||
access_close(access);
|
||||
}
|
||||
{
|
||||
D_Event evt = d_ctrl_last_stop_event();
|
||||
U64 vaddr = evt.rip_vaddr;
|
||||
@@ -12656,12 +12694,12 @@ rd_frame(void)
|
||||
for EachNode(n, D_LineNode, lines.first)
|
||||
{
|
||||
D_Line line = n->v;
|
||||
String8 line_file_path_relative = path_relative_dst_from_absolute_dst_src(scratch.arena, line.file_path, module->string);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " {\n");
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " file_path: \"%S\"\n", line.file_path);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " file_path: \"%S\"\n", line_file_path_relative);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " line_num: %I64d\n", line.pt.line);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " column_num: %I64d\n", line.pt.column);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " voff_range_min: 0x%I64x\n", line.voff_range.min);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " voff_range_max: 0x%I64x\n", line.voff_range.max);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " voff_range: [0x%I64x, 0x%I64x)\n", line.voff_range.min, line.voff_range.max);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " }\n");
|
||||
}
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " }\n");
|
||||
@@ -12688,8 +12726,7 @@ rd_frame(void)
|
||||
D_Entity *module = modules.v[idx];
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " {\n");
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " name: \"%S\"\n", escaped_from_raw_str8(scratch.arena, module->string));
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " vaddr_range_min: 0x%I64x\n", module->vaddr_range.min);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " vaddr_range_max: 0x%I64x\n", module->vaddr_range.max);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " vaddr_range: [0x%I64x, 0x%I64x)\n", module->vaddr_range.min, module->vaddr_range.max);
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " }\n");
|
||||
}
|
||||
str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " }\n");
|
||||
@@ -12698,6 +12735,12 @@ rd_frame(void)
|
||||
}break;
|
||||
case RD_CmdKind_Eval:
|
||||
{
|
||||
// TODO(rjf): to use this for evaluation testing, we need some way to temporarily
|
||||
// call the eval system with ctrl-thread-like evaluation rules (e.g. waiting for
|
||||
// memory, never accepting stale results, not looking into caches, etc.). currently
|
||||
// we'd only be able to do that by setting up an entirely new evaluation context,
|
||||
// which is currently a ton of code & laborious & duplicative, so we need to tighten
|
||||
// that up first. @eval_regressions
|
||||
String8 expr = rd_regs()->expr;
|
||||
E_Eval eval = e_eval_from_string(expr);
|
||||
E_Eval type_eval = e_eval_from_stringf("typeof(%S)", expr);
|
||||
@@ -12706,6 +12749,10 @@ rd_frame(void)
|
||||
.flags = EV_StringFlag_ReadOnlyDisplayRules | rd_state->eval_viz_base_string_flags,
|
||||
.radix = 10,
|
||||
};
|
||||
if(rd_regs()->disable_addresses)
|
||||
{
|
||||
string_params.flags |= EV_StringFlag_DisableAddresses;
|
||||
}
|
||||
String8 value_string = ev_value_string_from_eval(scratch.arena, &string_params, eval, 512);
|
||||
String8 type_value_string = ev_value_string_from_eval(scratch.arena, &string_params, type_eval, 512);
|
||||
String8List msgs_strings = {0};
|
||||
@@ -16903,7 +16950,7 @@ rd_frame(void)
|
||||
}
|
||||
|
||||
// rjf: focus window if none focused, and if we have a thread to snap to
|
||||
if(need_refocus && (selected_thread != &d_entity_nil || thread != &d_entity_nil))
|
||||
if(!rd_state->override_focus_on_stop && need_refocus && (selected_thread != &d_entity_nil || thread != &d_entity_nil))
|
||||
{
|
||||
B32 any_window_is_focused = 0;
|
||||
for(RD_WindowState *ws = rd_state->first_window_state; ws != &rd_nil_window_state; ws = ws->order_next)
|
||||
|
||||
@@ -388,6 +388,7 @@ struct RD_State
|
||||
Arena *arena;
|
||||
B32 quit;
|
||||
B32 quit_after_success;
|
||||
B32 override_focus_on_stop;
|
||||
S32 frame_depth;
|
||||
U64 frame_eval_memread_endt_us;
|
||||
|
||||
@@ -444,7 +445,7 @@ struct RD_State
|
||||
Access *frame_access;
|
||||
String8 last_window_title;
|
||||
|
||||
// rjf: evaluation cache
|
||||
// rjf: evaluation caches
|
||||
E_Cache *eval_cache;
|
||||
|
||||
// rjf: ambiguous path table (constructed from-scratch each frame)
|
||||
|
||||
@@ -426,7 +426,7 @@ struct IPCInfo
|
||||
//~ rjf: Globals
|
||||
|
||||
//- rjf: IPC resources
|
||||
#define IPC_SHARED_MEMORY_BUFFER_SIZE MB(4)
|
||||
#define IPC_SHARED_MEMORY_BUFFER_SIZE KB(64)
|
||||
StaticAssert(IPC_SHARED_MEMORY_BUFFER_SIZE > sizeof(IPCInfo), ipc_buffer_size_requirement);
|
||||
global Semaphore ipc_sender2main_signal_semaphore = {0};
|
||||
global Semaphore ipc_sender2main_lock_semaphore = {0};
|
||||
@@ -434,7 +434,7 @@ global U8 *ipc_sender2main_shared_memory_base = 0;
|
||||
global Semaphore ipc_main2sender_signal_semaphore = {0};
|
||||
global Semaphore ipc_main2sender_lock_semaphore = {0};
|
||||
global U8 *ipc_main2sender_shared_memory_base = 0;
|
||||
global U8 ipc_s2m_ring_buffer[MB(4)] = {0};
|
||||
global U8 ipc_s2m_ring_buffer[KB(64)] = {0};
|
||||
global U64 ipc_s2m_ring_write_pos = 0;
|
||||
global U64 ipc_s2m_ring_read_pos = 0;
|
||||
global Mutex ipc_s2m_ring_mutex = {0};
|
||||
@@ -666,6 +666,7 @@ entry_point(CmdLine *cmd_line)
|
||||
if(msg.size != 0)
|
||||
{
|
||||
log_infof("ipc_msg: \"%S\"", msg);
|
||||
String8List cmd_parts_of_msg = str8_split(scratch.arena, msg, (U8 *)";", 1, 0);
|
||||
RD_WindowState *dst_ws = rd_state->first_window_state;
|
||||
for(RD_WindowState *ws = dst_ws; ws != &rd_nil_window_state; ws = ws->order_next)
|
||||
{
|
||||
@@ -690,7 +691,10 @@ entry_point(CmdLine *cmd_line)
|
||||
rd_regs()->view = panel_tree.focused->selected_tab->id;
|
||||
scratch_end(scratch);
|
||||
}
|
||||
rd_cmd(RD_CmdKind_RunExternalDriverTextCommand, .string = msg);
|
||||
for EachNode(n, String8Node, cmd_parts_of_msg.first)
|
||||
{
|
||||
rd_cmd(RD_CmdKind_RunExternalDriverTextCommand, .string = n->string);
|
||||
}
|
||||
rd_request_frame();
|
||||
}
|
||||
}
|
||||
|
||||
+235
-40
@@ -1,6 +1,16 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Debugger Testing IPC Driving Helpers
|
||||
|
||||
internal String8
|
||||
rd_test__mule_main_path(Arena *arena)
|
||||
{
|
||||
String8 mule_main_exe_path = str8f(arena, "%S/%S%S", get_process_info()->binary_path, s("mule_main"), program_ext_postfix_from_os(OperatingSystem_CURRENT));
|
||||
return mule_main_exe_path;
|
||||
}
|
||||
|
||||
internal String8
|
||||
rd_test__raddbg_path(Arena *arena, CmdLine *cmdline)
|
||||
{
|
||||
@@ -14,9 +24,9 @@ rd_test__open_debugger(CmdLine *cmdline, String8 test_artifacts_path, String8 ta
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
String8 raddbg_path = rd_test__raddbg_path(scratch.arena, cmdline);
|
||||
String8 user_file_path = str8f(scratch.arena, "%S/test.raddbg_user", test_artifacts_path);\
|
||||
String8 user_file_path = str8f(scratch.arena, "%S/test.raddbg_user", test_artifacts_path);
|
||||
delete_file_at_path(user_file_path);
|
||||
Process process = launch_cmd_linef("%S --gen_crash_dump --user:test.raddbg_user --logs:logs %S", raddbg_path, target_cmd_line);
|
||||
Process process = launch_cmd_linef("%S --gen_crash_dump --no_focus_on_stop --user:%S --logs:logs %S", raddbg_path, user_file_path, target_cmd_line);
|
||||
scratch_end(scratch);
|
||||
return process;
|
||||
}
|
||||
@@ -41,64 +51,249 @@ rd_test__ipc_cmd(Arena *arena, CmdLine *cmdline, String8 test_artifacts_path, U6
|
||||
return response;
|
||||
}
|
||||
|
||||
Test(stepping)
|
||||
////////////////////////////////
|
||||
//~ rjf: Exemplar Test Helpers
|
||||
|
||||
internal void
|
||||
rd_test__exemplar_test_finish(Arena *arena, String8List test_log_strings, String8 test_exemplars_path, String8 test_artifacts_path, TestResult *result_out, String8List *test_out)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8 mule_main_exe_path = str8f(scratch.arena, "%S/%S%S", get_process_info()->binary_path, s("mule_main"), program_ext_postfix_from_os(OperatingSystem_CURRENT));
|
||||
struct
|
||||
|
||||
// rjf: combine all current test log output; write to 'current' data
|
||||
String8 test_log_current = str8_list_join(scratch.arena, &test_log_strings, 0);
|
||||
String8 test_log_current_path = str8f(scratch.arena, "%S/current", test_artifacts_path);
|
||||
write_data_to_file_path(test_log_current_path, test_log_current);
|
||||
|
||||
// rjf: load test log exemplar
|
||||
make_directory(test_exemplars_path);
|
||||
String8 exemplar_path = str8f(scratch.arena, "%S/exemplar", test_exemplars_path);
|
||||
String8 exemplar_data = data_from_file_path(scratch.arena, exemplar_path);
|
||||
|
||||
// rjf: if exemplar data is empty -> just save our output as the new exemplar
|
||||
if(exemplar_data.size == 0)
|
||||
{
|
||||
String8 cmdline;
|
||||
String8 start_symbol;
|
||||
B32 step_over_on_even;
|
||||
copy_file_path(exemplar_path, test_log_current_path);
|
||||
}
|
||||
test_cases[] =
|
||||
|
||||
// rjf: if we have exemplar data, then we need to check that it matches
|
||||
if(exemplar_data.size != 0)
|
||||
{
|
||||
{ mule_main_exe_path, s("mule_main"), 0 },
|
||||
{ mule_main_exe_path, s("mule_main"), 1 },
|
||||
{ mule_main_exe_path, s("control_flow_stepping_tests"), 0 },
|
||||
{ mule_main_exe_path, s("control_flow_stepping_tests"), 1 },
|
||||
};
|
||||
for EachElement(test_case_idx, test_cases)
|
||||
{
|
||||
String8 test_cmdline = test_cases[test_case_idx].cmdline;
|
||||
String8 start_symbol = test_cases[test_case_idx].start_symbol;
|
||||
B32 step_over_on_even = test_cases[test_case_idx].step_over_on_even;
|
||||
Process debugger = rd_test__open_debugger(cmdline, test_artifacts_path, test_cmdline);
|
||||
U64 debugger_pid = pid_from_process(debugger);
|
||||
String8 next_step_cmd = {0};
|
||||
rd_test__ipc_cmd(scratch.arena, cmdline, test_artifacts_path, debugger_pid, str8f(scratch.arena, "run_to_name %S", start_symbol));
|
||||
for(U64 cmd_idx = 0;; cmd_idx += 1)
|
||||
B32 current_matches_exemplar = str8_match(test_log_current, exemplar_data, 0);
|
||||
if(!current_matches_exemplar)
|
||||
{
|
||||
String8 step_cmd = s("step_into");
|
||||
if((cmd_idx % 2 == 0 && step_over_on_even) || (cmd_idx % 2 == 1 && !step_over_on_even))
|
||||
String8 diff_cmd = str8f(scratch.arena, "diff %S %S",
|
||||
path_normalized_from_string(scratch.arena, exemplar_path),
|
||||
path_normalized_from_string(scratch.arena, test_log_current_path));
|
||||
test_outf("Current log does not match exemplar; run `%S`\n", diff_cmd);
|
||||
}
|
||||
TestCheck(current_matches_exemplar);
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Test Helpers
|
||||
|
||||
internal void
|
||||
rd_test__stepping_regressions(Arena *arena, CmdLine *cmdline, String8 test_exemplars_path, String8 test_artifacts_path, TestResult *result_out, String8List *test_out, String8 target_cmdline, String8 start_symbol, B32 step_over_on_even)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8List test_log_strings = {0};
|
||||
|
||||
// rjf: start debugger
|
||||
Process debugger = rd_test__open_debugger(cmdline, test_artifacts_path, target_cmdline);
|
||||
U64 debugger_pid = pid_from_process(debugger);
|
||||
|
||||
// rjf: step & gather info
|
||||
{
|
||||
U64 last_stop_count = max_U64;
|
||||
B32 ready_for_next_operation = 0;
|
||||
String8 next_step_cmd = {0};
|
||||
for(U64 cmd_idx = 0;;)
|
||||
{
|
||||
Temp scratch2 = scratch_begin(&scratch.arena, 1);
|
||||
|
||||
// rjf: need next operation -> do op
|
||||
if(ready_for_next_operation)
|
||||
{
|
||||
step_cmd = s("step_over");
|
||||
ready_for_next_operation = 0;
|
||||
String8 step_cmd = s("step_into");
|
||||
if(cmd_idx == 0)
|
||||
{
|
||||
step_cmd = str8f(scratch2.arena, "run_to_name %S", start_symbol);
|
||||
}
|
||||
else if((cmd_idx % 2 == 0 && step_over_on_even) || (cmd_idx % 2 == 1 && !step_over_on_even))
|
||||
{
|
||||
step_cmd = s("step_over");
|
||||
}
|
||||
if(next_step_cmd.size != 0)
|
||||
{
|
||||
step_cmd = next_step_cmd;
|
||||
MemoryZeroStruct(&next_step_cmd);
|
||||
}
|
||||
String8 step_response = rd_test__ipc_cmd(scratch2.arena, cmdline, test_artifacts_path, debugger_pid, step_cmd);
|
||||
(void)step_response;
|
||||
cmd_idx += 1;
|
||||
}
|
||||
if(next_step_cmd.size != 0)
|
||||
{
|
||||
step_cmd = next_step_cmd;
|
||||
MemoryZeroStruct(&next_step_cmd);
|
||||
}
|
||||
String8 step_response = rd_test__ipc_cmd(scratch.arena, cmdline, test_artifacts_path, debugger_pid, step_cmd);
|
||||
String8 state_response = rd_test__ipc_cmd(scratch.arena, cmdline, test_artifacts_path, debugger_pid, s("state"));
|
||||
MD_Node *state_response_tree = md_tree_from_string(scratch.arena, state_response);
|
||||
|
||||
// rjf: query state, parse
|
||||
String8 state_response = rd_test__ipc_cmd(scratch2.arena, cmdline, test_artifacts_path, debugger_pid, s("state"));
|
||||
MD_Node *state_response_tree = md_tree_from_string(scratch2.arena, state_response);
|
||||
MD_Node *state = md_child_from_string(state_response_tree, s("state"), 0);
|
||||
U64 ip_vaddr = 0;
|
||||
try_u64_from_str8_c_rules(md_child_from_string(state, s("ip"), 0)->first->string, &ip_vaddr);
|
||||
if(ip_vaddr != 0 && md_child_from_string(state, s("lines"), 0)->first == &md_nil_node)
|
||||
|
||||
// rjf: we are only ready for next step command when the stop count has changed
|
||||
{
|
||||
next_step_cmd = s("step_out");
|
||||
U64 stop_count = 0;
|
||||
try_u64_from_str8_c_rules(md_child_from_string(state, s("stop_count"), 0)->first->string, &stop_count);
|
||||
if(stop_count != last_stop_count)
|
||||
{
|
||||
ready_for_next_operation = 1;
|
||||
last_stop_count = stop_count;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: if we are ready for the next operation, then accumulate deterministic log info
|
||||
if(ready_for_next_operation)
|
||||
{
|
||||
MD_Node *lines = md_child_from_string(state, s("lines"), 0);
|
||||
MD_Node *ip_voff = md_child_from_string(state, s("ip_voff"), 0);
|
||||
MD_Node *ip_voff_symbol = md_child_from_string(state, s("ip_voff_symbol"), 0);
|
||||
String8 lines_dump = md_string_from_tree(scratch.arena, lines);
|
||||
String8 ip_voff_dump = md_string_from_tree(scratch.arena, ip_voff);
|
||||
String8 ip_voff_symbol_dump = md_string_from_tree(scratch.arena, ip_voff_symbol);
|
||||
str8_list_push(scratch.arena, &test_log_strings, lines_dump);
|
||||
str8_list_push(scratch.arena, &test_log_strings, ip_voff_dump);
|
||||
str8_list_push(scratch.arena, &test_log_strings, ip_voff_symbol_dump);
|
||||
}
|
||||
|
||||
// rjf: are we without line info? -> step out
|
||||
if(ready_for_next_operation)
|
||||
{
|
||||
U64 ip_vaddr = 0;
|
||||
try_u64_from_str8_c_rules(md_child_from_string(state, s("ip"), 0)->first->string, &ip_vaddr);
|
||||
if(ip_vaddr != 0 && md_child_from_string(state, s("lines"), 0)->first == &md_nil_node)
|
||||
{
|
||||
next_step_cmd = s("step_out");
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch2);
|
||||
if(cmd_idx >= 100)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
rd_test__close_debugger(debugger);
|
||||
}
|
||||
|
||||
// rjf: end exemplar test
|
||||
rd_test__exemplar_test_finish(arena, test_log_strings, test_exemplars_path, test_artifacts_path, result_out, test_out);
|
||||
|
||||
// rjf: close debugger
|
||||
rd_test__close_debugger(debugger);
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
internal void
|
||||
rd_test__eval_regressions(Arena *arena, CmdLine *cmdline, String8 test_exemplars_path, String8 test_artifacts_path, TestResult *result_out, String8List *test_out, String8 target_cmdline, String8 target_line)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8List test_log_strings = {0};
|
||||
|
||||
// rjf: start debugger
|
||||
Process debugger = rd_test__open_debugger(cmdline, test_artifacts_path, target_cmdline);
|
||||
U64 debugger_pid = pid_from_process(debugger);
|
||||
|
||||
// rjf: query state
|
||||
U64 initial_stop_count = 0;
|
||||
{
|
||||
String8 response = rd_test__ipc_cmd(scratch.arena, cmdline, test_artifacts_path, debugger_pid, s("state"));
|
||||
MD_Node *state = md_child_from_string(md_tree_from_string(scratch.arena, response), s("state"), 0);
|
||||
MD_Node *stop_count = md_child_from_string(state, s("stop_count"), 0);
|
||||
try_u64_from_str8_c_rules(stop_count->first->string, &initial_stop_count);
|
||||
}
|
||||
|
||||
// rjf: run to target line
|
||||
rd_test__ipc_cmd(scratch.arena, cmdline, test_artifacts_path, debugger_pid, str8f(scratch.arena, "run_to_line %S", target_line));
|
||||
|
||||
// rjf: wait for stop, collect locals
|
||||
String8List locals = {0};
|
||||
for(;;)
|
||||
{
|
||||
Temp scratch2 = scratch_begin(&scratch.arena, 1);
|
||||
String8 response = rd_test__ipc_cmd(scratch.arena, cmdline, test_artifacts_path, debugger_pid, s("state"));
|
||||
MD_Node *state = md_child_from_string(md_tree_from_string(scratch.arena, response), s("state"), 0);
|
||||
MD_Node *stop_count = md_child_from_string(state, s("stop_count"), 0);
|
||||
U64 new_stop_count = 0;
|
||||
try_u64_from_str8_c_rules(stop_count->first->string, &new_stop_count);
|
||||
scratch_end(scratch2);
|
||||
if(new_stop_count != initial_stop_count)
|
||||
{
|
||||
MD_Node *locals_root = md_child_from_string(state, s("locals"), 0);
|
||||
for MD_EachNode(c, locals_root->first)
|
||||
{
|
||||
str8_list_push(scratch.arena, &locals, c->string);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: evaluate all locals
|
||||
String8List eval_cmd_strings = {0};
|
||||
for EachNode(n, String8Node, locals.first)
|
||||
{
|
||||
str8_list_pushf(scratch.arena, &eval_cmd_strings, "eval %S", n->string);
|
||||
}
|
||||
StringJoin join = {.sep = s(" ; ")};
|
||||
String8 eval_msg = str8_list_join(scratch.arena, &eval_cmd_strings, &join);
|
||||
String8 response = rd_test__ipc_cmd(scratch.arena, cmdline, test_artifacts_path, debugger_pid, eval_msg);
|
||||
MD_Node *response_tree = md_tree_from_string(scratch.arena, response);
|
||||
for MD_EachNode(n, response_tree->first)
|
||||
{
|
||||
if(str8_match(n->string, s("eval"), 0))
|
||||
{
|
||||
String8 eval_dump = md_string_from_tree(scratch.arena, n);
|
||||
str8_list_push(scratch.arena, &test_log_strings, eval_dump);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: end exemplar test
|
||||
rd_test__exemplar_test_finish(arena, test_log_strings, test_exemplars_path, test_artifacts_path, result_out, test_out);
|
||||
|
||||
// rjf: close debugger
|
||||
rd_test__close_debugger(debugger);
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Tests
|
||||
|
||||
#if 0
|
||||
Test(mule_main_step_regressions_0)
|
||||
{
|
||||
String8 exe_path = {0};
|
||||
rd_test__stepping_regressions(arena, cmdline, test_exemplars_path, test_artifacts_path, result_out, test_out, rd_test__mule_main_path(arena), s("mule_main"), 0);
|
||||
}
|
||||
|
||||
Test(mule_main_step_regressions_1)
|
||||
{
|
||||
rd_test__stepping_regressions(arena, cmdline, test_exemplars_path, test_artifacts_path, result_out, test_out, rd_test__mule_main_path(arena), s("mule_main"), 1);
|
||||
}
|
||||
|
||||
Test(control_flow_step_regressions)
|
||||
{
|
||||
rd_test__stepping_regressions(arena, cmdline, test_exemplars_path, test_artifacts_path, result_out, test_out, rd_test__mule_main_path(arena), s("mule_main"), 0);
|
||||
}
|
||||
|
||||
SkippedTest(type_coverage_eval_regressions)
|
||||
{
|
||||
// TODO(rjf): see @eval_regressions
|
||||
rd_test__eval_regressions(arena, cmdline, test_exemplars_path, test_artifacts_path, result_out, test_out, rd_test__mule_main_path(arena), s("C:/devel/raddebugger/src/mule/mule_main.cpp:723"));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
////////////////////////////////
|
||||
// IPC Controller
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
// command line
|
||||
global String8 g_stdout_file_name = str8_lit_comp("torture.out");
|
||||
global String8 g_wdir;
|
||||
global String8 g_exemplar_dir;
|
||||
global String8 g_out = str8_lit_comp("torture_artifacts");
|
||||
global B32 g_verbose;
|
||||
global B32 g_redirect_stdout = 1;
|
||||
@@ -168,7 +169,7 @@ t_run_caller(void *raw_ctx)
|
||||
if (ctx->test->skip) {
|
||||
ctx->result.status = TestStatus_Skip;
|
||||
} else {
|
||||
ctx->test->test_fn(scratch.arena, ctx->cmdline, g_wdir, &ctx->result, &test_out);
|
||||
ctx->test->test_fn(scratch.arena, ctx->cmdline, g_exemplar_dir, g_wdir, &ctx->result, &test_out);
|
||||
}
|
||||
|
||||
if (ctx->result.status == TestStatus_Fail || ctx->result.status == TestStatus_Crash) {
|
||||
@@ -1273,6 +1274,13 @@ t_entry_point(CmdLine *cmdline)
|
||||
fprintf(stdout, " %.*s ", (int)dots_count, dots);
|
||||
fflush(stdout);
|
||||
|
||||
// rjf: find exemplar data directory
|
||||
{
|
||||
String8 binary_dir_path = get_process_info()->binary_path;
|
||||
String8 root_dir_path = str8_chop_last_slash(binary_dir_path);
|
||||
g_exemplar_dir = str8f(scratch.arena, "%S/data/test_exemplars/%S", root_dir_path, test->label);
|
||||
}
|
||||
|
||||
// setup output directory
|
||||
g_wdir = str8f(scratch.arena, "%S/%S", g_out, test->label);
|
||||
g_wdir = full_path_from_path(scratch.arena, g_wdir);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#endif
|
||||
|
||||
internal DASM_Inst
|
||||
x64_dasm_inst_from_code(Arena *arena, U64 vaddr, String8 code, DASM_Syntax syntax)
|
||||
x64_dasm_inst_from_code(Arena *arena, U64 vaddr, String8 code, DASM_Syntax syntax)
|
||||
{
|
||||
DASM_Inst inst = {0};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user