print out last captured output when a test fails or crashes

This commit is contained in:
Nikita Smith
2026-06-02 12:09:48 -07:00
committed by Ryan Fleury
parent a645622b10
commit 887ee21d94
7 changed files with 245 additions and 214 deletions
+77 -77
View File
@@ -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
View File
@@ -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_(&params);
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()) {
+8 -2
View File
@@ -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)
+3 -5
View File
@@ -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
View File
@@ -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};
+32 -43
View File
@@ -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;
-5
View File
@@ -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);