update IPC parser

This commit is contained in:
Nikita Smith
2026-06-02 12:10:53 -07:00
committed by Ryan Fleury
parent c723584bfa
commit c875c912d2
3 changed files with 141 additions and 143 deletions
+4 -2
View File
@@ -12635,7 +12635,8 @@ rd_frame(void)
String8 explanation_string = dr_string_from_fstrs(scratch.arena, &explanation_fstrs); 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, " 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, " arch: %S\n", string_from_arch(evt.arch));
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, " 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, " ip_vaddr: 0x%I64x\n", evt.rip_vaddr); 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, " 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); str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " tls_root: 0x%I64x\n", evt.tls_root);
@@ -12670,7 +12671,8 @@ rd_frame(void)
D_Entity *module = modules.v[idx]; 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, " {\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, " 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: [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, " 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, " }\n"); 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"); str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " }\n");
+118 -123
View File
@@ -53,6 +53,7 @@ rd_ipc_parse_u32(MD_Node *node, String8 child_name, U32 *out)
return 0; return 0;
} }
#define rd_ipc_parse_int(n, c, ptr) rd_ipc_parse_int_(n, c, sizeof(*ptr), ptr)
internal B32 internal B32
rd_ipc_parse_int_(MD_Node *node, String8 child_name, U64 out_size, void *out) rd_ipc_parse_int_(MD_Node *node, String8 child_name, U64 out_size, void *out)
{ {
@@ -95,7 +96,7 @@ rd_ipc_parse_b32(MD_Node *node, String8 child_name, B32 *out)
internal U32 g_dbg_pid; internal U32 g_dbg_pid;
internal B32 internal B32
t_dbg_send_cmd(String8 cmd, U64 timeout_us, Arena *reply_arena, RD_IpcReply *reply_out) t_dbg_send_cmd(String8 cmd, U64 timeout_us, Arena *reply_arena, MD_ParseResult *reply_out)
{ {
Temp scratch = scratch_begin(&reply_arena, 1); Temp scratch = scratch_begin(&reply_arena, 1);
B32 is_sent = 0; B32 is_sent = 0;
@@ -122,16 +123,15 @@ t_dbg_send_cmd(String8 cmd, U64 timeout_us, Arena *reply_arena, RD_IpcReply *rep
if (has_reply) { if (has_reply) {
// parse reply // parse reply
Arena *a = reply_arena ? reply_arena : scratch.arena; Arena *a = reply_arena ? reply_arena : scratch.arena;
String8 reply_text = str8_copy(a, g_output); String8 reply_text = str8_copy(a, g_output);
RD_IpcReply reply = rd_ipc_mdesk_reply_from_string(a, reply_text);
t_infof("IPC-Reply: \"%S\"\n", reply_text);
//fprintf(stderr, "Reply: %.*s\n", str8_varg(reply_text)); MD_ParseResult reply = md_parse_from_text(a, str8_lit("ipc_reply"), reply_text);
// validate reply // validate reply
if (reply.parse.msgs.worst_message_kind >= MD_MsgKind_Error) { goto exit; } if (reply.msgs.worst_message_kind >= MD_MsgKind_Error) { goto exit; }
if (md_node_is_nil(reply.msg)) { goto exit; } if (md_node_is_nil(reply.root)) { goto exit; }
//if ( ! str8_matchi(reply.parse.root->first->string, cmd)) { Assert(0); goto exit; }
if (reply_arena && reply_out) { *reply_out = reply; } if (reply_arena && reply_out) { *reply_out = reply; }
} }
@@ -143,7 +143,7 @@ t_dbg_send_cmd(String8 cmd, U64 timeout_us, Arena *reply_arena, RD_IpcReply *rep
} }
internal B32 internal B32
t_dbg_send_cmdf(U64 timeout_us, Arena *reply_arena, RD_IpcReply *reply_out, char *fmt, ...) t_dbg_send_cmdf(U64 timeout_us, Arena *reply_arena, MD_ParseResult *reply_out, char *fmt, ...)
{ {
Temp scratch = scratch_begin(&reply_arena, 1); Temp scratch = scratch_begin(&reply_arena, 1);
va_list args; va_list args;
@@ -155,92 +155,73 @@ t_dbg_send_cmdf(U64 timeout_us, Arena *reply_arena, RD_IpcReply *reply_out, char
return is_ok; return is_ok;
} }
internal B32 internal T_DbgState *
t_dbg_status(T_DbgStatus *status_out, U64 timeout_us) t_dbg_state(Arena *arena, U64 timeout_us)
{ {
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(&arena, 1);
B32 is_ok = 0; T_DbgState *result = 0;
T_DbgStatus status = {0};
// send status request // send status request
RD_IpcReply reply = {0}; MD_ParseResult reply = {0};
if ( ! t_dbg_send_cmd(str8_lit("status"), timeout_us, scratch.arena, &reply)) { goto exit; } if ( ! t_dbg_send_cmd(str8_lit("state"), timeout_us, arena ? arena : scratch.arena, &reply)) { goto exit; }
// parse reply // parse reply
if ( ! rd_ipc_parse_b32(reply.msg, str8_lit("ok"), &is_ok)) { t_errorf("ERROR: failed to parse reply member: ok\n"); Assert(0); goto exit; } MD_Node *state_md = md_child_from_string(reply.root, str8_lit("state"), 0);
if ( ! rd_ipc_parse_b32(reply.msg, str8_lit("running"), &status.running)) { t_errorf("ERROR: failed to parse reply member: running\n"); Assert(0); goto exit; } MD_Node *stop_event_md = md_child_from_string(state_md, str8_lit("stop_event"), 0);
if ( ! rd_ipc_parse_int(reply.msg, str8_lit("run_gen"), &status.run_gen)) { t_errorf("ERROR: failed to parse reply member: run_gen\n"); Assert(0); goto exit; } MD_Node *threads_md = md_child_from_string(state_md, str8_lit("threads"), 0);
if ( ! rd_ipc_parse_int(reply.msg, str8_lit("ip"), &status.ip)) { t_errorf("ERROR: failed to parse reply member: ip\n"); Assert(0); goto exit; } MD_Node *modules_md = md_child_from_string(state_md, str8_lit("modules"), 0);
if (status_out != 0) { *status_out = status; } T_DbgState v = {0};
if (!rd_ipc_parse_int(state_md, str8_lit("running"), &v.running)) { Assert(0); goto exit; }
if (!rd_ipc_parse_int(state_md, str8_lit("run_gen"), &v.run_gen)) { Assert(0); goto exit; }
if (!rd_ipc_parse_int(state_md, str8_lit("ip"), &v.ip)) { Assert(0); goto exit; }
result = push_array(arena, T_DbgState, 1);
*result = v;
exit:; exit:;
if ( ! is_ok && reply.parse.root) { return result;
t_errorf("\tReply: %S\n", reply.parse.root->raw_string);
}
scratch_end(scratch);
return is_ok;
} }
internal B32 internal B32
t_dbg_stop_event(Arena *arena, T_DbgStopEvent *out, U64 timeout_us) t_dbg_src_line(Arena *arena, U64 vaddr, T_DbgLineArray *lines_out, U64 timeout_us)
{
Temp scratch = scratch_begin(0, 0);
T_DbgStopEvent v = {0};
B32 is_ok = 0;
// send status request
RD_IpcReply reply = {0};
if ( ! t_dbg_send_cmd(str8_lit("stop_event"), timeout_us, arena ? arena : scratch.arena, &reply)) { goto exit; }
// parse reply
if ( ! rd_ipc_parse_b32 (reply.msg, str8_lit("ok"), &is_ok)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("arch"), &v.arch)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("vaddr_min"), &v.vaddr_min)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("vaddr_max"), &v.vaddr_max)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("ip_vaddr"), &v.ip_vaddr)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("sp_base"), &v.sp_base)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("tls_root"), &v.tls_root)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("tls_index"), &v.tls_index)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("tls_offset"), &v.tls_offset)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("timestamp"), &v.timestamp)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("exception_code"), &v.exception_code)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("bp_flags"), &v.bp_flags)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_string (reply.msg, str8_lit("string"), &v.string)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("target_os"), &v.target_os)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("tls_model"), &v.tls_model)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_string (reply.msg, str8_lit("stop_cause"), &v.stop_cause)) { AssertAlways(0); goto exit; }
if (arena && out != 0) { *out = v; }
exit:;
return is_ok;
}
internal B32
t_dbg_src_line(Arena *arena, U64 vaddr, T_DbgSourceLocation *loc_out, U64 timeout_us)
{ {
Temp scratch = scratch_begin(&arena, 1); Temp scratch = scratch_begin(&arena, 1);
B32 is_ok = 0; B32 is_ok = 0;
RD_IpcReply reply = {0}; // send line map request
if(!t_dbg_send_cmdf(timeout_us, arena, &reply, "source_location_from_address 0x%llx", vaddr)) { goto exit; } MD_ParseResult reply = {0};
if(!t_dbg_send_cmdf(timeout_us, arena, &reply, "line_from_vaddr 0x%llx", vaddr)) { goto exit; }
T_DbgSourceLocation loc = {0};
// parse reply
if ( ! rd_ipc_parse_b32 (reply.msg, str8_lit("ok"), &is_ok)) { AssertAlways(0); goto exit; } MD_Node *lines_md = md_child_from_string(reply.root, str8_lit("lines"), 0);
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("vaddr"), &loc.vaddr)) { AssertAlways(0); goto exit; }
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("voff"), &loc.voff)) { AssertAlways(0); goto exit; } typedef struct Node { struct Node *next; T_DbgLine v; } Node;
if ( ! rd_ipc_parse_string(reply.msg, str8_lit("file_path"), &loc.file_path)) { AssertAlways(0); goto exit; } Node *first_line = 0, *last_line = 0;
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("line"), &loc.pt.line)) { AssertAlways(0); goto exit; } U64 line_count = 0;
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("column"), &loc.pt.column)) { AssertAlways(0); goto exit; } for MD_EachNode(n, lines_md->first) {
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("voff_min"), &loc.voff_range.min)){ AssertAlways(0); goto exit; } T_DbgLine line = {0};
if ( ! rd_ipc_parse_int (reply.msg, str8_lit("voff_max"), &loc.voff_range.max)){ AssertAlways(0); goto exit; } if ( ! rd_ipc_parse_string(lines_md, str8_lit("file_path"), &line.file_path)) { Assert(0); goto exit; }
if ( ! rd_ipc_parse_int(lines_md, str8_lit("line_num"), &line.line_num)) { Assert(0); goto exit; }
if (loc_out != 0) { *loc_out = loc; } if ( ! rd_ipc_parse_int(lines_md, str8_lit("column_num"), &line.column_num)) { Assert(0); goto exit; }
if ( ! rd_ipc_parse_int(lines_md, str8_lit("voff_range_min"), &line.voff_range.min)) { Assert(0); goto exit; }
if ( ! rd_ipc_parse_int(lines_md, str8_lit("voff_range_max"), &line.voff_range.max)) { Assert(0); goto exit; }
Node *n = push_array(scratch.arena, Node, 1);
n->v = line;
SLLQueuePush(first_line, last_line, n);
line_count += 1;
}
if (lines_out && line_count > 0) {
lines_out->count = 0;
lines_out->v = push_array(arena, T_DbgLine, line_count);
for EachNode(n, Node, first_line) {
lines_out->v[lines_out->count++] = n->v;
}
}
is_ok = 1;
exit:; exit:;
scratch_end(scratch); scratch_end(scratch);
return is_ok; return is_ok;
@@ -274,8 +255,8 @@ t_dbg_send_cmd_and_wait_stop(String8 cmd, U64 timeout_us)
B32 is_stopped = 0; B32 is_stopped = 0;
// snapshot status // snapshot status
T_DbgStatus status_before = {0}; T_DbgState *status_before = t_dbg_state(scratch.arena, max_U64);
if (t_dbg_status(&status_before, max_U64) == 0) { Assert(0 && "failed to snapshot status"); goto exit; } if (status_before == 0) { Assert(0 && "failed to snapshot status"); goto exit; }
// send command // send command
if (t_dbg_send_cmd(cmd, max_U64, 0, 0) == 0) { Assert(0 && "failed to the command"); goto exit; } if (t_dbg_send_cmd(cmd, max_U64, 0, 0) == 0) { Assert(0 && "failed to the command"); goto exit; }
@@ -284,11 +265,11 @@ t_dbg_send_cmd_and_wait_stop(String8 cmd, U64 timeout_us)
U64 t = ENDT_US(timeout_us); U64 t = ENDT_US(timeout_us);
for (;;) { for (;;) {
// query debugger status // query debugger status
T_DbgStatus status = {0}; T_DbgState *status = t_dbg_state(scratch.arena, t);
if (t_dbg_status(&status, t) == 0) { Assert(0 && "failed to acquire debugger status"); goto exit; } if (status == 0) { Assert(0 && "failed to acquire debugger status"); goto exit; }
// did state change? -> break // did state change? -> break
if (!status.running && status.run_gen != status_before.run_gen) { if (!status->running && status->run_gen != status_before->run_gen) {
is_stopped = 1; is_stopped = 1;
break; break;
} }
@@ -300,8 +281,7 @@ t_dbg_send_cmd_and_wait_stop(String8 cmd, U64 timeout_us)
//--- Status --------------------- //--- Status ---------------------
if (0 && is_stopped) { if (0 && is_stopped) {
T_DbgStatus status = {0}; T_DbgState *state = t_dbg_state(scratch.arena, T_Dbg_DefaultTimeout);
AssertAlways(t_dbg_status(&status, T_Dbg_DefaultTimeout));
String8 process_id = str8_skip(str8_chop(t_dbg_value_from_exprf(scratch.arena, "query:current_process.id"), 2), 2); String8 process_id = str8_skip(str8_chop(t_dbg_value_from_exprf(scratch.arena, "query:current_process.id"), 2), 2);
String8 process_label = str8_chop(str8_skip(t_dbg_value_from_exprf(scratch.arena, "query:current_process.label"), 2), 2); String8 process_label = str8_chop(str8_skip(t_dbg_value_from_exprf(scratch.arena, "query:current_process.label"), 2), 2);
@@ -312,22 +292,26 @@ t_dbg_send_cmd_and_wait_stop(String8 cmd, U64 timeout_us)
String8 ip = t_dbg_value_from_exprf(scratch.arena, "hex(reg:rip)"); String8 ip = t_dbg_value_from_exprf(scratch.arena, "hex(reg:rip)");
String8 sp = t_dbg_value_from_exprf(scratch.arena, "hex(reg:rsp)"); String8 sp = t_dbg_value_from_exprf(scratch.arena, "hex(reg:rsp)");
T_DbgStopEvent last_stop = {0}; T_DbgState *last_stop = t_dbg_state(scratch.arena, T_Dbg_DefaultTimeout);
AssertAlways(t_dbg_stop_event(scratch.arena, &last_stop, T_Dbg_DefaultTimeout)); AssertAlways(last_stop);
T_DbgSourceLocation loc = {0}; T_DbgLineArray lines = {0};
AssertAlways(t_dbg_src_line(scratch.arena, last_stop.ip_vaddr, &loc, T_Dbg_DefaultTimeout)); AssertAlways(t_dbg_src_line(scratch.arena, last_stop->ip_vaddr, &lines, T_Dbg_DefaultTimeout));
printf("------------------------------------------------------------------------------------------------------------------------\n"); t_infof("------------------------------------------------------------------------------------------------------------------------\n");
printf(" Process: %.*s [%.*s] (Active: %.*s)\n", str8_varg(process_id), str8_varg(process_label), str8_varg(process_active)); t_infof(" Process: %.*s [%.*s] (Active: %.*s)\n", str8_varg(process_id), str8_varg(process_label), str8_varg(process_active));
printf(" Thread: %.*s [%.*s] (Active: %.*s)\n", str8_varg(thread_id), str8_varg(thread_label), str8_varg(thread_active)); t_infof(" Thread: %.*s [%.*s] (Active: %.*s)\n", str8_varg(thread_id), str8_varg(thread_label), str8_varg(thread_active));
printf(" IP: %.*s\n", str8_varg(ip)); t_infof(" IP: %.*s\n", str8_varg(ip));
printf(" SP: %.*s\n", str8_varg(sp)); t_infof(" SP: %.*s\n", str8_varg(sp));
printf(" File Path: %.*s\n", str8_varg(loc.file_path)); t_infof(" Run Gen: %llu\n", (unsigned long long)state->run_gen);
printf(" Line: %lld\n", (long long)loc.pt.line); t_infof(" Stop Cause: \"%.*s\"\n", str8_varg(last_stop->stop_cause));
printf(" Column: %lld\n", (long long)loc.pt.column); for EachIndex(i, lines.count) {
printf(" Run Gen: %llu\n", (unsigned long long)status.run_gen); t_infof(" {\n");
printf(" Stop Cause: \"%.*s\"\n", str8_varg(last_stop.stop_cause)); t_infof(" File Path: %.*s\n", str8_varg(lines.v[i].file_path));
t_infof(" Line: %lld\n", (long long)lines.v[i].line_num);
t_infof(" Column: %lld\n", (long long)lines.v[i].column_num);
t_infof(" }\n");
}
fflush(stdout); fflush(stdout);
} }
//-------------------------------- //--------------------------------
@@ -337,7 +321,15 @@ t_dbg_send_cmd_and_wait_stop(String8 cmd, U64 timeout_us)
return is_stopped; return is_stopped;
} }
internal B32 t_dbg_ping (U64 timeout_us) { return t_dbg_status(0, timeout_us); } internal B32
t_dbg_ping(U64 timeout_us)
{
Temp scratch = scratch_begin(0,0);
T_DbgState *state = t_dbg_state(scratch.arena, timeout_us);
B32 did_reply = state != 0;
scratch_end(scratch);
return did_reply;
}
internal B32 t_dbg_bp_add_line(String8 file, U64 line) { return t_dbg_send_cmdf(0,0,0, "add_breakpoint \"%S\":%llu", file, line); } internal B32 t_dbg_bp_add_line(String8 file, U64 line) { return t_dbg_send_cmdf(0,0,0, "add_breakpoint \"%S\":%llu", file, line); }
internal B32 t_dbg_bp_add_func(String8 func_name) { return t_dbg_send_cmdf(0,0,0, "add_function_breakpoint %S", func_name); } internal B32 t_dbg_bp_add_func(String8 func_name) { return t_dbg_send_cmdf(0,0,0, "add_function_breakpoint %S", func_name); }
internal B32 t_dbg_bp_add_addr(U64 addr) { return t_dbg_send_cmdf(0,0,0, "add_address_breakpoint 0x%llx", addr); } internal B32 t_dbg_bp_add_addr(U64 addr) { return t_dbg_send_cmdf(0,0,0, "add_address_breakpoint 0x%llx", addr); }
@@ -396,15 +388,15 @@ t_dbg_eval(Arena *arena, String8 expr, T_Eval *eval_out)
{ {
Temp scratch = scratch_begin(&arena, 1); Temp scratch = scratch_begin(&arena, 1);
RD_IpcReply reply = {0}; MD_ParseResult reply = {0};
String8 cmd = str8f(scratch.arena, "eval %llu %S", /* value char cap: */ 10000, expr); String8 cmd = str8f(scratch.arena, "eval %llu %S", /* value char cap: */ 10000, expr);
B32 is_ok = t_dbg_send_cmd(cmd, T_Dbg_DefaultTimeout, arena, &reply); B32 is_ok = t_dbg_send_cmd(cmd, T_Dbg_DefaultTimeout, arena, &reply);
T_Eval e = {0}; T_Eval e = {0};
if ( ! rd_ipc_parse_string(reply.msg, str8_lit("expr"), &e.expr)) { t_errorf("ERROR: failed to parse reply member: expr\n"); Assert(0); goto exit; } if ( ! rd_ipc_parse_string(reply.root, str8_lit("expr"), &e.expr)) { t_errorf("ERROR: failed to parse reply member: expr\n"); Assert(0); goto exit; }
if ( ! rd_ipc_parse_string(reply.msg, str8_lit("value"), &e.value)) { t_errorf("ERROR: failed to parse reply member: value\n"); Assert(0); goto exit; } if ( ! rd_ipc_parse_string(reply.root, str8_lit("value"), &e.value)) { t_errorf("ERROR: failed to parse reply member: value\n"); Assert(0); goto exit; }
if ( ! rd_ipc_parse_string(reply.msg, str8_lit("type"), &e.type)) { t_errorf("ERROR: failed to parse reply member: type\n"); Assert(0); goto exit; } if ( ! rd_ipc_parse_string(reply.root, str8_lit("type"), &e.type)) { t_errorf("ERROR: failed to parse reply member: type\n"); Assert(0); goto exit; }
if ( ! rd_ipc_parse_string(reply.msg, str8_lit("error"), &e.error)) { t_errorf("ERROR: failed to parse reply member: error\n"); Assert(0); goto exit; } if ( ! rd_ipc_parse_string(reply.root, str8_lit("error"), &e.error)) { t_errorf("ERROR: failed to parse reply member: error\n"); Assert(0); goto exit; }
if (eval_out) { *eval_out = e; } if (eval_out) { *eval_out = e; }
exit:; exit:;
@@ -700,17 +692,17 @@ t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us)
goto exit; goto exit;
} }
#else #else
T_DbgStatus temp_status = {0}; T_DbgState *temp_status = t_dbg_state(scratch.arena, T_Dbg_DefaultTimeout);
if ( ! t_dbg_status(&temp_status, T_Dbg_DefaultTimeout)) { if (temp_status == 0) {
t_errorf("ERROR: %S:%llu: failed to query IP\n", script->file_path, (unsigned long long)cmd->line); t_errorf("ERROR: %S:%llu: failed to query IP\n", script->file_path, (unsigned long long)cmd->line);
goto exit; goto exit;
} }
U64 ip = temp_status.ip; U64 ip = temp_status->ip;
#endif #endif
// map IP -> source location // map IP -> source location
T_DbgSourceLocation loc = {0}; T_DbgLineArray lines = {0};
if (t_dbg_src_line(scratch.arena, ip, &loc, T_Dbg_DefaultTimeout) == 0) { if (t_dbg_src_line(scratch.arena, ip, &lines, T_Dbg_DefaultTimeout) == 0) {
t_errorf("ERROR: %S:%llu: IP (0x%llx) does not map to a source line\n", script->file_path, (unsigned long long)cmd->line, (unsigned long long)ip); t_errorf("ERROR: %S:%llu: IP (0x%llx) does not map to a source line\n", script->file_path, (unsigned long long)cmd->line, (unsigned long long)ip);
goto exit; goto exit;
} }
@@ -721,14 +713,17 @@ t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us)
AssertAlways(at_line_u64 > 0); AssertAlways(at_line_u64 > 0);
// match expected vs current debugger locations // match expected vs current debugger locations
B32 mismatch = loc.pt.line != at_line_u64 ||
!str8_match(loc.file_path, program->file->path, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive); for EachIndex(i, lines.count) {
if (mismatch) { B32 mismatch = lines.v[i].line_num != at_line_u64 ||
t_errorf("ERROR: %S:%llu: location check did not pass:\n", script->file_path, (unsigned long long)cmd->line); !str8_match(lines.v[i].file_path, program->file->path, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive);
t_errorf(" Expected: %S:%llu\n", program->file->path, (unsigned long long)at_line_u64); if (mismatch) {
t_errorf(" Got : %S:%llu\n", loc.file_path, (unsigned long long)loc.pt.line); t_errorf("ERROR: %S:%llu: location check did not pass:\n", script->file_path, (unsigned long long)cmd->line);
t_errorf(" IP : 0x%llx\n", (unsigned long long)ip); t_errorf(" Expected: %S:%llu\n", program->file->path, (unsigned long long)at_line_u64);
goto exit; t_errorf(" Got : %S:%llu\n", lines.v[i].file_path, (unsigned long long)lines.v[i].line_num);
t_errorf(" IP : 0x%llx\n", (unsigned long long)ip);
goto exit;
}
} }
} break; } break;
case T_DbgScriptCmdKind_Eval: NotImplemented; break; case T_DbgScriptCmdKind_Eval: NotImplemented; break;
+19 -18
View File
@@ -116,22 +116,9 @@ typedef struct
typedef struct typedef struct
{ {
B32 running; B32 running;
U64 run_gen; U64 run_gen;
U64 ip; U64 ip;
} T_DbgStatus;
typedef struct
{
U64 vaddr;
U64 voff;
String8 file_path;
TxtPt pt;
Rng1U64 voff_range;
} T_DbgSourceLocation;
typedef struct
{
Arch arch; Arch arch;
U64 vaddr_min; U64 vaddr_min;
U64 vaddr_max; U64 vaddr_max;
@@ -147,7 +134,21 @@ typedef struct
OperatingSystem target_os; OperatingSystem target_os;
U64 tls_model; U64 tls_model;
String8 stop_cause; String8 stop_cause;
} T_DbgStopEvent; } T_DbgState;
typedef struct
{
String8 file_path;
U64 line_num;
U64 column_num;
Rng1U64 voff_range;
} T_DbgLine;
typedef struct
{
U64 count;
T_DbgLine *v;
} T_DbgLineArray;
typedef struct typedef struct
{ {
@@ -180,5 +181,5 @@ internal B32 t_dbg_step_into_line(U64 timeout_us);
internal B32 t_dbg_launch(String8 cmdline, U64 timeout_us); internal B32 t_dbg_launch(String8 cmdline, U64 timeout_us);
internal B32 t_dbg_eval(Arena *arena, String8 expr, T_Eval *eval_out); internal B32 t_dbg_eval(Arena *arena, String8 expr, T_Eval *eval_out);
// TODO: need a source location query in eval // TODO: need a source location query in eval
internal B32 t_dbg_src_line(Arena *arena, U64 vaddr, T_DbgSourceLocation *loc_out, U64 timeout_us); internal B32 t_dbg_src_line(Arena *arena, U64 vaddr, T_DbgLineArray *lines, U64 timeout_us);