mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
print out last captured output when a test fails or crashes
This commit is contained in:
committed by
Ryan Fleury
parent
a645622b10
commit
887ee21d94
+77
-77
@@ -10479,9 +10479,9 @@ rd_ipc_make_reply_stop_event(Arena *arena)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
rd_ipc_make_reply_eval(Arena *arena, String8 expr, E_Eval eval, U64 cap)
|
||||
{
|
||||
internal String8
|
||||
rd_ipc_make_reply_eval(Arena *arena, String8 expr, E_Eval eval, U64 cap)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
// gather value & type
|
||||
@@ -10510,62 +10510,62 @@ rd_ipc_make_reply_eval(Arena *arena, String8 expr, E_Eval eval, U64 cap)
|
||||
String8 result = str8_list_join(arena, &reply, 0);
|
||||
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
rd_ipc_make_reply_source_location_from_address(Arena *arena, U64 vaddr)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
D_Entity *process = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_base_regs()->process);
|
||||
if(process == &d_entity_nil)
|
||||
{
|
||||
D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_base_regs()->thread);
|
||||
process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
||||
}
|
||||
|
||||
D_Entity *module = &d_entity_nil;
|
||||
DI_Key dbgi_key = {0};
|
||||
U64 voff = 0;
|
||||
D_LineList lines = {0};
|
||||
if(process != &d_entity_nil)
|
||||
{
|
||||
module = d_module_from_process_vaddr(process, vaddr);
|
||||
if(module != &d_entity_nil)
|
||||
{
|
||||
dbgi_key = d_dbgi_key_from_module(module);
|
||||
voff = d_voff_from_vaddr(module, vaddr);
|
||||
lines = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, voff);
|
||||
}
|
||||
}
|
||||
D_Line line = {0};
|
||||
if(lines.first != 0)
|
||||
{
|
||||
line = lines.first->v;
|
||||
}
|
||||
|
||||
B32 is_ok = (process != &d_entity_nil && module != &d_entity_nil && lines.first != 0);
|
||||
|
||||
String8List reply = {0};
|
||||
rd_ipc_reply_block_begin(arena, &reply, "source_location_from_address");
|
||||
rd_ipc_reply_push_b32 (arena, &reply, "ok", is_ok);
|
||||
rd_ipc_reply_push_u64 (arena, &reply, "vaddr", vaddr);
|
||||
rd_ipc_reply_push_u64 (arena, &reply, "voff", voff);
|
||||
rd_ipc_reply_push_str8(arena, &reply, "file_path", line.file_path);
|
||||
rd_ipc_reply_push_u64 (arena, &reply, "line", line.pt.line);
|
||||
rd_ipc_reply_push_u64 (arena, &reply, "column", line.pt.column);
|
||||
rd_ipc_reply_push_u64 (arena, &reply, "voff_min", line.voff_range.min);
|
||||
rd_ipc_reply_push_u64 (arena, &reply, "voff_max", line.voff_range.max);
|
||||
rd_ipc_reply_block_end(arena, &reply);
|
||||
String8 result = str8_list_join(arena, &reply, 0);
|
||||
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Main Layer Top-Level Calls
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
rd_ipc_make_reply_source_location_from_address(Arena *arena, U64 vaddr)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
D_Entity *process = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_base_regs()->process);
|
||||
if(process == &d_entity_nil)
|
||||
{
|
||||
D_Entity *thread = d_entity_from_handle(&d_user_state->ctrl_entity_store->ctx, rd_base_regs()->thread);
|
||||
process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process);
|
||||
}
|
||||
|
||||
D_Entity *module = &d_entity_nil;
|
||||
DI_Key dbgi_key = {0};
|
||||
U64 voff = 0;
|
||||
D_LineList lines = {0};
|
||||
if(process != &d_entity_nil)
|
||||
{
|
||||
module = d_module_from_process_vaddr(process, vaddr);
|
||||
if(module != &d_entity_nil)
|
||||
{
|
||||
dbgi_key = d_dbgi_key_from_module(module);
|
||||
voff = d_voff_from_vaddr(module, vaddr);
|
||||
lines = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, voff);
|
||||
}
|
||||
}
|
||||
D_Line line = {0};
|
||||
if(lines.first != 0)
|
||||
{
|
||||
line = lines.first->v;
|
||||
}
|
||||
|
||||
B32 is_ok = (process != &d_entity_nil && module != &d_entity_nil && lines.first != 0);
|
||||
|
||||
String8List reply = {0};
|
||||
rd_ipc_reply_block_begin(arena, &reply, "source_location_from_address");
|
||||
rd_ipc_reply_push_b32 (arena, &reply, "ok", is_ok);
|
||||
rd_ipc_reply_push_u64 (arena, &reply, "vaddr", vaddr);
|
||||
rd_ipc_reply_push_u64 (arena, &reply, "voff", voff);
|
||||
rd_ipc_reply_push_str8(arena, &reply, "file_path", line.file_path);
|
||||
rd_ipc_reply_push_u64 (arena, &reply, "line", line.pt.line);
|
||||
rd_ipc_reply_push_u64 (arena, &reply, "column", line.pt.column);
|
||||
rd_ipc_reply_push_u64 (arena, &reply, "voff_min", line.voff_range.min);
|
||||
rd_ipc_reply_push_u64 (arena, &reply, "voff_max", line.voff_range.max);
|
||||
rd_ipc_reply_block_end(arena, &reply);
|
||||
String8 result = str8_list_join(arena, &reply, 0);
|
||||
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Main Layer Top-Level Calls
|
||||
|
||||
#if !defined(STBI_INCLUDE_STB_IMAGE_H)
|
||||
# define STB_IMAGE_IMPLEMENTATION
|
||||
@@ -12906,24 +12906,24 @@ rd_frame(void)
|
||||
rd_cmd(RD_CmdKind_StepIntoLine);
|
||||
str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_ack(rd_state->cmd_output_arena, str8_lit("step_into_line"), 1));
|
||||
}
|
||||
else if(str8_match(cmd_kind_name, str8_lit("eval"), 0))
|
||||
{
|
||||
U64 cap_end = str8_find_needle(cmd_args, 0, str8_lit(" "), 0);
|
||||
String8 cap_str = str8_substr(cmd_args, r1u64(0, cap_end));
|
||||
U64 cap = 0;
|
||||
try_u64_from_str8_c_rules(cap_str, &cap);
|
||||
String8 expr = str8_skip(cmd_args, cap_str.size);
|
||||
str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_eval(rd_state->cmd_output_arena, expr, e_eval_from_string(expr), cap));
|
||||
}
|
||||
else if(str8_match(cmd_kind_name, str8_lit("source_location_from_address"), 0))
|
||||
{
|
||||
String8 vaddr_str = str8_skip_chop_whitespace(cmd_args);
|
||||
U64 vaddr = 0;
|
||||
try_u64_from_str8_c_rules(vaddr_str, &vaddr);
|
||||
str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_source_location_from_address(rd_state->cmd_output_arena, vaddr));
|
||||
}
|
||||
else if(cmd_kind_info != &rd_nil_cmd_kind_info) RD_RegsScope()
|
||||
{
|
||||
else if(str8_match(cmd_kind_name, str8_lit("eval"), 0))
|
||||
{
|
||||
U64 cap_end = str8_find_needle(cmd_args, 0, str8_lit(" "), 0);
|
||||
String8 cap_str = str8_substr(cmd_args, r1u64(0, cap_end));
|
||||
U64 cap = 0;
|
||||
try_u64_from_str8_c_rules(cap_str, &cap);
|
||||
String8 expr = str8_skip(cmd_args, cap_str.size);
|
||||
str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_eval(rd_state->cmd_output_arena, expr, e_eval_from_string(expr), cap));
|
||||
}
|
||||
else if(str8_match(cmd_kind_name, str8_lit("source_location_from_address"), 0))
|
||||
{
|
||||
String8 vaddr_str = str8_skip_chop_whitespace(cmd_args);
|
||||
U64 vaddr = 0;
|
||||
try_u64_from_str8_c_rules(vaddr_str, &vaddr);
|
||||
str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_source_location_from_address(rd_state->cmd_output_arena, vaddr));
|
||||
}
|
||||
else if(cmd_kind_info != &rd_nil_cmd_kind_info) RD_RegsScope()
|
||||
{
|
||||
for EachNonZeroEnumVal(RD_RegSlot, s)
|
||||
{
|
||||
String8 reg_slot_name = rd_reg_slot_code_name_table[s];
|
||||
|
||||
+110
-72
@@ -2,21 +2,23 @@
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
// command line
|
||||
global String8 g_stdout_file_name = str8_lit_comp("torture.out");
|
||||
global String8 g_wdir;
|
||||
global String8 g_out = str8_lit_comp("torture");
|
||||
global B32 g_verbose;
|
||||
global B32 g_redirect_stdout = 1;
|
||||
global B32 g_stop_on_first_fail_or_crash = 1;
|
||||
global String8 g_linker;
|
||||
global String8 g_test_data;
|
||||
global String8 g_stdout_file_name = str8_lit_comp("torture.out");
|
||||
global String8 g_wdir;
|
||||
global String8 g_out = str8_lit_comp("torture");
|
||||
global B32 g_verbose;
|
||||
global B32 g_redirect_stdout = 1;
|
||||
global B32 g_stop_on_first_fail_or_crash = 1;
|
||||
global String8 g_linker;
|
||||
global String8 g_test_data;
|
||||
|
||||
// tests
|
||||
U64 g_torture_test_count;
|
||||
T_Test g_torture_tests[0xffffff];
|
||||
|
||||
// invoke
|
||||
global int g_last_exit_code;
|
||||
global int g_last_exit_code;
|
||||
global Arena *g_output_arena;
|
||||
global String8 g_output;
|
||||
|
||||
internal String8
|
||||
t_test_name_from_idx(Arena *arena, U64 test_idx)
|
||||
@@ -180,6 +182,11 @@ t_run(T_Run run, String8 user_data)
|
||||
} else {
|
||||
t_run_caller(&ctx);
|
||||
}
|
||||
|
||||
if (ctx.result.status == T_RunStatus_Fail || ctx.result.status == T_RunStatus_Crash) {
|
||||
fprintf(stderr, "Last captured output:\n%.*s\n", str8_varg(g_output));
|
||||
}
|
||||
|
||||
return ctx.result;
|
||||
}
|
||||
|
||||
@@ -228,27 +235,27 @@ t_cl_version(void)
|
||||
|
||||
if ( ! version.size) {
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
String8 output = {0};
|
||||
t_invoke_(t_cl_path(), str8_zero(), max_U64, scratch.arena, &output);
|
||||
|
||||
t_invoke_cl("");
|
||||
AssertAlways(g_last_exit_code == 0);
|
||||
|
||||
String8 needle = str8_lit("Version");
|
||||
U64 version_lo = str8_find_needle(output, 0, needle, 0);
|
||||
U64 version_lo = str8_find_needle(g_output, 0, needle, 0);
|
||||
version_lo += needle.size + 1;
|
||||
AssertAlways(version_lo < output.size);
|
||||
|
||||
U64 version_hi = str8_find_needle(output, version_lo, str8_lit(" "), 0);
|
||||
AssertAlways(version_hi < output.size);
|
||||
|
||||
version = str8_substr(output, r1u64(version_lo, version_hi));
|
||||
AssertAlways(version_lo < g_output.size);
|
||||
|
||||
U64 version_hi = str8_find_needle(g_output, version_lo, str8_lit(" "), 0);
|
||||
AssertAlways(version_hi < g_output.size);
|
||||
|
||||
version = str8_substr(g_output, r1u64(version_lo, version_hi));
|
||||
AssertAlways(version.size > 0);
|
||||
|
||||
local_persist U8 buffer[4096];
|
||||
ArenaParams params = { .reserve_size = sizeof(buffer), .commit_size = sizeof(buffer), .optional_backing_buffer = buffer };
|
||||
Arena *arena = arena_alloc_(¶ms);
|
||||
version = str8_copy(arena, version);
|
||||
|
||||
|
||||
MemoryZeroStruct(&g_output);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
@@ -322,27 +329,27 @@ t_src_path(void)
|
||||
}
|
||||
|
||||
internal B32
|
||||
t_invoke_env(String8 exe_path, String8 cmdline, String8List env, U64 timeout, Arena *output_arena, String8 *output_out)
|
||||
t_invoke_env(String8 exe_path, String8 cmdline, String8List env, U64 timeout)
|
||||
{
|
||||
Temp scratch = scratch_begin(&output_arena,1);
|
||||
|
||||
Temp scratch = scratch_begin(&g_output_arena,1);
|
||||
|
||||
B32 is_ok = 0;
|
||||
|
||||
B32 capture_output = output_out || g_redirect_stdout;
|
||||
|
||||
|
||||
// clean up global state
|
||||
arena_pop_to(g_output_arena, 0);
|
||||
MemoryZeroStruct(&g_output);
|
||||
g_last_exit_code = -1;
|
||||
|
||||
|
||||
#if OS_WINDOWS
|
||||
File read_pipe_handle = {0}, write_pipe_handle = {0};
|
||||
if (capture_output) {
|
||||
HANDLE read_pipe, write_pipe;
|
||||
SECURITY_ATTRIBUTES at = { .nLength = sizeof(at), .bInheritHandle = 1 };
|
||||
if (!CreatePipe(&read_pipe, &write_pipe, &at, 0)) {
|
||||
AssertAlways(0 && "failed to create a pipe");
|
||||
}
|
||||
read_pipe_handle = (File){ .u64[0] = (U64)read_pipe };
|
||||
write_pipe_handle = (File){ .u64[0] = (U64)write_pipe };
|
||||
}
|
||||
|
||||
HANDLE read_pipe, write_pipe;
|
||||
SECURITY_ATTRIBUTES at = { .nLength = sizeof(at), .bInheritHandle = 1 };
|
||||
if (!CreatePipe(&read_pipe, &write_pipe, &at, 0)) { AssertAlways(0 && "failed to create a pipe"); }
|
||||
read_pipe_handle = (File){ .u64[0] = (U64)read_pipe };
|
||||
write_pipe_handle = (File){ .u64[0] = (U64)write_pipe };
|
||||
#else
|
||||
# error NotImplemented
|
||||
#endif
|
||||
// Build Launch Options
|
||||
ProcessLaunchParams launch_opts = {
|
||||
.path = g_wdir,
|
||||
@@ -362,54 +369,84 @@ t_invoke_env(String8 exe_path, String8 cmdline, String8List env, U64 timeout, Ar
|
||||
|
||||
// invoke exe
|
||||
Process process_handle = process_launch(&launch_opts);
|
||||
if (process_match(process_handle, process_zero())) { goto exit; }
|
||||
|
||||
// close handle so last to ReadFile does not block
|
||||
file_close(write_pipe_handle);
|
||||
|
||||
if ( ! process_match(process_handle, process_zero())) {
|
||||
if (capture_output) {
|
||||
// capture process output
|
||||
String8List output = {0};
|
||||
for (;;) {
|
||||
String8 string = file_read_cstring(scratch.arena, read_pipe_handle, 0);
|
||||
if (string.size == 0) { break; }
|
||||
str8_list_push(scratch.arena, &output, string);
|
||||
}
|
||||
file_close(read_pipe_handle);
|
||||
|
||||
if (output_out) {
|
||||
*output_out = str8_list_join(output_arena, &output, 0);
|
||||
}
|
||||
|
||||
// write to the output file
|
||||
if (g_redirect_stdout) {
|
||||
write_data_list_to_file_path(g_stdout_file_name, output);
|
||||
}
|
||||
}
|
||||
|
||||
U64 exit_code_u64 = 0;
|
||||
if (process_join(process_handle, timeout, &exit_code_u64)) {
|
||||
g_last_exit_code = (int)exit_code_u64;
|
||||
is_ok = 1;
|
||||
} else {
|
||||
process_kill(process_handle);
|
||||
}
|
||||
// capture process output
|
||||
String8List output = {0};
|
||||
for (;;) {
|
||||
String8 string = file_read_cstring(scratch.arena, read_pipe_handle, 0);
|
||||
if (string.size == 0) { break; }
|
||||
str8_list_push(scratch.arena, &output, string);
|
||||
}
|
||||
file_close(read_pipe_handle);
|
||||
|
||||
// update output global
|
||||
g_output = str8_list_join(g_output_arena, &output, 0);
|
||||
|
||||
// write to the output file
|
||||
if (g_redirect_stdout) {
|
||||
write_data_list_to_file_path(g_stdout_file_name, output);
|
||||
}
|
||||
|
||||
U64 exit_code_u64 = 0;
|
||||
if (process_join(process_handle, timeout, &exit_code_u64)) {
|
||||
g_last_exit_code = (int)exit_code_u64;
|
||||
is_ok = 1;
|
||||
} else {
|
||||
process_kill(process_handle);
|
||||
}
|
||||
|
||||
exit:;
|
||||
scratch_end(scratch);
|
||||
return is_ok;
|
||||
}
|
||||
|
||||
internal B32
|
||||
t_invoke_(String8 exe_path, String8 cmdline, U64 timeout, Arena *output_arena, String8 *output_out)
|
||||
t_invoke(String8 exe_path, String8 cmdline, U64 timeout)
|
||||
{
|
||||
return t_invoke_env(exe_path, cmdline, (String8List){0}, timeout, output_arena, output_out);
|
||||
return t_invoke_env(exe_path, cmdline, (String8List){0}, timeout);
|
||||
}
|
||||
|
||||
internal B32
|
||||
t_invoke(String8 exe_path, String8 cmdline, U64 timeout)
|
||||
t_invoke_cl(char *fmt, ...)
|
||||
{
|
||||
return t_invoke_(exe_path, cmdline, timeout, 0, 0);
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
String8 cmdl = push_str8fv(scratch.arena, fmt, args);
|
||||
va_end(args);
|
||||
B32 is_ok = t_invoke(t_cl_path(), cmdl, max_U64);
|
||||
scratch_end(scratch);
|
||||
return is_ok;
|
||||
}
|
||||
|
||||
internal B32
|
||||
t_invoke_linkerf(char *fmt, ...)
|
||||
{
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
String8 cmdl = push_str8fv(scratch.arena, fmt, args);
|
||||
va_end(args);
|
||||
B32 is_ok = t_invoke(t_radlink_path(), cmdl, max_U64);
|
||||
scratch_end(scratch);
|
||||
return is_ok;
|
||||
}
|
||||
|
||||
internal B32
|
||||
t_invoke_radbin(char *fmt, ...)
|
||||
{
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
String8 cmdl = push_str8fv(scratch.arena, fmt, args);
|
||||
va_end(args);
|
||||
B32 is_ok = t_invoke(t_radbin_path(), cmdl, max_U64);
|
||||
scratch_end(scratch);
|
||||
return is_ok;
|
||||
}
|
||||
|
||||
internal void
|
||||
@@ -422,10 +459,10 @@ t_kill_all(String8 pattern)
|
||||
while (dmn_process_iter_next(scratch.arena, &it, &info)) {
|
||||
if (str8_match_wildcard(info.name, pattern, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive)) {
|
||||
#if OS_WINDOWS
|
||||
if (!t_invoke_(str8_lit("taskkill"), str8f(scratch.arena, "/PID %u /F", info.pid), max_U64, 0, 0)) { fprintf(stderr, "ERROR: failed to invoke taskkill\n"); }
|
||||
if (!t_invoke(str8_lit("taskkill"), str8f(scratch.arena, "/PID %u /F", info.pid), max_U64)) { fprintf(stderr, "ERROR: failed to invoke taskkill\n"); }
|
||||
#elif OS_LINUX
|
||||
NotImplemented; // TODO: test
|
||||
if (!t_invoke_(str8_lit("kill"), str8f(scratch.arena, " -9 %u", info.pid), max_U64, 0, 0)) { fprintf(stderr, "ERROR: failed to invoke kill\n"); }
|
||||
if (!t_invoke(str8_lit("kill"), str8f(scratch.arena, " -9 %u", info.pid), max_U64)) { fprintf(stderr, "ERROR: failed to invoke kill\n"); }
|
||||
#else
|
||||
# error NotImplemented
|
||||
#endif
|
||||
@@ -703,7 +740,8 @@ t_entry_point(CmdLine *cmdline)
|
||||
g_verbose = cmd_line_has_flag(cmdline, str8_lit("verbose"));
|
||||
g_redirect_stdout = !cmd_line_has_flag(cmdline, str8_lit("print_stdout"));
|
||||
g_stop_on_first_fail_or_crash = !cmd_line_has_flag(cmdline, str8_lit("keep_going"));
|
||||
|
||||
g_output_arena = arena_alloc();
|
||||
|
||||
// default options when running under debugger
|
||||
#if OS_WINDOWS
|
||||
if (!cmd_line_has_flag(cmdline, str8_lit("print_stdout")) && IsDebuggerPresent()) {
|
||||
|
||||
@@ -90,7 +90,13 @@ internal String8 t_radlink_path(void);
|
||||
internal String8 t_cwd_path(void);
|
||||
internal String8 t_src_path(void);
|
||||
|
||||
internal B32 t_invoke_(String8 exe_path, String8 cmdline, U64 timeout, Arena *output_arena, String8 *output_out);
|
||||
internal B32 t_invoke(String8 exe, String8 cmdline, U64 timeout);
|
||||
#define t_invoke_cl(f, ...) t_invoke_(t_cl_path(), str8f(scratch.arena, f, ## __VA_ARGS__), max_U64, 0, 0)
|
||||
internal B32 t_invoke_cl(char *fmt, ...);
|
||||
internal B32 t_invoke_linkerf(char *fmt, ...);
|
||||
internal B32 t_invoke_radbin(char *fmt, ...);
|
||||
internal void t_kill_all(String8 pattern);
|
||||
|
||||
#define t_invoke_linker_timeout(c, t) T_Ok(t_invoke(g_linker, c, t))
|
||||
#define t_invoke_linker_timeoutf(t, f, ...) t_invoke_linker_timeout(push_str8f(arena, f, ##__VA_ARGS__), t)
|
||||
#define t_invoke_linker(c) t_invoke_linker_timeout(c, max_U64)
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ d2r_rdi_from_dwarf_writer(Arena *arena, DW_Writer *writer)
|
||||
B32 was_pdb_deleted = delete_file_at_path(t_make_file_path(scratch.arena, str8_lit("a.pdb")));
|
||||
Assert(was_pdb_deleted);
|
||||
|
||||
t_invoke_(t_radbin_path(), str8_lit("-rdi a.exe -out:a.rdi"), max_U64, 0, 0);
|
||||
t_invoke(t_radbin_path(), str8_lit("-rdi a.exe -out:a.rdi"), max_U64);
|
||||
Assert(g_last_exit_code == 0);
|
||||
|
||||
String8 raw_rdi = t_read_file(arena, str8_lit("a.rdi"));
|
||||
@@ -275,11 +275,9 @@ TEST(d2r_line_table)
|
||||
|
||||
for EachElement(i, test_table) {
|
||||
for EachIndex(k, test_table[i].line_size) {
|
||||
String8 cmd_line = str8f(arena, "-voff2line -voff:0x%llx a.rdi", test_table[i].voff + k);
|
||||
String8 output = {0};
|
||||
t_invoke_(t_radbin_path(), cmd_line, max_U64, arena, &output);
|
||||
t_invoke_radbin("-voff2line -voff:0x%llx a.rdi", test_table[i].voff + k);
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
T_MatchLinef(&output, "%S:%llu", test_table[i].file->path, test_table[i].ln);
|
||||
T_MatchLinef(&g_output, "%S:%llu", test_table[i].file->path, test_table[i].ln);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-10
@@ -33,10 +33,8 @@ t_dbg_send_cmd(String8 cmd, U64 timeout_us, Arena *reply_arena, RD_IpcReply *rep
|
||||
#endif
|
||||
|
||||
// send command
|
||||
String8 cmdline = str8f(scratch.arena, "--ipc --pid:%u %S", dbg_pid, cmd);
|
||||
Arena *output_arena = reply_arena ? reply_arena : scratch.arena;
|
||||
String8 output = {0};
|
||||
if (t_invoke_(t_raddbg_path(), cmdline, timeout_us, output_arena, &output) == 0) { goto exit; }
|
||||
String8 cmdline = str8f(scratch.arena, "--ipc --pid:%u %S", dbg_pid, cmd);
|
||||
if (t_invoke(t_raddbg_path(), cmdline, timeout_us) == 0) { goto exit; }
|
||||
|
||||
B32 has_reply = 1;
|
||||
|
||||
@@ -55,7 +53,9 @@ t_dbg_send_cmd(String8 cmd, U64 timeout_us, Arena *reply_arena, RD_IpcReply *rep
|
||||
|
||||
if (has_reply) {
|
||||
// parse reply
|
||||
RD_IpcReply reply = rd_ipc_mdesk_reply_from_string(output_arena, output);
|
||||
Arena *a = reply_arena ? reply_arena : scratch.arena;
|
||||
String8 reply_text = str8_copy(a, g_output);
|
||||
RD_IpcReply reply = rd_ipc_mdesk_reply_from_string(a, reply_text);
|
||||
if (rd_ipc_reply_is_ok(&reply) == 0) { goto exit; }
|
||||
if (md_node_is_nil(reply.msg)) { goto exit; }
|
||||
if (reply_arena && reply_out) { *reply_out = reply; }
|
||||
@@ -111,7 +111,7 @@ t_dbg_stop_event(Arena *arena, T_DbgStopEvent *out, U64 timeout_us)
|
||||
|
||||
// send status request
|
||||
RD_IpcReply reply = {0};
|
||||
if ( ! t_dbg_send_cmd(str8_lit("stop_event"), timeout_us, scratch.arena, &reply)) { goto exit; }
|
||||
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; }
|
||||
@@ -131,7 +131,7 @@ t_dbg_stop_event(Arena *arena, T_DbgStopEvent *out, U64 timeout_us)
|
||||
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 (out != 0) { *out = v; }
|
||||
if (arena && out != 0) { *out = v; }
|
||||
|
||||
exit:;
|
||||
return is_ok;
|
||||
@@ -223,7 +223,7 @@ t_dbg_send_cmd_and_wait_stop(String8 cmd, U64 timeout_us)
|
||||
} while (t > 0);
|
||||
|
||||
//--- Status ---------------------
|
||||
if (is_stopped) {
|
||||
if (0 && is_stopped) {
|
||||
T_DbgStatus status = {0};
|
||||
AssertAlways(t_dbg_status(&status, 0));
|
||||
|
||||
@@ -271,8 +271,9 @@ t_dbg_launch(String8 cmdline, U64 timeout_us)
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
B32 dbg_ready = 0;
|
||||
|
||||
String8 user_path = t_make_file_path(scratch.arena, str8_lit("test.raddbg_user"));
|
||||
cmdline = str8f(scratch.arena, "--user:\"%S\" %S", user_path, cmdline);
|
||||
String8 user_path = t_make_file_path(scratch.arena, str8_lit("test.raddbg_user"));
|
||||
String8 project_path = t_make_file_path(scratch.arena, str8_lit("test.raddbg_project"));
|
||||
cmdline = str8f(scratch.arena, "--user:\"%S\" --project:\"%S\" %S", user_path, project_path, cmdline);
|
||||
|
||||
// launch debugger
|
||||
OS_ProcessLaunchParams launch_opts = {
|
||||
@@ -585,6 +586,10 @@ t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us)
|
||||
case T_DbgScriptCmdKind_ClearBreakpoints: t_dbg_send_cmdf(0,0,0, "clear_breakpoints"); break;
|
||||
case T_DbgScriptCmdKind_Run: t_dbg_send_cmd(str8_lit("run"), timeout_us, 0, 0); break;
|
||||
case T_DbgScriptCmdKind_At: {
|
||||
T_DbgStatus status = {0};
|
||||
AssertAlways(t_dbg_status(&status, 0));
|
||||
AssertAlways(status.running == 0);
|
||||
|
||||
// map IP -> source location
|
||||
U64 ip = u64_from_str8(t_dbg_value_from_exprf(scratch.arena, "reg:rip"), 10);
|
||||
T_DbgSourceLocation loc = {0};
|
||||
|
||||
@@ -5011,14 +5011,15 @@ TEST(debug_p_sig_mismatch)
|
||||
T_Ok(t_write_file(str8_lit("b.obj"), b_obj));
|
||||
T_Ok(t_write_entry_obj());
|
||||
|
||||
String8 output = {0};
|
||||
t_invoke_(t_radlink_path(), str8_lit("/subsystem:console /entry:entry /out:a.exe /debug:full a.obj b.obj entry.obj"), max_U64, arena, &output);
|
||||
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /debug:full a.obj b.obj entry.obj");
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
|
||||
B32 found_error = 0;
|
||||
String8 a_obj_path = t_make_file_path(arena, str8_lit("a.obj"));
|
||||
String8 b_obj_path = t_make_file_path(arena, str8_lit("b.obj"));
|
||||
String8 expected_line = str8f(arena, "Error(%03d): %S: PCH signature mismatch, expected 0x%x got 0x%x; PCH obj %S", LNK_Error_PrecompSigMismatch, b_obj_path, b_sig, a_sig, a_obj_path);
|
||||
|
||||
String8 output = g_output;
|
||||
while (output.size) {
|
||||
String8 line = t_chop_line(&output);
|
||||
found_error = str8_match(line, expected_line, StringMatchFlag_CaseInsensitive);
|
||||
@@ -5124,10 +5125,10 @@ TEST(debug_p_and_debug_t_in_obj)
|
||||
}
|
||||
}));
|
||||
T_Ok(t_write_entry_obj());
|
||||
String8 output = {0};
|
||||
t_invoke_(t_radlink_path(), str8_lit("/subsystem:console /entry:entry /out:a.exe /debug:full pch.obj entry.obj"), max_U64, arena, &output);
|
||||
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /debug:full pch.obj entry.obj");
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
|
||||
String8 output = g_output;
|
||||
B32 found_warning = 0;
|
||||
String8 pch_obj_path = t_make_file_path(arena, str8_lit("pch.obj"));
|
||||
String8 expected_line = str8f(arena, "Warning(%03d): %S: multiple sections with debug types detected, obj must have either .debug$T or .debug$P; discarding both sections", LNK_Warning_MultipleDebugTAndDebugP, pch_obj_path);
|
||||
@@ -5531,12 +5532,11 @@ TEST(cyclic_type)
|
||||
T_Ok(t_write_entry_obj());
|
||||
T_Ok(t_write_file(str8_lit("cycle.obj"), raw_coff));
|
||||
|
||||
String8 cmd_line = str8f(arena, "/subsystem:console /entry:entry /out:a.exe /debug:full /rad_ignore:-%u cycle.obj entry.obj", LNK_Error_InvalidTypeIndex);
|
||||
String8 output = {0};
|
||||
t_invoke_(t_radlink_path(), cmd_line, max_U64, arena, &output);
|
||||
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /debug:full /rad_ignore:-%u cycle.obj entry.obj", LNK_Error_InvalidTypeIndex);
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
|
||||
B32 is_cycle_detected = 0;
|
||||
String8 output = g_output;
|
||||
B32 is_cycle_detected = 0;
|
||||
while (output.size && !is_cycle_detected) {
|
||||
is_cycle_detected = t_match_linef(&output,
|
||||
"Error(043): %S: LF_POINTER(type_index: 0x1000) forward refs member type index 0x1001 (leaf struct offset: 0x0)",
|
||||
@@ -6006,14 +6006,13 @@ TEST(ghash_check_corrupt)
|
||||
T_Ok(t_write_file(str8_lit("debug.obj"), debug_obj));
|
||||
T_Ok(t_write_entry_obj());
|
||||
|
||||
String8 output = {0};
|
||||
t_invoke_(t_radlink_path(), str8_lit("/subsystem:console /entry:entry /out:a.exe /debug:ghash entry.obj debug.obj"), max_U64, arena, &output);
|
||||
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /debug:ghash entry.obj debug.obj");
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
|
||||
B32 is_warning_found = 0;
|
||||
String8 debug_obj_path = t_make_file_path(arena, str8_lit("debug.obj"));
|
||||
String8 expected_line = str8f(arena, "Warning(%03u): %S: .debug$H section is too small to contain the header", LNK_Warning_GHash, debug_obj_path, LLVM_GHash_Magic);
|
||||
for (String8 i = output; i.size > 0 && !is_warning_found; ) {
|
||||
for (String8 i = g_output; i.size > 0 && !is_warning_found; ) {
|
||||
String8 line = t_chop_line(&i);
|
||||
is_warning_found = str8_match(expected_line, line, StringMatchFlag_CaseInsensitive);
|
||||
}
|
||||
@@ -6056,14 +6055,13 @@ TEST(ghash_check_magic)
|
||||
T_Ok(t_write_file(str8_lit("debug.obj"), debug_obj));
|
||||
T_Ok(t_write_entry_obj());
|
||||
|
||||
String8 output = {0};
|
||||
t_invoke_(t_radlink_path(), str8_lit("/subsystem:console /entry:entry /out:a.exe /debug:ghash entry.obj debug.obj"), max_U64, arena, &output);
|
||||
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /debug:ghash entry.obj debug.obj");
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
|
||||
B32 is_warning_found = 0;
|
||||
String8 debug_obj_path = t_make_file_path(arena, str8_lit("debug.obj"));
|
||||
String8 expected_line = str8f(arena, "Warning(%03u): %S: .debug$H contains invalid magic: got 0x7b, expected 0x%x", LNK_Warning_GHash, debug_obj_path, LLVM_GHash_Magic);
|
||||
for (String8 i = output; i.size > 0 && !is_warning_found; ) {
|
||||
for (String8 i = g_output; i.size > 0 && !is_warning_found; ) {
|
||||
String8 line = t_chop_line(&i);
|
||||
is_warning_found = str8_match(expected_line, line, StringMatchFlag_CaseInsensitive);
|
||||
}
|
||||
@@ -6106,14 +6104,13 @@ TEST(ghash_check_version)
|
||||
T_Ok(t_write_file(str8_lit("debug.obj"), debug_obj));
|
||||
T_Ok(t_write_entry_obj());
|
||||
|
||||
String8 output = {0};
|
||||
t_invoke_(t_radlink_path(), str8_lit("/subsystem:console /entry:entry /out:a.exe /debug:ghash entry.obj debug.obj"), max_U64, arena, &output);
|
||||
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /debug:ghash entry.obj debug.obj");
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
|
||||
B32 is_warning_found = 0;
|
||||
String8 debug_obj_path = t_make_file_path(arena, str8_lit("debug.obj"));
|
||||
String8 expected_line = str8f(arena, "Warning(%03u): %S: mismatched .debug$H version: got %u, expected %u", LNK_Warning_GHash, debug_obj_path, 0xbeef, LLVM_GHash_CurrentVersion);
|
||||
for (String8 i = output; i.size > 0 && !is_warning_found; ) {
|
||||
for (String8 i = g_output; i.size > 0 && !is_warning_found; ) {
|
||||
String8 line = t_chop_line(&i);
|
||||
is_warning_found = str8_match(expected_line, line, StringMatchFlag_CaseInsensitive);
|
||||
}
|
||||
@@ -6148,14 +6145,13 @@ TEST(ghash_check_hash_alg)
|
||||
T_Ok(t_write_file(str8_lit("debug.obj"), debug_obj));
|
||||
T_Ok(t_write_entry_obj());
|
||||
|
||||
String8 output = {0};
|
||||
t_invoke_(t_radlink_path(), str8_lit("/subsystem:console /entry:entry /out:a.exe /debug:ghash entry.obj debug.obj"), max_U64, arena, &output);
|
||||
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /debug:ghash entry.obj debug.obj");
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
|
||||
B32 is_warning_found = 0;
|
||||
String8 debug_obj_path = t_make_file_path(arena, str8_lit("debug.obj"));
|
||||
String8 expected_line = str8f(arena, "Warning(%03u): %S: mismatched .debug$H hash algorithm: got SHA1_8, expected BALK3", LNK_Warning_GHash, debug_obj_path);
|
||||
for (String8 i = output; i.size > 0 && !is_warning_found; ) {
|
||||
B32 is_warning_found = 0;
|
||||
String8 debug_obj_path = t_make_file_path(arena, str8_lit("debug.obj"));
|
||||
String8 expected_line = str8f(arena, "Warning(%03u): %S: mismatched .debug$H hash algorithm: got SHA1_8, expected BALK3", LNK_Warning_GHash, debug_obj_path);
|
||||
for (String8 i = g_output; i.size > 0 && !is_warning_found; ) {
|
||||
String8 line = t_chop_line(&i);
|
||||
is_warning_found = str8_match(expected_line, line, StringMatchFlag_CaseInsensitive);
|
||||
}
|
||||
@@ -6191,13 +6187,13 @@ TEST(ghash_match_debug_t)
|
||||
T_Ok(t_write_entry_obj());
|
||||
|
||||
String8 output = {0};
|
||||
t_invoke_(t_radlink_path(), str8_lit("/subsystem:console /entry:entry /out:a.exe /debug:ghash entry.obj debug.obj"), max_U64, arena, &output);
|
||||
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /debug:ghash entry.obj debug.obj");
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
|
||||
B32 is_warning_found = 0;
|
||||
String8 debug_obj_path = t_make_file_path(arena, str8_lit("debug.obj"));
|
||||
String8 expected_line = str8f(arena, "Warning(%03u): %S: mismatched .debug$H hash count and type count: got 3 hashes for 2 types", LNK_Warning_GHash, debug_obj_path);
|
||||
for (String8 i = output; i.size > 0 && !is_warning_found; ) {
|
||||
B32 is_warning_found = 0;
|
||||
String8 debug_obj_path = t_make_file_path(arena, str8_lit("debug.obj"));
|
||||
String8 expected_line = str8f(arena, "Warning(%03u): %S: mismatched .debug$H hash count and type count: got 3 hashes for 2 types", LNK_Warning_GHash, debug_obj_path);
|
||||
for (String8 i = g_output; i.size > 0 && !is_warning_found; ) {
|
||||
String8 line = t_chop_line(&i);
|
||||
is_warning_found = str8_match(expected_line, line, StringMatchFlag_CaseInsensitive);
|
||||
}
|
||||
@@ -6426,18 +6422,17 @@ t_radlink_validate_asan_out(String8 obj_name)
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
B32 is_ok = 0;
|
||||
|
||||
t_invoke_(t_radlink_path(), str8f(scratch.arena, "%S /debug:full", obj_name), max_U64, 0, 0);
|
||||
t_invoke_linkerf("%S /debug:full", obj_name);
|
||||
if (g_last_exit_code != 0) { goto exit; }
|
||||
|
||||
String8 exe_path = t_make_file_path(scratch.arena, str8f(scratch.arena, "%S.exe", str8_chop_last_dot(obj_name)));
|
||||
String8 out = {0};
|
||||
|
||||
char *old_path_cstr = getenv("PATH");
|
||||
String8List env = {0};
|
||||
str8_list_pushf(scratch.arena, &env, "PATH=%S;%S", str8_chop_last_slash(t_cl_path()), str8_cstring(old_path_cstr));
|
||||
t_invoke_env(exe_path, str8_zero(), env, max_U64, scratch.arena, &out);
|
||||
t_invoke_env(exe_path, str8_zero(), env, max_U64);
|
||||
|
||||
String8 s = out;
|
||||
String8 s = g_output;
|
||||
|
||||
String8 header = t_chop_line(&s);
|
||||
if ( ! str8_match(header, str8_lit("================================================================="), 0)) {
|
||||
@@ -6469,8 +6464,7 @@ TEST(infer_asan)
|
||||
// /MD
|
||||
{
|
||||
T_Ok(t_write_file(str8_lit("main.c"), str8_cstring(program)));
|
||||
String8 cl_output = {0};
|
||||
t_invoke_(t_cl_path(), str8_lit("/MD /fsanitize=address /Z7 /c /Fo:main_md.obj main.c"), max_U64, arena, &cl_output);
|
||||
t_invoke_cl("/MD /fsanitize=address /Z7 /c /Fo:main_md.obj main.c");
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
T_Ok(t_radlink_validate_asan_out(str8_lit("main_md.obj")));
|
||||
}
|
||||
@@ -6478,8 +6472,7 @@ TEST(infer_asan)
|
||||
// /MDd
|
||||
{
|
||||
T_Ok(t_write_file(str8_lit("main.c"), str8_cstring(program)));
|
||||
String8 cl_output = {0};
|
||||
t_invoke_(t_cl_path(), str8_lit("/MDd /fsanitize=address /Z7 /c /Fo:main_mdd.obj main.c"), max_U64, arena, &cl_output);
|
||||
t_invoke_cl("/MDd /fsanitize=address /Z7 /c /Fo:main_mdd.obj main.c");
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
T_Ok(t_radlink_validate_asan_out(str8_lit("main_mdd.obj")));
|
||||
}
|
||||
@@ -6487,8 +6480,7 @@ TEST(infer_asan)
|
||||
// /MT
|
||||
{
|
||||
T_Ok(t_write_file(str8_lit("main.c"), str8_cstring(program)));
|
||||
String8 cl_output = {0};
|
||||
t_invoke_(t_cl_path(), str8_lit("/MT /fsanitize=address /Z7 /c /Fo:main_mt.obj main.c"), max_U64, arena, &cl_output);
|
||||
t_invoke_cl("/MT /fsanitize=address /Z7 /c /Fo:main_mt.obj main.c");
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
T_Ok(t_radlink_validate_asan_out(str8_lit("main_mt.obj")));
|
||||
}
|
||||
@@ -6496,8 +6488,7 @@ TEST(infer_asan)
|
||||
// /MTd
|
||||
{
|
||||
T_Ok(t_write_file(str8_lit("main.c"), str8_cstring(program)));
|
||||
String8 cl_output = {0};
|
||||
t_invoke_(t_cl_path(), str8_lit("/MT /fsanitize=address /Z7 /c /Fo:main_mtd.obj main.c"), max_U64, arena, &cl_output);
|
||||
t_invoke_cl("/MT /fsanitize=address /Z7 /c /Fo:main_mtd.obj main.c");
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
T_Ok(t_radlink_validate_asan_out(str8_lit("main_mtd.obj")));
|
||||
}
|
||||
@@ -6509,9 +6500,7 @@ TEST(infer_asan)
|
||||
TEST(determ_test)
|
||||
{
|
||||
// compile the test target (torture)
|
||||
String8 cl_line = str8f(arena, "/fsanitize=address /c /Z7 /Fo:test.obj -I%S /Zc:preprocessor %S/torture/torture_main.c", t_src_path(), t_src_path());
|
||||
String8 cl_out = {0};
|
||||
t_invoke_(t_cl_path(), cl_line, max_U64, arena, &cl_out);
|
||||
t_invoke_cl("/fsanitize=address /c /Z7 /Fo:test.obj -I%S /Zc:preprocessor %S/torture/torture_main.c", t_src_path(), t_src_path());
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
|
||||
U64 run_count = 25;
|
||||
|
||||
@@ -22,11 +22,6 @@ typedef enum
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
#define t_invoke_linker_timeout(c, t) T_Ok(t_invoke(g_linker, c, t))
|
||||
#define t_invoke_linker_timeoutf(t, f, ...) t_invoke_linker_timeout(push_str8f(arena, f, ##__VA_ARGS__), t)
|
||||
#define t_invoke_linker(c) t_invoke_linker_timeout(c, max_U64)
|
||||
#define t_invoke_linkerf(f, ...) t_invoke_linker(push_str8f(arena, f, ##__VA_ARGS__))
|
||||
|
||||
internal T_Linker t_id_linker(void);
|
||||
|
||||
internal COFF_ObjSection * t_push_text_section(COFF_ObjWriter *obj_writer, String8 data);
|
||||
|
||||
Reference in New Issue
Block a user