mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-08 14:58:08 +00:00
rework file directive handling; remove T_Group; add SKIP to disable
tests that are not passing; change command line syntax for easier test run/skip/force; updated help; shortened --dbg_graphical -> --gui; add 'skip' directive to the dbg scripts
This commit is contained in:
committed by
Ryan Fleury
parent
a21a256333
commit
fe2778133f
@@ -8,9 +8,8 @@ on:
|
|||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.md'
|
- '**.md'
|
||||||
|
|
||||||
# TODO: fix skips
|
|
||||||
env:
|
env:
|
||||||
TORTURE_FLAGS: "--gen_crash_dump -s:d2r::d2r_line_table,d2r::d2r_checksums"
|
TORTURE_FLAGS: "* --gen_crash_dump"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-ubuntu-24-04:
|
build-ubuntu-24-04:
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ if "%TORTURE_ARGS:~0,3%" == "-- " set "TORTURE_ARGS=%TORTURE_ARGS:~3%" && goto p
|
|||||||
set "TORTURE_ARGS=%TORTURE_ARGS:* -- =%"
|
set "TORTURE_ARGS=%TORTURE_ARGS:* -- =%"
|
||||||
|
|
||||||
:parse_done
|
:parse_done
|
||||||
|
if not defined TORTURE_ARGS set "TORTURE_ARGS=*
|
||||||
|
|
||||||
for %%m in (%MODE_VALUES%) do for %%c in (%CC_VALUES%) do (
|
for %%m in (%MODE_VALUES%) do for %%c in (%CC_VALUES%) do (
|
||||||
setlocal
|
setlocal
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ while [[ $# -gt 0 ]]; do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [[ "${#torture_args[@]}" == "0" ]]; then
|
||||||
|
torture_args=("*")
|
||||||
|
fi
|
||||||
|
|
||||||
for m in "${mode_values[@]}"; do
|
for m in "${mode_values[@]}"; do
|
||||||
for c in "${cc_values[@]}"; do
|
for c in "${cc_values[@]}"; do
|
||||||
# nuke artifacts from last run
|
# nuke artifacts from last run
|
||||||
|
|||||||
@@ -926,7 +926,9 @@ internal void * keys_from_hash_map_raw ( Arena *arena, HashMap *hm) { retur
|
|||||||
|
|
||||||
// values
|
// values
|
||||||
force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_value_u64) { MemoryCopy(buffer, &kv->value.value_u64, sizeof(kv->value.value_u64)); }
|
force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_value_u64) { MemoryCopy(buffer, &kv->value.value_u64, sizeof(kv->value.value_u64)); }
|
||||||
|
force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_value_raw) { MemoryCopy(buffer, &kv->value.value_raw, sizeof(kv->value.value_raw)); }
|
||||||
internal U64 * values_from_hash_map_u64(Arena *arena, HashMap *hm) { return hash_map_extract(arena, hm, 0, 0, hash_map_extract_value_u64, sizeof(U64)).values; }
|
internal U64 * values_from_hash_map_u64(Arena *arena, HashMap *hm) { return hash_map_extract(arena, hm, 0, 0, hash_map_extract_value_u64, sizeof(U64)).values; }
|
||||||
|
internal void * values_from_hash_map_raw(Arena *arena, HashMap *hm) {return hash_map_extract(arena, hm, 0, 0, hash_map_extract_value_raw, sizeof(void *)).values; }
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/// test: {
|
||||||
|
/// windows: {
|
||||||
|
/// skip: ""
|
||||||
|
/// compile: {
|
||||||
|
/// cc: "clang"
|
||||||
|
/// args: "-O0 -g -o main.exe %FILE%"
|
||||||
|
/// }
|
||||||
|
/// launch: "main.exe"
|
||||||
|
/// }
|
||||||
|
/// linux: {
|
||||||
|
/// skip: ""
|
||||||
|
/// compile: "-O0 -g -o main %FILE%"
|
||||||
|
/// launch: "./main"
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{ /// 1: { step_into step_into }
|
||||||
|
for (int i = 0; i < 1; /// 2: step_into
|
||||||
|
++i, ({ goto exit; })) { /// 4: step_into
|
||||||
|
int x = 0; /// 3: step_into
|
||||||
|
}
|
||||||
|
exit:;
|
||||||
|
} /// 5: at
|
||||||
|
|
||||||
@@ -1,20 +1,22 @@
|
|||||||
// TODO: step into alg needs to detect that it is about to step into a thunk and place breakpoint, respective to OS,
|
// TODO: step into alg needs to detect that it is about to step into a thunk and place breakpoint, respective to OS,
|
||||||
// where thunk calls into resolved function
|
// where thunk calls into resolved function
|
||||||
//
|
|
||||||
// test: {
|
/// test: {
|
||||||
// windows: {
|
/// windows: {
|
||||||
// compile: "/Od /Z7 /c main.c module.c"
|
/// skip: ""
|
||||||
// link: "/fixed /debug:full /dll module.obj"
|
/// compile: "/Od /Z7 /c main.c module.c"
|
||||||
// link: "/fixed /debug:full /entry:main kernel32.lib module.lib delayimp.lib main.obj /out:main.exe /delayload:module.dll /incremental:no"
|
/// link: "/fixed /debug:full /dll module.obj"
|
||||||
// launch: "main.exe"
|
/// link: "/fixed /debug:full /entry:main kernel32.lib module.lib delayimp.lib main.obj /out:main.exe /delayload:module.dll /incremental:no"
|
||||||
// }
|
/// launch: "main.exe"
|
||||||
// linux: {
|
/// }
|
||||||
// compile: "-O0 -g module.c -fPIC -shared -o libmodule.so"
|
/// linux: {
|
||||||
// compile: "-O0 -g main.c -L. -lmodule -o main -Wl,-rpath,%CWD%"
|
/// skip: ""
|
||||||
// launch: "./main"
|
/// compile: "-O0 -g module.c -fPIC -shared -o libmodule.so"
|
||||||
// }
|
/// compile: "-O0 -g main.c -L. -lmodule -o main -Wl,-rpath,%CWD%"
|
||||||
// }
|
/// launch: "./main"
|
||||||
//
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
|
||||||
/// file: "module.c"
|
/// file: "module.c"
|
||||||
|
|
||||||
|
|||||||
+180
-133
@@ -23,19 +23,54 @@ global String8 g_output;
|
|||||||
global String8 g_errors;
|
global String8 g_errors;
|
||||||
|
|
||||||
// tools
|
// tools
|
||||||
global B32 g_dbg_graphical;
|
global B32 g_gui;
|
||||||
global String8 g_radbin_path;
|
global String8 g_radbin_path;
|
||||||
global String8 g_cl_path;
|
global String8 g_cl_path;
|
||||||
global String8 g_clang_path;
|
global String8 g_clang_path;
|
||||||
global String8 g_gcc_path;
|
global String8 g_gcc_path;
|
||||||
global String8 g_linker_path;
|
global String8 g_linker_path;
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
internal String8
|
||||||
|
t_group_from_test(T_Test *test)
|
||||||
|
{
|
||||||
|
String8 file = str8_cstring(test->file);
|
||||||
|
String8 group = str8_chop_last_dot(str8_skip_last_slash(file));
|
||||||
|
if (str8_match_wildcard(group, str8_lit("torture_*"), StringMatchFlag_CaseInsensitive)) {
|
||||||
|
group = str8_skip(group, str8_lit("torture_").size);
|
||||||
|
}
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String8
|
||||||
|
t_group_from_test_idx(U64 test_idx)
|
||||||
|
{
|
||||||
|
return t_group_from_test(g_torture_tests[test_idx]);
|
||||||
|
}
|
||||||
|
|
||||||
internal String8
|
internal String8
|
||||||
t_test_name_from_idx(Arena *arena, U64 test_idx)
|
t_test_name_from_idx(Arena *arena, U64 test_idx)
|
||||||
{
|
{
|
||||||
return str8f(arena, "%s::%s", g_torture_tests[test_idx]->group, g_torture_tests[test_idx]->label);
|
return str8f(arena, "%.*s/%s", str8_varg(t_group_from_test_idx(test_idx)), g_torture_tests[test_idx]->label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal String8List
|
||||||
|
t_test_group_from_name(Arena *arena, String8 pattern)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
String8List matches = {0};
|
||||||
|
for EachIndex(i, g_torture_test_count) {
|
||||||
|
if (str8_match_wildcard(t_test_name_from_idx(scratch.arena, i), pattern, 0)) {
|
||||||
|
str8_list_push(arena, &matches, t_group_from_test_idx(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scratch_end(scratch);
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
internal char *
|
internal char *
|
||||||
t_string_from_result(T_RunStatus v)
|
t_string_from_result(T_RunStatus v)
|
||||||
{
|
{
|
||||||
@@ -43,10 +78,24 @@ t_string_from_result(T_RunStatus v)
|
|||||||
case T_RunStatus_Fail: return "FAIL";
|
case T_RunStatus_Fail: return "FAIL";
|
||||||
case T_RunStatus_Crash: return "CRASH";
|
case T_RunStatus_Crash: return "CRASH";
|
||||||
case T_RunStatus_Pass: return "PASS";
|
case T_RunStatus_Pass: return "PASS";
|
||||||
|
case T_RunStatus_Skip: return "SKIP";
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal char *
|
||||||
|
t_color_from_result(T_RunStatus v)
|
||||||
|
{
|
||||||
|
switch (v) {
|
||||||
|
#define X(n,c,...) case T_RunStatus_##n: return c;
|
||||||
|
T_Run_XList
|
||||||
|
#undef X
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
t_break_if_debugger_present(void)
|
t_break_if_debugger_present(void)
|
||||||
{
|
{
|
||||||
@@ -167,17 +216,22 @@ t_run_caller(void *raw_ctx)
|
|||||||
ctx->result.status = T_RunStatus_Pass;
|
ctx->result.status = T_RunStatus_Pass;
|
||||||
|
|
||||||
String8List test_out = {0};
|
String8List test_out = {0};
|
||||||
ctx->run(scratch.arena, ctx->user_data, &ctx->result, &test_out);
|
|
||||||
|
if (ctx->test->skip) {
|
||||||
|
ctx->result.status = T_RunStatus_Skip;
|
||||||
|
} else {
|
||||||
|
ctx->test->r(scratch.arena, ctx->user_data, &ctx->result, &test_out);
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->result.status == T_RunStatus_Fail || ctx->result.status == T_RunStatus_Crash) {
|
if (ctx->result.status == T_RunStatus_Fail || ctx->result.status == T_RunStatus_Crash) {
|
||||||
for EachNode(n, String8Node, test_out.first) {
|
for EachNode(n, String8Node, test_out.first) {
|
||||||
t_errorf("%S", n->string);
|
t_errorf("%S", n->string);
|
||||||
}
|
}
|
||||||
if (g_errors.size) {
|
if (g_errors.size) {
|
||||||
t_errorf("stderr: \"%S\"\n", g_errors);
|
t_errorf("%S\n", g_errors);
|
||||||
}
|
}
|
||||||
if (g_output.size) {
|
if (g_output.size) {
|
||||||
t_errorf("stdout: \"%S\"\n", g_output);
|
t_errorf("%S\n", g_output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,9 +239,9 @@ t_run_caller(void *raw_ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal T_RunResult
|
internal T_RunResult
|
||||||
t_run(T_Run run, String8 user_data)
|
t_run(T_Test *test, String8 user_data)
|
||||||
{
|
{
|
||||||
T_RunCtx ctx = { .run = run, .user_data = user_data, .result.status = T_RunStatus_Fail };
|
T_RunCtx ctx = { .test = test, .user_data = user_data, .result.status = T_RunStatus_Fail };
|
||||||
t_run_caller(&ctx);
|
t_run_caller(&ctx);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
@@ -332,7 +386,7 @@ t_raddbg_path(void)
|
|||||||
local_persist U8 buffer[4096];
|
local_persist U8 buffer[4096];
|
||||||
ArenaParams params = { .reserve_size = sizeof(buffer), .commit_size = sizeof(buffer), .optional_backing_buffer = buffer };
|
ArenaParams params = { .reserve_size = sizeof(buffer), .commit_size = sizeof(buffer), .optional_backing_buffer = buffer };
|
||||||
Arena *arena = arena_alloc_(¶ms);
|
Arena *arena = arena_alloc_(¶ms);
|
||||||
String8 raddbg_base_name = g_dbg_graphical ? str8_lit("raddbg") : str8_lit("raddbg_non_graphical");
|
String8 raddbg_base_name = g_gui ? str8_lit("raddbg") : str8_lit("raddbg_non_graphical");
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
Temp scratch = scratch_begin(0, 0);
|
Temp scratch = scratch_begin(0, 0);
|
||||||
path = full_path_from_path(arena, str8f(scratch.arena, "%S.exe", raddbg_base_name));
|
path = full_path_from_path(arena, str8f(scratch.arena, "%S.exe", raddbg_base_name));
|
||||||
@@ -779,7 +833,7 @@ t_invoke_env(String8 exe_path, String8 cmdline, String8List env, U64 timeout_us)
|
|||||||
exit:;
|
exit:;
|
||||||
for EachElement(i, read_capture_handles) { file_close(read_capture_handles[i]); }
|
for EachElement(i, read_capture_handles) { file_close(read_capture_handles[i]); }
|
||||||
for EachElement(i, write_capture_handles) { file_close(write_capture_handles[i]); }
|
for EachElement(i, write_capture_handles) { file_close(write_capture_handles[i]); }
|
||||||
AssertAlways(is_ok);
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
return is_ok;
|
return is_ok;
|
||||||
}
|
}
|
||||||
@@ -883,7 +937,9 @@ internal int
|
|||||||
t_test_compar(const void *raw_a, const void *raw_b)
|
t_test_compar(const void *raw_a, const void *raw_b)
|
||||||
{
|
{
|
||||||
const T_Test *a = raw_a, *b = raw_b;
|
const T_Test *a = raw_a, *b = raw_b;
|
||||||
int cmp = str8_compar(str8_cstring(a->group), str8_cstring(b->group), 0);
|
String8 group_a = t_group_from_test((T_Test *)a);
|
||||||
|
String8 group_b = t_group_from_test((T_Test *)b);
|
||||||
|
int cmp = str8_compar(group_a, group_b, 0);
|
||||||
if (cmp == 0) {
|
if (cmp == 0) {
|
||||||
cmp = u64_compar(&a->decl_line, &b->decl_line);
|
cmp = u64_compar(&a->decl_line, &b->decl_line);
|
||||||
}
|
}
|
||||||
@@ -1014,10 +1070,37 @@ t_errorf(char *fmt, ...)
|
|||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
t_help(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "--- Help -------------------------------------------------------\n");
|
||||||
|
fprintf(stderr, " %s\n\n", BUILD_TITLE_STRING_LITERAL);
|
||||||
|
fprintf(stderr, " Usage: torture [Options] <Input>\n\n");
|
||||||
|
fprintf(stderr, " Options:\n");
|
||||||
|
fprintf(stderr, " -list Print available test targets\n");
|
||||||
|
fprintf(stderr, " --gui Launch debugger with window\n");
|
||||||
|
fprintf(stderr, " -cl:<path> Override default cl path\n");
|
||||||
|
fprintf(stderr, " -clang:<path> Override default clang path\n");
|
||||||
|
fprintf(stderr, " -gcc:<path> Override default gcc path\n");
|
||||||
|
fprintf(stderr, " -linker:<path> Path to PE/COFF linker\n");
|
||||||
|
fprintf(stderr, " -print_stdout Print to console stdout and stderr of a run\n");
|
||||||
|
fprintf(stderr, " -out:<path> Directory path for test outputs (default \"%.*s\")\n", str8_varg(g_out));
|
||||||
|
fprintf(stderr, " -verbose Enable verbose mode\n");
|
||||||
|
fprintf(stderr, " -help Print help menu and exit\n");
|
||||||
|
fprintf(stderr, "\nInputs are wildcard expressions. Prefix with ! to skip matches, or + to force-run matches.\n");
|
||||||
|
fprintf(stderr, "\nExamples:\n");
|
||||||
|
fprintf(stderr, " torture * Run all tests\n");
|
||||||
|
fprintf(stderr, " torture bit_array Run 'bit_array' test\n");
|
||||||
|
fprintf(stderr, " torture !* Skip all tests\n");
|
||||||
|
fprintf(stderr, " torture * !bit_array Run all tests but skip 'bit_array'\n");
|
||||||
|
fprintf(stderr, " torture +* Force-run all tests\n");
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
t_entry_point(CmdLine *cmdline)
|
t_entry_point(CmdLine *cmdline)
|
||||||
{
|
{
|
||||||
Temp scratch = scratch_begin(0,0);
|
Temp scratch = scratch_begin(0,0);
|
||||||
|
U64 exit_code = max_U64;
|
||||||
|
|
||||||
U64 dashes_size = 9999;
|
U64 dashes_size = 9999;
|
||||||
U8 *dashes = push_array(scratch.arena, U8, dashes_size);
|
U8 *dashes = push_array(scratch.arena, U8, dashes_size);
|
||||||
@@ -1038,23 +1121,8 @@ t_entry_point(CmdLine *cmdline)
|
|||||||
B32 print_help = cmd_line_has_flag(cmdline, str8_lit("help")) ||
|
B32 print_help = cmd_line_has_flag(cmdline, str8_lit("help")) ||
|
||||||
cmd_line_has_flag(cmdline, str8_lit("h"));
|
cmd_line_has_flag(cmdline, str8_lit("h"));
|
||||||
if (print_help) {
|
if (print_help) {
|
||||||
PrintHeader("Help");
|
t_help();
|
||||||
fprintf(stderr, " %s\n\n", BUILD_TITLE_STRING_LITERAL);
|
goto exit;
|
||||||
fprintf(stderr, " Usage: torture [Options] [Files]\n\n");
|
|
||||||
fprintf(stderr, " Options:\n");
|
|
||||||
fprintf(stderr, " -target:{name[,name]} Selects targets to test\n");
|
|
||||||
fprintf(stderr, " -skip:{name[,name]} Selects targets to skip\n");
|
|
||||||
fprintf(stderr, " -list Print available test targets and exit\n");
|
|
||||||
fprintf(stderr, " -out:{path} Directory path for test outputs (default \"%.*s\")\n", str8_varg(g_out));
|
|
||||||
fprintf(stderr, " -verbose Enable verbose mode\n");
|
|
||||||
fprintf(stderr, " -cl:{path} Override default cl path\n");
|
|
||||||
fprintf(stderr, " -clang:{path} Override default clang path\n");
|
|
||||||
fprintf(stderr, " -gcc:{path} Override default gcc path\n");
|
|
||||||
fprintf(stderr, " -linker:{path} Path to PE/COFF linker\n");
|
|
||||||
fprintf(stderr, " --dbg_graphical Launch debugger with window\n");
|
|
||||||
fprintf(stderr, " -print_stdout Print to console stdout and stderr of a run\n");
|
|
||||||
fprintf(stderr, " -help Print help menu and exit\n");
|
|
||||||
abort_self(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1086,7 +1154,7 @@ t_entry_point(CmdLine *cmdline)
|
|||||||
//
|
//
|
||||||
// Compiler overrides
|
// Compiler overrides
|
||||||
//
|
//
|
||||||
g_dbg_graphical = cmd_line_has_flag(cmdline, str8_lit("dbg_graphical"));
|
g_gui = cmd_line_has_flag(cmdline, str8_lit("gui"));
|
||||||
g_cl_path = cmd_line_string(cmdline, str8_lit("cl"));
|
g_cl_path = cmd_line_string(cmdline, str8_lit("cl"));
|
||||||
g_clang_path = cmd_line_string(cmdline, str8_lit("clang"));
|
g_clang_path = cmd_line_string(cmdline, str8_lit("clang"));
|
||||||
g_gcc_path = cmd_line_string(cmdline, str8_lit("gcc"));
|
g_gcc_path = cmd_line_string(cmdline, str8_lit("gcc"));
|
||||||
@@ -1106,44 +1174,68 @@ t_entry_point(CmdLine *cmdline)
|
|||||||
//
|
//
|
||||||
// Handle optional -target
|
// Handle optional -target
|
||||||
//
|
//
|
||||||
String8List target = cmdline->inputs;
|
U64List targets = {0};
|
||||||
{
|
{
|
||||||
CmdLineOpt *target_opt = cmd_line_opt_from_string(cmdline, str8_lit("target"));
|
String8List inputs = {0};
|
||||||
if (target_opt == 0) {
|
|
||||||
target_opt = cmd_line_opt_from_string(cmdline, str8_lit("t"));
|
CmdLineOpt *target_opt = 0;
|
||||||
}
|
if (target_opt == 0) { target_opt = cmd_line_opt_from_string(cmdline, str8_lit("target")); }
|
||||||
|
if (target_opt == 0) { target_opt = cmd_line_opt_from_string(cmdline, str8_lit("t")); }
|
||||||
|
|
||||||
|
// handle explicit target switch
|
||||||
if (target_opt) {
|
if (target_opt) {
|
||||||
HashTable *ht = hash_table_init(scratch.arena, g_torture_test_count*2);
|
str8_list_concat_in_place(&inputs, &target_opt->value_strings);
|
||||||
|
}
|
||||||
|
|
||||||
String8List targets = target_opt->value_strings;
|
// accept inputs from the command line as target tests to run
|
||||||
str8_list_concat_in_place(&targets, &cmdline->inputs);
|
str8_list_concat_in_place(&inputs, &cmdline->inputs);
|
||||||
|
|
||||||
|
// no inputs -> print help and exit
|
||||||
|
if (inputs.node_count == 0) {
|
||||||
|
t_help();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMap hm = {0};
|
||||||
|
for EachNode(input_n, String8Node, inputs.first) {
|
||||||
|
String8 t = input_n->string;
|
||||||
|
|
||||||
|
// parse mode
|
||||||
|
typedef enum { Mode_Default, Mode_Skip, Mode_Force, } Mode;
|
||||||
|
Mode mode = Mode_Default;
|
||||||
|
if (str8_match_wildcard(t, str8_lit("+*"), 0)) { mode = Mode_Force; t = str8_skip(t, 1); }
|
||||||
|
else if (str8_match_wildcard(t, str8_lit("!*"), 0)) { mode = Mode_Skip; t = str8_skip(t, 1); }
|
||||||
|
|
||||||
|
if (str8_find_needle(t, 0, str8_lit("/"), 0) >= t.size) {
|
||||||
|
t = str8f(scratch.arena, "*/%S", t);
|
||||||
|
}
|
||||||
|
|
||||||
|
U64 match_count = 0;
|
||||||
|
|
||||||
if (targets.node_count > 0) {
|
|
||||||
for EachNode(pattern_n, String8Node, targets.first) {
|
|
||||||
B32 do_namespace = str8_find_needle(pattern_n->string, 0, str8_lit("::"), 0) < pattern_n->string.size;
|
|
||||||
for EachIndex(test_idx, g_torture_test_count) {
|
for EachIndex(test_idx, g_torture_test_count) {
|
||||||
String8 name = str8_cstring(g_torture_tests[test_idx]->label);
|
// match test names
|
||||||
if (do_namespace) {
|
String8 test_name = t_test_name_from_idx(scratch.arena, test_idx);
|
||||||
name = t_test_name_from_idx(scratch.arena, test_idx);
|
|
||||||
}
|
if (str8_match_wildcard(test_name, t, StringMatchFlag_CaseInsensitive)) {
|
||||||
if (str8_match_wildcard(name, pattern_n->string, 0)) {
|
// set skip flag
|
||||||
if ( ! hash_table_search_string(ht, name)) {
|
switch (mode) {
|
||||||
hash_table_push_string_raw(scratch.arena, ht, name, 0);
|
case Mode_Default: break;
|
||||||
str8_list_push(scratch.arena, &target, str8_cstring(g_torture_tests[test_idx]->label));
|
case Mode_Skip: g_torture_tests[test_idx]->skip = 1; break;
|
||||||
|
case Mode_Force: g_torture_tests[test_idx]->skip = 0; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// append test when not in skipping mode
|
||||||
|
if ( ! hash_map_search_string_u64(&hm, test_name)) {
|
||||||
|
hash_map_push_string_u64(scratch.arena, &hm, test_name, 1);
|
||||||
|
u64_list_push(scratch.arena, &targets, test_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ht->count == 0) {
|
if (match_count == 0) {
|
||||||
fprintf(stderr, "ERROR: -target matches not found for the following patterns: ");
|
fprintf(stderr, "WARNING: no matches found for input: %.*s\n", str8_varg(input_n->string));
|
||||||
for EachNode(n, String8Node, target_opt->value_strings.first) {
|
|
||||||
fprintf(stderr, "\"%.*s\"\n", str8_varg(n->string));
|
|
||||||
}
|
|
||||||
abort_self(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "ERROR: -target has invalid number of arguments\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1199,62 +1291,17 @@ t_entry_point(CmdLine *cmdline)
|
|||||||
// Run tests
|
// Run tests
|
||||||
//
|
//
|
||||||
{
|
{
|
||||||
U64List target_indices_list = {0};
|
U64Array target_indices = u64_array_from_list(scratch.arena, &targets);
|
||||||
if (target.node_count == 0) {
|
|
||||||
for EachIndex(i, g_torture_test_count) { u64_list_push(scratch.arena, &target_indices_list, i); }
|
|
||||||
} else {
|
|
||||||
for EachNode(target_n, String8Node, target.first) {
|
|
||||||
B32 is_target_unknown = 1;
|
|
||||||
for EachIndex(i, g_torture_test_count) {
|
|
||||||
if (str8_match(str8_cstring(g_torture_tests[i]->label), target_n->string, 0)) {
|
|
||||||
u64_list_push(scratch.arena, &target_indices_list, i);
|
|
||||||
is_target_unknown = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (is_target_unknown) {
|
|
||||||
fprintf(stderr, "ERROR: unknown target \"%.*s\"\n", str8_varg(target_n->string));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// -skip
|
|
||||||
//
|
|
||||||
U64List final_target_list = {0};
|
|
||||||
CmdLineOpt *skip_opt = cmd_line_opt_from_string(cmdline, str8_lit("skip"));
|
|
||||||
CmdLineOpt *s_opt = cmd_line_opt_from_string(cmdline, str8_lit("s"));
|
|
||||||
String8List skip_list = skip_opt ? skip_opt->value_strings : s_opt ? s_opt->value_strings : (String8List){0};
|
|
||||||
for EachNode(n, U64Node, target_indices_list.first) {
|
|
||||||
// should test be skipped?
|
|
||||||
B32 include_test = 1;
|
|
||||||
String8 test_name = t_test_name_from_idx(scratch.arena, n->data);
|
|
||||||
for EachNode(pattern_n, String8Node, skip_list.first) {
|
|
||||||
if (str8_match_wildcard(test_name, pattern_n->string, 0)) {
|
|
||||||
include_test = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (include_test) {
|
|
||||||
u64_list_push(scratch.arena, &final_target_list, n->data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
U64 skip_count = target_indices_list.count - final_target_list.count;
|
|
||||||
U64Array target_indices = u64_array_from_list(scratch.arena, &final_target_list);
|
|
||||||
|
|
||||||
U64 max_label_size = 0;
|
U64 max_label_size = 0;
|
||||||
U64 max_group_size = 0;
|
U64 max_group_size = 0;
|
||||||
for EachIndex(i, target_indices.count) {
|
for EachIndex(i, target_indices.count) {
|
||||||
U64 test_idx = target_indices.v[i];
|
U64 test_idx = target_indices.v[i];
|
||||||
max_label_size = Max(max_label_size, cstring8_length((U8*)g_torture_tests[test_idx]->label));
|
max_label_size = Max(max_label_size, cstring8_length((U8*)g_torture_tests[test_idx]->label));
|
||||||
max_group_size = Max(max_group_size, cstring8_length((U8*)g_torture_tests[test_idx]->group));
|
max_group_size = Max(max_group_size, t_group_from_test_idx(test_idx).size);
|
||||||
}
|
}
|
||||||
|
|
||||||
U64 pass_count = 0;
|
U64 run_counters[T_RunStatus_Count] = {0};
|
||||||
U64 fail_count = 0;
|
|
||||||
U64 crash_count = 0;
|
|
||||||
U64 max_digit_count = count_digits_u64(target_indices.count, 10);
|
U64 max_digit_count = count_digits_u64(target_indices.count, 10);
|
||||||
U64 total_time_start = now_time_us();
|
U64 total_time_start = now_time_us();
|
||||||
|
|
||||||
@@ -1262,6 +1309,8 @@ t_entry_point(CmdLine *cmdline)
|
|||||||
Slowest slowest[5] = {0};
|
Slowest slowest[5] = {0};
|
||||||
for EachElement(i, slowest) { slowest[i].target_idx = max_U64; }
|
for EachElement(i, slowest) { slowest[i].target_idx = max_U64; }
|
||||||
|
|
||||||
|
U64List skipped_tests = {0};
|
||||||
|
|
||||||
for EachIndex(i, target_indices.count) {
|
for EachIndex(i, target_indices.count) {
|
||||||
if (i == 0) { PrintHeader("Tests"); }
|
if (i == 0) { PrintHeader("Tests"); }
|
||||||
|
|
||||||
@@ -1274,7 +1323,7 @@ t_entry_point(CmdLine *cmdline)
|
|||||||
U64 curr_digit_count = count_digits_u64(i+1, 10);
|
U64 curr_digit_count = count_digits_u64(i+1, 10);
|
||||||
int idx_align_space_count = (int)(max_digit_count - curr_digit_count);
|
int idx_align_space_count = (int)(max_digit_count - curr_digit_count);
|
||||||
fprintf(stdout, "[%.*s%llu/%llu] ", idx_align_space_count, spaces, (unsigned long long)i+1, (unsigned long long)target_indices.count);
|
fprintf(stdout, "[%.*s%llu/%llu] ", idx_align_space_count, spaces, (unsigned long long)i+1, (unsigned long long)target_indices.count);
|
||||||
fprintf(stdout, "%s %.*s:: %s", test->group, (int)(max_group_size - cstring8_length((U8*)test->group)), spaces, test->label);
|
fprintf(stdout, "%.*s %.*s/ %s", str8_varg(t_group_from_test(test)), (int)(max_group_size - t_group_from_test(test).size), spaces, test->label);
|
||||||
fprintf(stdout, " %.*s ", (int)dots_count, dots);
|
fprintf(stdout, " %.*s ", (int)dots_count, dots);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
@@ -1295,19 +1344,14 @@ t_entry_point(CmdLine *cmdline)
|
|||||||
|
|
||||||
// run test
|
// run test
|
||||||
U64 run_start_time = now_time_us();
|
U64 run_start_time = now_time_us();
|
||||||
T_RunResult result = t_run(test->r, test->user_data);
|
T_RunResult result = t_run(test, test->user_data);
|
||||||
U64 run_end_time = now_time_us();
|
U64 run_end_time = now_time_us();
|
||||||
// print result
|
|
||||||
if (result.status == T_RunStatus_Pass) {
|
// update
|
||||||
fprintf(stdout, "\x1b[32m" "%s" "\x1b[0m", t_string_from_result(result.status));
|
run_counters[result.status] += 1;
|
||||||
pass_count += 1;
|
|
||||||
} else if (result.status == T_RunStatus_Fail) {
|
// print run status
|
||||||
fprintf(stdout, "\x1b[31m" "%s" "\x1b[0m", t_string_from_result(result.status));
|
fprintf(stdout, "%s%s" T_RESET, t_color_from_result(result.status), t_string_from_result(result.status));
|
||||||
fail_count += 1;
|
|
||||||
} else if (result.status == T_RunStatus_Crash) {
|
|
||||||
fprintf(stdout, "\x1b[33m" "%s" "\x1b[0m", t_string_from_result(result.status));
|
|
||||||
crash_count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.status == T_RunStatus_Pass) {
|
if (result.status == T_RunStatus_Pass) {
|
||||||
U64 d = run_end_time - run_start_time;
|
U64 d = run_end_time - run_start_time;
|
||||||
@@ -1341,18 +1385,23 @@ t_entry_point(CmdLine *cmdline)
|
|||||||
if (result.status == T_RunStatus_Fail || result.status == T_RunStatus_Crash) {
|
if (result.status == T_RunStatus_Fail || result.status == T_RunStatus_Crash) {
|
||||||
if (g_stop_on_first_fail_or_crash) { goto exit; }
|
if (g_stop_on_first_fail_or_crash) { goto exit; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.status == T_RunStatus_Skip) {
|
||||||
|
u64_list_push(scratch.arena, &skipped_tests, target_idx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
U64 total_time_end = now_time_us();
|
U64 total_time_end = now_time_us();
|
||||||
|
|
||||||
if (target_indices.count > 0 && (pass_count > 0 || fail_count > 0 || crash_count > 0 || skip_count > 0)) {
|
if (target_indices.count > 0 && sum_array_u64(ArrayCount(run_counters), run_counters) > 0) {
|
||||||
fprintf(stderr, "\n");
|
|
||||||
PrintHeader("Summary");
|
|
||||||
U64 total_time_dt = total_time_end - total_time_start;
|
U64 total_time_dt = total_time_end - total_time_start;
|
||||||
String8 total_time_str = string_from_elapsed_time(scratch.arena, date_time_from_micro_seconds(total_time_dt));
|
String8 total_time_str = string_from_elapsed_time(scratch.arena, date_time_from_micro_seconds(total_time_dt));
|
||||||
fprintf(stderr, " Passed %llu\n", (unsigned long long)pass_count);
|
|
||||||
fprintf(stderr, " Failed %llu\n", (unsigned long long)fail_count);
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, " Crashed %llu\n", (unsigned long long)crash_count);
|
PrintHeader("Summary");
|
||||||
fprintf(stderr, " Skipped %llu\n", (unsigned long long)skip_count);
|
fprintf(stderr, " Passed %llu\n", (unsigned long long)run_counters[T_RunStatus_Pass]);
|
||||||
|
fprintf(stderr, " Failed %llu\n", (unsigned long long)run_counters[T_RunStatus_Fail]);
|
||||||
|
fprintf(stderr, " Crashed %llu\n", (unsigned long long)run_counters[T_RunStatus_Crash]);
|
||||||
|
fprintf(stderr, " Skipped %llu\n", (unsigned long long)run_counters[T_RunStatus_Skip]);
|
||||||
fprintf(stderr, " Time %.*s\n", str8_varg(total_time_str));
|
fprintf(stderr, " Time %.*s\n", str8_varg(total_time_str));
|
||||||
|
|
||||||
U64 slow_count = 0;
|
U64 slow_count = 0;
|
||||||
@@ -1368,17 +1417,17 @@ t_entry_point(CmdLine *cmdline)
|
|||||||
for EachElement(i, slowest) {
|
for EachElement(i, slowest) {
|
||||||
Slowest s = slowest[i];
|
Slowest s = slowest[i];
|
||||||
label_max = Max(strlen(g_torture_tests[s.target_idx]->label), label_max);
|
label_max = Max(strlen(g_torture_tests[s.target_idx]->label), label_max);
|
||||||
group_max = Max(strlen(g_torture_tests[s.target_idx]->group), group_max);
|
group_max = Max(t_group_from_test_idx(s.target_idx).size, group_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, " Slow Tests\n");
|
fprintf(stderr, " \nSlow Tests\n");
|
||||||
for EachElement(i, slowest) {
|
for EachElement(i, slowest) {
|
||||||
Slowest s = slowest[i];
|
Slowest s = slowest[i];
|
||||||
if (s.target_idx >= g_torture_test_count) { break; }
|
if (s.target_idx >= g_torture_test_count) { break; }
|
||||||
String8 elapsed_time = string_from_elapsed_time(scratch.arena, date_time_from_micro_seconds(s.d));
|
String8 elapsed_time = string_from_elapsed_time(scratch.arena, date_time_from_micro_seconds(s.d));
|
||||||
fprintf(stderr, " %s %.*s:: %s %.*s %.*s\n",
|
fprintf(stderr, " %.*s %.*s/ %s %.*s %.*s\n",
|
||||||
g_torture_tests[s.target_idx]->group,
|
str8_varg(t_group_from_test_idx(s.target_idx)),
|
||||||
(int)(group_max - strlen(g_torture_tests[s.target_idx]->group)), spaces,
|
(int)(group_max - t_group_from_test_idx(s.target_idx).size), spaces,
|
||||||
g_torture_tests[s.target_idx]->label,
|
g_torture_tests[s.target_idx]->label,
|
||||||
(int)(label_max - strlen(g_torture_tests[s.target_idx]->label)) + 4, dots,
|
(int)(label_max - strlen(g_torture_tests[s.target_idx]->label)) + 4, dots,
|
||||||
str8_varg(elapsed_time));
|
str8_varg(elapsed_time));
|
||||||
@@ -1386,12 +1435,10 @@ t_entry_point(CmdLine *cmdline)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit_code = run_counters[T_RunStatus_Fail] + run_counters[T_RunStatus_Crash];
|
||||||
exit:;
|
exit:;
|
||||||
if (fail_count + crash_count != 0) {
|
|
||||||
fflush(stdout);
|
|
||||||
abort_self(fail_count + crash_count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
|
// TODO: return exit_code;
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-18
@@ -5,11 +5,25 @@
|
|||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
|
#define T_RESET "\x1b[0m"
|
||||||
|
#define T_RED "\x1b[31m"
|
||||||
|
#define T_GREEN "\x1b[32m"
|
||||||
|
#define T_YELLOW "\x1b[33m"
|
||||||
|
#define T_BLUE "\x1b[34m"
|
||||||
|
|
||||||
|
//#define X(n, c)
|
||||||
|
#define T_Run_XList \
|
||||||
|
X(Fail, T_RED) \
|
||||||
|
X(Crash, T_RED) \
|
||||||
|
X(Pass, T_GREEN) \
|
||||||
|
X(Skip, T_RESET)
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
T_RunStatus_Fail,
|
#define X(n,...) T_RunStatus_##n,
|
||||||
T_RunStatus_Crash,
|
T_Run_XList
|
||||||
T_RunStatus_Pass,
|
#undef X
|
||||||
|
T_RunStatus_Count
|
||||||
} T_RunStatus;
|
} T_RunStatus;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -25,20 +39,21 @@ typedef void (*T_Run)(Arena *arena, String8 user_data, T_RunResul
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
T_Run run;
|
char *file;
|
||||||
String8 user_data;
|
|
||||||
T_RunResult result;
|
|
||||||
} T_RunCtx;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char *group;
|
|
||||||
char *label;
|
char *label;
|
||||||
int decl_line;
|
int decl_line;
|
||||||
T_Run r;
|
T_Run r;
|
||||||
|
B32 skip;
|
||||||
String8 user_data;
|
String8 user_data;
|
||||||
} T_Test;
|
} T_Test;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
T_Test *test;
|
||||||
|
String8 user_data;
|
||||||
|
T_RunResult result;
|
||||||
|
} T_RunCtx;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
T_Compiler_Null,
|
T_Compiler_Null,
|
||||||
@@ -61,25 +76,28 @@ extern T_Test g_torture_tests_[0xffffff];
|
|||||||
|
|
||||||
internal void t_break_if_debugger_present(void);
|
internal void t_break_if_debugger_present(void);
|
||||||
|
|
||||||
#define T_AddTest(name, l, ...) \
|
#define T_AddTest(name, f, l, skip, ...) \
|
||||||
T_RunSig(name); \
|
T_RunSig(name); \
|
||||||
__VA_ARGS__ void t_add_test_##name(void) \
|
__VA_ARGS__ void t_add_test_##name(void) \
|
||||||
{ \
|
{ \
|
||||||
g_torture_tests_[g_torture_test_count++] = (T_Test){ .group = T_Group, .label = Stringify(name), .r = &t_##name, .decl_line = l }; \
|
g_torture_tests_[g_torture_test_count++] = (T_Test){ f, Stringify(name), l, &t_##name, skip }; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#if COMPILER_MSVC
|
#if COMPILER_MSVC
|
||||||
# pragma section(".CRT$XCU", read)
|
# pragma section(".CRT$XCU", read)
|
||||||
# define TEST_(name) \
|
# define TEST_(name, skip) \
|
||||||
T_AddTest(name, __LINE__) \
|
T_AddTest(name, __FILE__, __LINE__, skip) \
|
||||||
__declspec(allocate(".CRT$XCU")) void(*r_##name)(void) = t_add_test_##name; \
|
__declspec(allocate(".CRT$XCU")) void(*r_##name)(void) = t_add_test_##name; \
|
||||||
__pragma(comment(linker, "/include:" Stringify(r_##name)))
|
__pragma(comment(linker, "/include:" Stringify(r_##name)))
|
||||||
#else
|
#else
|
||||||
# define TEST_(name) T_AddTest(name, __LINE__, __attribute__((constructor)))
|
# define TEST_(name, skip) T_AddTest(name, __FILE__, __LINE__, skip, __attribute__((constructor)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TEST(name) \
|
#define TEST(name) \
|
||||||
TEST_(name) \
|
TEST_(name, 0) \
|
||||||
|
T_RunSig(name)
|
||||||
|
#define SKIP(name) \
|
||||||
|
TEST_(name, 1) \
|
||||||
T_RunSig(name)
|
T_RunSig(name)
|
||||||
|
|
||||||
#define T_Ok(c) do { if (!(c)) { \
|
#define T_Ok(c) do { if (!(c)) { \
|
||||||
@@ -113,7 +131,7 @@ internal String8 t_make_file_path(Arena *arena, String8 name);
|
|||||||
// test runner
|
// test runner
|
||||||
internal void t_run_caller(void *raw_ctx);
|
internal void t_run_caller(void *raw_ctx);
|
||||||
internal void t_run_fail_handler(void *raw_ctx);
|
internal void t_run_fail_handler(void *raw_ctx);
|
||||||
internal T_RunResult t_run(T_Run run, String8 user_data);
|
internal T_RunResult t_run(T_Test *test, String8 user_data);
|
||||||
|
|
||||||
// tools
|
// tools
|
||||||
internal String8 t_radbin_path(void);
|
internal String8 t_radbin_path(void);
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright (c) Epic Games Tools
|
// Copyright (c) Epic Games Tools
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
#define T_Group "Base"
|
|
||||||
|
|
||||||
TEST(str8_list_substr)
|
TEST(str8_list_substr)
|
||||||
{
|
{
|
||||||
String8List zero_list = {0};
|
String8List zero_list = {0};
|
||||||
@@ -341,4 +339,3 @@ TEST(hash_map)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef T_Group
|
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
//
|
//
|
||||||
// [ ] d2r_types alias size and byte size on __float80 typedef mismatch
|
// [ ] d2r_types alias size and byte size on __float80 typedef mismatch
|
||||||
|
|
||||||
#define T_Group "d2r"
|
|
||||||
|
|
||||||
internal RDI_Parsed *
|
internal RDI_Parsed *
|
||||||
d2r_rdi_from_dwarf_writer(Arena *arena, DW_Writer *writer)
|
d2r_rdi_from_dwarf_writer(Arena *arena, DW_Writer *writer)
|
||||||
{
|
{
|
||||||
@@ -232,7 +230,7 @@ T_Ok(str8_match(str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx), s
|
|||||||
dw_writer_end(&writer);
|
dw_writer_end(&writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(d2r_line_table)
|
SKIP(d2r_line_table)
|
||||||
{
|
{
|
||||||
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64);
|
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64);
|
||||||
String8 comp_dir = str8_lit("c:/DEVEL/");
|
String8 comp_dir = str8_lit("c:/DEVEL/");
|
||||||
@@ -303,7 +301,7 @@ TEST(d2r_line_table)
|
|||||||
dw_writer_end(&writer);
|
dw_writer_end(&writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(d2r_checksums)
|
SKIP(d2r_checksums)
|
||||||
{
|
{
|
||||||
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64);
|
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64);
|
||||||
|
|
||||||
@@ -553,4 +551,3 @@ TEST(d2r_general)
|
|||||||
dw_writer_end(&writer);
|
dw_writer_end(&writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef T_Group
|
|
||||||
|
|||||||
+180
-115
@@ -1,32 +1,54 @@
|
|||||||
// Copyright (c) Epic Games Tools
|
// Copyright (c) Epic Games Tools
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
#define T_Group "Dbg"
|
|
||||||
|
|
||||||
#define T_Dbg_DefaultTimeout TIMEOUT_SEC(5)
|
#define T_Dbg_DefaultTimeout TIMEOUT_SEC(5)
|
||||||
|
|
||||||
extern B32 g_stop_on_first_fail_or_crash;
|
extern B32 g_stop_on_first_fail_or_crash;
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
internal void
|
||||||
|
t_find_line_and_col(String8 source, MD_Node *n, U64 *line_out, U64 *col_out)
|
||||||
|
{
|
||||||
|
U64 line = 1;
|
||||||
|
U64 col = 1;
|
||||||
|
for (U64 cursor = 0; cursor < source.size && cursor < n->src_offset; cursor += 1) {
|
||||||
|
if (source.str[cursor] == '\n') {
|
||||||
|
line += 1;
|
||||||
|
col = 0;
|
||||||
|
}
|
||||||
|
col += 1;
|
||||||
|
}
|
||||||
|
if (line_out) { *line_out = line; }
|
||||||
|
if (col_out) { *col_out = col; }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
t_errorf_md(String8 file_name, String8 source, MD_Node *n, char *fmt, ...)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0,0);
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
String8 result = push_str8fv(scratch.arena, fmt, args);
|
||||||
|
U64 line = 0, col = 0;
|
||||||
|
t_find_line_and_col(source, n, &line, &col);
|
||||||
|
t_errorf("ERROR: %S:%llu%llu: %S\n", file_name, (unsigned long long)line, (unsigned long long)col, result);
|
||||||
|
va_end(args);
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Debugger IPC Replies
|
// Debugger IPC Replies
|
||||||
|
|
||||||
typedef struct RD_IpcReply RD_IpcReply;
|
typedef struct
|
||||||
struct RD_IpcReply
|
|
||||||
{
|
{
|
||||||
MD_ParseResult parse;
|
MD_ParseResult parse;
|
||||||
MD_Node *root;
|
MD_Node *root;
|
||||||
MD_Node *msg;
|
MD_Node *msg;
|
||||||
};
|
} T_IpcReply;
|
||||||
|
|
||||||
internal RD_IpcReply
|
|
||||||
rd_ipc_mdesk_reply_from_string(Arena *arena, String8 string)
|
|
||||||
{
|
|
||||||
MD_ParseResult parse = md_parse_from_text(arena, str8_lit("ipc_reply"), string);
|
|
||||||
return (RD_IpcReply){ .parse = parse, .root = parse.root, parse.root->first };
|
|
||||||
}
|
|
||||||
|
|
||||||
internal B32
|
internal B32
|
||||||
rd_ipc_parse_string(MD_Node *node, String8 child_name, String8 *out)
|
t_ipc_parse_string(MD_Node *node, String8 child_name, String8 *out)
|
||||||
{
|
{
|
||||||
MD_Node *child = md_child_from_string(node, child_name, 0);
|
MD_Node *child = md_child_from_string(node, child_name, 0);
|
||||||
if (!md_node_is_nil(child) && !md_node_is_nil(child->first))
|
if (!md_node_is_nil(child) && !md_node_is_nil(child->first))
|
||||||
@@ -38,10 +60,10 @@ rd_ipc_parse_string(MD_Node *node, String8 child_name, String8 *out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal B32
|
internal B32
|
||||||
rd_ipc_parse_u32(MD_Node *node, String8 child_name, U32 *out)
|
t_ipc_parse_u32(MD_Node *node, String8 child_name, U32 *out)
|
||||||
{
|
{
|
||||||
String8 value = {0};
|
String8 value = {0};
|
||||||
if (rd_ipc_parse_string(node, child_name, &value))
|
if (t_ipc_parse_string(node, child_name, &value))
|
||||||
{
|
{
|
||||||
U64 v64 = 0;
|
U64 v64 = 0;
|
||||||
if (try_u64_from_str8_c_rules(value, &v64))
|
if (try_u64_from_str8_c_rules(value, &v64))
|
||||||
@@ -53,12 +75,12 @@ 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)
|
#define t_ipc_parse_int(n, c, ptr) t_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)
|
t_ipc_parse_int_(MD_Node *node, String8 child_name, U64 out_size, void *out)
|
||||||
{
|
{
|
||||||
String8 value = {0};
|
String8 value = {0};
|
||||||
if (rd_ipc_parse_string(node, child_name, &value))
|
if (t_ipc_parse_string(node, child_name, &value))
|
||||||
{
|
{
|
||||||
U64 v64 = 0;
|
U64 v64 = 0;
|
||||||
if (try_u64_from_str8_c_rules(value, &v64))
|
if (try_u64_from_str8_c_rules(value, &v64))
|
||||||
@@ -71,12 +93,12 @@ rd_ipc_parse_int_(MD_Node *node, String8 child_name, U64 out_size, void *out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal B32
|
internal B32
|
||||||
rd_ipc_parse_b32(MD_Node *node, String8 child_name, B32 *out)
|
t_ipc_parse_b32(MD_Node *node, String8 child_name, B32 *out)
|
||||||
{
|
{
|
||||||
B32 is_ok = 0;
|
B32 is_ok = 0;
|
||||||
String8 s = {0};
|
String8 s = {0};
|
||||||
U64 value = 0;
|
U64 value = 0;
|
||||||
if (rd_ipc_parse_string(node, child_name, &s))
|
if (t_ipc_parse_string(node, child_name, &s))
|
||||||
{
|
{
|
||||||
if (str8_matchi(s, str8_lit("true"))) { value = 1; is_ok = 1; }
|
if (str8_matchi(s, str8_lit("true"))) { value = 1; is_ok = 1; }
|
||||||
else if (str8_matchi(s, str8_lit("false"))) { value = 0; is_ok = 1; }
|
else if (str8_matchi(s, str8_lit("false"))) { value = 0; is_ok = 1; }
|
||||||
@@ -172,9 +194,9 @@ t_dbg_state(Arena *arena, U64 timeout_us)
|
|||||||
MD_Node *threads_md = md_child_from_string(state_md, str8_lit("threads"), 0);
|
MD_Node *threads_md = md_child_from_string(state_md, str8_lit("threads"), 0);
|
||||||
MD_Node *modules_md = md_child_from_string(state_md, str8_lit("modules"), 0);
|
MD_Node *modules_md = md_child_from_string(state_md, str8_lit("modules"), 0);
|
||||||
T_DbgState v = {0};
|
T_DbgState v = {0};
|
||||||
if (!rd_ipc_parse_int(state_md, str8_lit("running"), &v.running)) { t_infof("INFO: 'state' is missing 'running'\n"); goto exit; }
|
if (!t_ipc_parse_int(state_md, str8_lit("running"), &v.running)) { t_infof("INFO: 'state' is missing 'running'\n"); goto exit; }
|
||||||
if (!rd_ipc_parse_int(state_md, str8_lit("run_gen"), &v.run_gen)) { t_infof("INFO: 'state' is missing 'run_gen'\n"); goto exit; }
|
if (!t_ipc_parse_int(state_md, str8_lit("run_gen"), &v.run_gen)) { t_infof("INFO: 'state' is missing 'run_gen'\n"); goto exit; }
|
||||||
if (!rd_ipc_parse_int(state_md, str8_lit("ip"), &v.ip)) { t_infof("INFO: 'state' is missing 'ip'\n"); goto exit; }
|
if (!t_ipc_parse_int(state_md, str8_lit("ip"), &v.ip)) { t_infof("INFO: 'state' is missing 'ip'\n"); goto exit; }
|
||||||
|
|
||||||
result = push_array(arena, T_DbgState, 1);
|
result = push_array(arena, T_DbgState, 1);
|
||||||
*result = v;
|
*result = v;
|
||||||
@@ -201,11 +223,11 @@ t_dbg_src_line(Arena *arena, U64 vaddr, T_DbgLineArray *lines_out, U64 timeout_u
|
|||||||
U64 line_count = 0;
|
U64 line_count = 0;
|
||||||
for MD_EachNode(n, lines_md->first) {
|
for MD_EachNode(n, lines_md->first) {
|
||||||
T_DbgLine line = {0};
|
T_DbgLine line = {0};
|
||||||
if ( ! rd_ipc_parse_string(n, str8_lit("file_path"), &line.file_path)) { t_infof("INFO: 'lines' is missing 'file_path'\n"); goto exit; }
|
if ( ! t_ipc_parse_string(n, str8_lit("file_path"), &line.file_path)) { t_infof("INFO: 'lines' is missing 'file_path'\n"); goto exit; }
|
||||||
if ( ! rd_ipc_parse_int(n, str8_lit("line_num"), &line.line_num)) { t_infof("INFO: 'lines' is missing 'line_num'\n"); goto exit; }
|
if ( ! t_ipc_parse_int(n, str8_lit("line_num"), &line.line_num)) { t_infof("INFO: 'lines' is missing 'line_num'\n"); goto exit; }
|
||||||
if ( ! rd_ipc_parse_int(n, str8_lit("column_num"), &line.column_num)) { t_infof("INFO: 'lines' is missing 'column_num'\n"); goto exit; }
|
if ( ! t_ipc_parse_int(n, str8_lit("column_num"), &line.column_num)) { t_infof("INFO: 'lines' is missing 'column_num'\n"); goto exit; }
|
||||||
if ( ! rd_ipc_parse_int(n, str8_lit("voff_range_min"), &line.voff_range.min)) { t_infof("INFO: 'lines' is missing 'voff_range_min'\n"); goto exit; }
|
if ( ! t_ipc_parse_int(n, str8_lit("voff_range_min"), &line.voff_range.min)) { t_infof("INFO: 'lines' is missing 'voff_range_min'\n"); goto exit; }
|
||||||
if ( ! rd_ipc_parse_int(n, str8_lit("voff_range_max"), &line.voff_range.max)) { t_infof("INFO: 'lines' is missing 'voff_range_max'\n"); goto exit; }
|
if ( ! t_ipc_parse_int(n, str8_lit("voff_range_max"), &line.voff_range.max)) { t_infof("INFO: 'lines' is missing 'voff_range_max'\n"); goto exit; }
|
||||||
|
|
||||||
Node *n = push_array(scratch.arena, Node, 1);
|
Node *n = push_array(scratch.arena, Node, 1);
|
||||||
n->v = line;
|
n->v = line;
|
||||||
@@ -393,10 +415,10 @@ t_dbg_eval(Arena *arena, String8 expr, T_Eval *eval_out)
|
|||||||
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.root, str8_lit("expr"), &e.expr)) { t_errorf("ERROR: failed to parse reply member: expr\n"); Assert(0); goto exit; }
|
if ( ! t_ipc_parse_string(reply.root, str8_lit("expr"), &e.expr)) { t_errorf_md(str8_lit("IPC"), str8_zero(), reply.root, "ERROR: failed to parse reply member: expr\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 ( ! t_ipc_parse_string(reply.root, str8_lit("value"), &e.value)) { t_errorf_md(str8_lit("IPC"), str8_zero(), reply.root, "ERROR: failed to parse reply member: value\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 ( ! t_ipc_parse_string(reply.root, str8_lit("type"), &e.type)) { t_errorf_md(str8_lit("IPC"), str8_zero(), reply.root, "ERROR: failed to parse reply member: type\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 ( ! t_ipc_parse_string(reply.root, str8_lit("error"), &e.error)) { t_errorf_md(str8_lit("IPC"), str8_zero(), reply.root, "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:;
|
||||||
@@ -424,22 +446,11 @@ internal String8
|
|||||||
t_string_from_dbg_script_cmd_kind(T_DbgScriptCmdKind v)
|
t_string_from_dbg_script_cmd_kind(T_DbgScriptCmdKind v)
|
||||||
{
|
{
|
||||||
switch (v) {
|
switch (v) {
|
||||||
|
#define X(n,v) case T_DbgScriptCmdKind_##n: return str8_lit(v);
|
||||||
|
T_DbgScriptCmdKind_XList
|
||||||
|
#undef X
|
||||||
case T_DbgScriptCmdKind_Null: return str8_zero();
|
case T_DbgScriptCmdKind_Null: return str8_zero();
|
||||||
case T_DbgScriptCmdKind_Breakpoint: return str8_lit("bp");
|
default: InvalidPath; break;
|
||||||
case T_DbgScriptCmdKind_ClearBreakpoints: return str8_lit("bp_clear");
|
|
||||||
case T_DbgScriptCmdKind_Run: return str8_lit("run");
|
|
||||||
case T_DbgScriptCmdKind_Halt: return str8_lit("halt");
|
|
||||||
case T_DbgScriptCmdKind_StepOver: return str8_lit("step_over");
|
|
||||||
case T_DbgScriptCmdKind_StepInto: return str8_lit("step_into");
|
|
||||||
case T_DbgScriptCmdKind_StepOut: return str8_lit("step_out");
|
|
||||||
case T_DbgScriptCmdKind_StepOverInst: return str8_lit("step_over_inst");
|
|
||||||
case T_DbgScriptCmdKind_StepIntoInst: return str8_lit("step_into_inst");
|
|
||||||
case T_DbgScriptCmdKind_StepOverLine: return str8_lit("step_over_line");
|
|
||||||
case T_DbgScriptCmdKind_StepIntoLine: return str8_lit("step_into_line");
|
|
||||||
case T_DbgScriptCmdKind_KillAll: return str8_lit("kill_all");
|
|
||||||
case T_DbgScriptCmdKind_At: return str8_lit("at");
|
|
||||||
case T_DbgScriptCmdKind_Eval: return str8_lit("eval");
|
|
||||||
default: InvalidPath;
|
|
||||||
}
|
}
|
||||||
return str8_zero();
|
return str8_zero();
|
||||||
}
|
}
|
||||||
@@ -508,28 +519,65 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS
|
|||||||
if (str8_matchi(field->string, str8_lit("compile"))) { kind = T_DbgScriptDirectiveKind_Compile; }
|
if (str8_matchi(field->string, str8_lit("compile"))) { kind = T_DbgScriptDirectiveKind_Compile; }
|
||||||
else if (str8_matchi(field->string, str8_lit("link"))) { kind = T_DbgScriptDirectiveKind_Link; }
|
else if (str8_matchi(field->string, str8_lit("link"))) { kind = T_DbgScriptDirectiveKind_Link; }
|
||||||
else if (str8_matchi(field->string, str8_lit("launch"))) { kind = T_DbgScriptDirectiveKind_Launch; }
|
else if (str8_matchi(field->string, str8_lit("launch"))) { kind = T_DbgScriptDirectiveKind_Launch; }
|
||||||
AssertAlways(kind != T_DbgScriptDirectiveKind_Null);
|
else if (str8_matchi(field->string, str8_lit("skip"))) { kind = T_DbgScriptDirectiveKind_Skip; }
|
||||||
|
|
||||||
// syntax check
|
if (kind == T_DbgScriptDirectiveKind_Null) {
|
||||||
AssertAlways( !md_node_is_nil(field->first));
|
t_errorf_md(file_path, source, n, "unknown field in test header \"%S\"\n", field->string);
|
||||||
AssertAlways(md_node_is_nil(field->first->next));
|
goto exit;
|
||||||
Assert(field->first->flags & MD_NodeFlag_StringLiteral);
|
}
|
||||||
|
|
||||||
// src_offset -> line
|
T_DbgScriptDirective *dir = push_array(arena, T_DbgScriptDirective, 1);
|
||||||
//
|
dir->kind = kind;
|
||||||
// TODO: super silly!! mdesk should export line numbers
|
t_find_line_and_col(source, field, &dir->line, 0);
|
||||||
U64 line = 1;
|
|
||||||
String8 text_before_src = str8_prefix(source, field->src_offset);
|
|
||||||
for EachIndex(idx, text_before_src.size) { line += (text_before_src.str[idx] == '\n'); }
|
|
||||||
|
|
||||||
T_DbgScriptDirective *n = push_array(arena, T_DbgScriptDirective, 1);
|
if (field->flags & MD_NodeFlag_HasBraceLeft) {
|
||||||
n->kind = kind;
|
if (kind == T_DbgScriptDirectiveKind_Compile) {
|
||||||
n->line = line;
|
for MD_EachNode(sub_field, field->first) {
|
||||||
n->args = str8_copy(arena, field->first->string);
|
if (str8_matchi(sub_field->string, str8_lit("cc"))) {
|
||||||
// TODO: expand % in compile: and link: to current source file name and esacpe with %%
|
MD_Node *cc = sub_field->first;
|
||||||
|
if (cc->flags & MD_NodeFlag_StringLiteral) {
|
||||||
|
if (str8_matchi(cc->string, str8_lit("clang"))) { dir->compile.cc = T_Compiler_Clang; }
|
||||||
|
else if (str8_matchi(cc->string, str8_lit("cl"))) { dir->compile.cc = T_Compiler_Cl; }
|
||||||
|
else {
|
||||||
|
t_errorf_md(file_path, source, cc, "unknown compiler name: \"%S\"\n", sub_field->string);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t_errorf_md(file_path, source, sub_field, "value of CC must be a string literal e.g. CC: \"clang\"\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
} else if (str8_matchi(sub_field->string, str8_lit("args"))) {
|
||||||
|
MD_Node *args = sub_field->first;
|
||||||
|
if (args->flags & MD_NodeFlag_StringLiteral) {
|
||||||
|
dir->args = str8_copy(arena, args->string);
|
||||||
|
} else {
|
||||||
|
t_errorf_md(file_path, source, args, "value of ARGS must be a string literal\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t_errorf_md(file_path, source, sub_field, "unknown field \"%S\"\n", sub_field->string);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (md_node_is_nil(field->first)) {
|
||||||
|
t_errorf_md(file_path, source, field, "missing value on field %S\n", field->string);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if ( ! md_node_is_nil(field->first->next)) {
|
||||||
|
t_errorf_md(file_path, source, field, "field %S accepts only one value\n", field->string);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (~field->first->flags & MD_NodeFlag_StringLiteral) {
|
||||||
|
t_errorf_md(file_path, source, field, "field %S accepts only strings\n", field->string);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
dir->args = str8_copy(arena, field->first->string);
|
||||||
|
}
|
||||||
|
|
||||||
T_DbgScriptDirectiveList *list = &script.directives[os][kind];
|
T_DbgScriptDirectiveList *list = &script.directives[os][kind];
|
||||||
SLLQueuePush(list->first, list->last, n);
|
SLLQueuePush(list->first, list->last, dir);
|
||||||
list->count += 1;
|
list->count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -541,52 +589,59 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS
|
|||||||
|
|
||||||
// file
|
// file
|
||||||
{
|
{
|
||||||
MD_Node *last_file = 0;
|
MD_NodePtrList files = {0};
|
||||||
for MD_EachNode(n, script_parse.root->first->next) {
|
for MD_EachNode(n, script_parse.root->first->next) {
|
||||||
B32 is_end = (md_node_is_nil(n->next) && last_file != 0);
|
if (str8_matchi(n->string, str8_lit("file"))) {
|
||||||
if (str8_matchi(n->string, str8_lit("file")) || is_end) {
|
|
||||||
if (!is_end) {
|
|
||||||
AssertAlways( ! md_node_is_nil(n->first));
|
AssertAlways( ! md_node_is_nil(n->first));
|
||||||
AssertAlways(md_node_is_nil(n->first->next));
|
|
||||||
|
if ( ! md_node_is_nil(n->first->next) || ! (n->first->flags & MD_NodeFlag_StringLiteral)) {
|
||||||
|
U32 line = 0;
|
||||||
|
for EachIndex(idx, n->first->src_offset) { line += (source.str[idx] == '\n'); }
|
||||||
|
t_errorf_md(file_path, source, n, "value of the 'file' must be a string, (e.g. file: \"main.c\")\n", file_path, line);
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_file) {
|
md_node_ptr_list_push(scratch.arena, &files, n);
|
||||||
// src_offset -> base_line
|
}
|
||||||
//
|
}
|
||||||
// TODO: super silly!! mdesk should export line numbers
|
|
||||||
U64 line = 1;
|
|
||||||
for EachIndex(idx, last_file->src_offset) { line += (source.str[idx] == '\n'); }
|
|
||||||
|
|
||||||
String8 sub_source = str8_substr(source, r1u64(last_file->src_offset, is_end ? source.size : n->src_offset));
|
if (files.count == 0) {
|
||||||
U64 file_dir_end = str8_find_needle(sub_source, 0, str8_lit("\n"), 0);
|
MD_Node *whole_file = push_array(scratch.arena, MD_Node, 1);
|
||||||
U64 next_file_dir_begin = str8_find_needle_reverse(sub_source, 0, str8_lit("\n"), n->src_offset);
|
whole_file->first = push_array(scratch.arena, MD_Node, 1);
|
||||||
sub_source = str8_substr(sub_source, r1u64(file_dir_end + 1, next_file_dir_begin));
|
whole_file->first->next = push_array(scratch.arena, MD_Node, 1);
|
||||||
|
whole_file->src_offset = 0;
|
||||||
|
whole_file->first->string = str8_skip_last_slash(file_path);
|
||||||
|
md_node_ptr_list_push(scratch.arena, &files, whole_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMap files_hm = {0};
|
||||||
|
for EachNode(n_ptr, MD_NodePtrNode, files.first) {
|
||||||
|
MD_Node *n = n_ptr->v;
|
||||||
|
|
||||||
|
U64 src_opl = source.size;
|
||||||
|
if (n_ptr->next) {
|
||||||
|
src_opl = n_ptr->next->v->src_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
String8 sub_source = str8_substr(source, r1u64(n->src_offset, src_opl));
|
||||||
|
U64 file_min = str8_find_needle(sub_source, 0, str8_lit("\n"), 0) + 1;
|
||||||
|
U64 file_max = str8_find_needle_reverse(sub_source, 0, str8_lit("\n"), 0);
|
||||||
|
sub_source = str8_substr(sub_source, r1u64(file_min, file_max));
|
||||||
|
|
||||||
T_DbgScriptFile *file = push_array(arena, T_DbgScriptFile, 1);
|
T_DbgScriptFile *file = push_array(arena, T_DbgScriptFile, 1);
|
||||||
file->path = t_make_file_path(arena, last_file->first->string);
|
file->path = t_make_file_path(arena, n->first->string);
|
||||||
file->source = sub_source;
|
file->source = sub_source;
|
||||||
file->line = line;
|
t_find_line_and_col(source, n, &file->line, 0);
|
||||||
SLLQueuePush(script.files.first, script.files.last, file);
|
SLLQueuePush(script.files.first, script.files.last, file);
|
||||||
script.files.count += 1;
|
script.files.count += 1;
|
||||||
}
|
|
||||||
|
|
||||||
last_file = n;
|
hash_map_push_raw_raw(scratch.arena, &files_hm, n, file);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// no file directives? assume script file as main source file
|
|
||||||
if (last_file == 0) {
|
|
||||||
T_DbgScriptFile *file = push_array(arena, T_DbgScriptFile, 1);
|
|
||||||
file->path = file_path;
|
|
||||||
file->source = source;
|
|
||||||
SLLQueuePush(script.files.first, script.files.last, file);
|
|
||||||
script.files.count += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// programs
|
// programs
|
||||||
{
|
{
|
||||||
HashTable *ht = hash_table_init(scratch.arena, 256); // <U64, T_DbgScriptProgram>
|
HashMap hm = {0}; // <U64, T_DbgScriptProgram>
|
||||||
for MD_EachNode(n, script_parse.root->first->next) {
|
for MD_EachNode(n, script_parse.root->first->next) {
|
||||||
U64 order = 0;
|
U64 order = 0;
|
||||||
if (try_u64_from_str8_c_rules(n->string, &order)) {
|
if (try_u64_from_str8_c_rules(n->string, &order)) {
|
||||||
@@ -598,20 +653,14 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS
|
|||||||
}
|
}
|
||||||
AssertAlways(file != 0);
|
AssertAlways(file != 0);
|
||||||
|
|
||||||
// src_offset -> line
|
T_DbgScriptProgram *p = hash_map_search_u64_raw(&hm, order);
|
||||||
//
|
|
||||||
// TODO: super silly!! mdesk should export line numbers
|
|
||||||
U64 line = 1;
|
|
||||||
for EachIndex(i, n->src_offset) { line += (source.str[i] == '\n'); }
|
|
||||||
|
|
||||||
T_DbgScriptProgram *p = hash_table_search_u64_raw(ht, order);
|
|
||||||
if (p == 0) {
|
if (p == 0) {
|
||||||
p = push_array(arena, T_DbgScriptProgram, 1);
|
p = push_array(arena, T_DbgScriptProgram, 1);
|
||||||
p->line = line;
|
t_find_line_and_col(source, n, &p->line, 0);
|
||||||
p->order = order;
|
p->order = order;
|
||||||
p->os = OperatingSystem_CURRENT;
|
p->os = OperatingSystem_CURRENT;
|
||||||
p->file = file;
|
p->file = file;
|
||||||
hash_table_push_u64_raw(scratch.arena, ht, order, p);
|
hash_map_push_u64_raw(scratch.arena, &hm, order, p);
|
||||||
} else {
|
} else {
|
||||||
t_errorf("ERROR: duplicate order number %llu found on line %llu\n", (unsigned long long)order, (unsigned long long)p->line);
|
t_errorf("ERROR: duplicate order number %llu found on line %llu\n", (unsigned long long)order, (unsigned long long)p->line);
|
||||||
}
|
}
|
||||||
@@ -620,7 +669,7 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS
|
|||||||
// push new cmd
|
// push new cmd
|
||||||
T_DbgScriptCmd *cmd = push_array(arena, T_DbgScriptCmd, 1);
|
T_DbgScriptCmd *cmd = push_array(arena, T_DbgScriptCmd, 1);
|
||||||
cmd->kind = t_dbg_script_cmd_kind_from_string(cmd_n->string);
|
cmd->kind = t_dbg_script_cmd_kind_from_string(cmd_n->string);
|
||||||
cmd->line = line;
|
t_find_line_and_col(source, n, &cmd->line_num, &cmd->col_num);
|
||||||
Assert(cmd->kind != T_DbgScriptCmdKind_Null);
|
Assert(cmd->kind != T_DbgScriptCmdKind_Null);
|
||||||
SLLQueuePush(p->first, p->last, cmd);
|
SLLQueuePush(p->first, p->last, cmd);
|
||||||
p->count += 1;
|
p->count += 1;
|
||||||
@@ -640,8 +689,8 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
script.program_count = ht->count;
|
script.program_count = hm.count;
|
||||||
script.programs = values_from_hash_table_raw(arena, ht);
|
script.programs = values_from_hash_map_raw(arena, &hm);
|
||||||
radsort(script.programs, script.program_count, t_dbg_script_program_is_before);
|
radsort(script.programs, script.program_count, t_dbg_script_program_is_before);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -666,7 +715,7 @@ t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us)
|
|||||||
|
|
||||||
if (program->os == OperatingSystem_CURRENT) {
|
if (program->os == OperatingSystem_CURRENT) {
|
||||||
for EachNode(cmd, T_DbgScriptCmd, program->first) {
|
for EachNode(cmd, T_DbgScriptCmd, program->first) {
|
||||||
t_infof("[%llu] Command: %S:%llu %S\n", program->order, script->file_path, (unsigned long long)cmd->line, t_string_from_dbg_script_cmd_kind(cmd->kind));
|
t_infof("[%llu] Command: %S:%llu %S\n", program->order, script->file_path, (unsigned long long)cmd->line_num, t_string_from_dbg_script_cmd_kind(cmd->kind));
|
||||||
|
|
||||||
switch (cmd->kind) {
|
switch (cmd->kind) {
|
||||||
case T_DbgScriptCmdKind_Null: break;
|
case T_DbgScriptCmdKind_Null: break;
|
||||||
@@ -694,7 +743,7 @@ t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us)
|
|||||||
#else
|
#else
|
||||||
T_DbgState *temp_status = t_dbg_state(scratch.arena, T_Dbg_DefaultTimeout);
|
T_DbgState *temp_status = t_dbg_state(scratch.arena, T_Dbg_DefaultTimeout);
|
||||||
if (temp_status == 0) {
|
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_num);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
U64 ip = temp_status->ip;
|
U64 ip = temp_status->ip;
|
||||||
@@ -703,7 +752,7 @@ t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us)
|
|||||||
// map IP -> source location
|
// map IP -> source location
|
||||||
T_DbgLineArray lines = {0};
|
T_DbgLineArray lines = {0};
|
||||||
if (t_dbg_src_line(scratch.arena, ip, &lines, 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_num, (unsigned long long)ip);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -712,13 +761,17 @@ t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us)
|
|||||||
U64 at_line_u64 = at_line_s64 >= 0 ? (U64)at_line_s64 : 0;
|
U64 at_line_u64 = at_line_s64 >= 0 ? (U64)at_line_s64 : 0;
|
||||||
AssertAlways(at_line_u64 > 0);
|
AssertAlways(at_line_u64 > 0);
|
||||||
|
|
||||||
// match expected vs current debugger locations
|
if (lines.count == 0) {
|
||||||
|
t_errorf("ERROR: %S:%llu:%llu: no source location maps for vaddr: 0x%llx\n", script->file_path, (unsigned long long)cmd->line_num, (unsigned long long)cmd->col_num, (unsigned long long)ip);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// match expected vs current debugger locations
|
||||||
for EachIndex(i, lines.count) {
|
for EachIndex(i, lines.count) {
|
||||||
B32 mismatch = lines.v[i].line_num != at_line_u64 ||
|
B32 mismatch = lines.v[i].line_num != at_line_u64 ||
|
||||||
!str8_match(lines.v[i].file_path, program->file->path, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive);
|
!str8_match(lines.v[i].file_path, program->file->path, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive);
|
||||||
if (mismatch) {
|
if (mismatch) {
|
||||||
t_errorf("ERROR: %S:%llu: location check did not pass:\n", script->file_path, (unsigned long long)cmd->line);
|
t_errorf("ERROR: %S:%llu: location check did not pass:\n", script->file_path, (unsigned long long)cmd->line_num);
|
||||||
t_errorf(" Expected: %S:%llu\n", program->file->path, (unsigned long long)at_line_u64);
|
t_errorf(" Expected: %S:%llu\n", program->file->path, (unsigned long long)at_line_u64);
|
||||||
t_errorf(" Got : %S:%llu\n", lines.v[i].file_path, (unsigned long long)lines.v[i].line_num);
|
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);
|
t_errorf(" IP : 0x%llx\n", (unsigned long long)ip);
|
||||||
@@ -758,6 +811,7 @@ T_RunSig(dbg_script_runner)
|
|||||||
// source -> script
|
// source -> script
|
||||||
T_DbgScript script = {0};
|
T_DbgScript script = {0};
|
||||||
if ( ! t_dbg_script_from_source(arena, user_data, source, &script)) {
|
if ( ! t_dbg_script_from_source(arena, user_data, source, &script)) {
|
||||||
|
result_out->status = T_RunStatus_Fail;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -769,16 +823,22 @@ T_RunSig(dbg_script_runner)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (script.directives[OperatingSystem_CURRENT][T_DbgScriptDirectiveKind_Skip].count) {
|
||||||
|
result_out->status = T_RunStatus_Skip;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
// compiler vars
|
// compiler vars
|
||||||
HashTable *script_vars = hash_table_init(arena, 1000);
|
HashTable *script_vars = hash_table_init(arena, 1000);
|
||||||
|
hash_table_push_path_string(arena, script_vars, str8_lit("FILE"), user_data);
|
||||||
hash_table_push_path_string(arena, script_vars, str8_lit("CWD"), g_wdir);
|
hash_table_push_path_string(arena, script_vars, str8_lit("CWD"), g_wdir);
|
||||||
|
|
||||||
// run compilers
|
// run compilers
|
||||||
for EachNode(directive, T_DbgScriptDirective, script.directives[OperatingSystem_CURRENT][T_DbgScriptDirectiveKind_Compile].first) {
|
for EachNode(directive, T_DbgScriptDirective, script.directives[OperatingSystem_CURRENT][T_DbgScriptDirectiveKind_Compile].first) {
|
||||||
T_Compiler compiler = directive->compile.compiler;
|
T_Compiler compiler = directive->compile.cc;
|
||||||
|
|
||||||
// pick default compiler if none selected
|
// pick default compiler if none selected
|
||||||
if (compiler == T_Compiler_Null) {
|
if (directive->compile.cc == T_Compiler_Null) {
|
||||||
switch (OperatingSystem_CURRENT) {
|
switch (OperatingSystem_CURRENT) {
|
||||||
case OperatingSystem_Windows: { compiler = T_Compiler_Cl; } break;
|
case OperatingSystem_Windows: { compiler = T_Compiler_Cl; } break;
|
||||||
case OperatingSystem_Linux: { compiler = T_Compiler_Clang; } break;
|
case OperatingSystem_Linux: { compiler = T_Compiler_Clang; } break;
|
||||||
@@ -796,10 +856,16 @@ T_RunSig(dbg_script_runner)
|
|||||||
|
|
||||||
// invoke compiler with arguments from directive
|
// invoke compiler with arguments from directive
|
||||||
String8 expanded_args = lnk_expand_env_vars_windows(arena, script_vars, directive->args);
|
String8 expanded_args = lnk_expand_env_vars_windows(arena, script_vars, directive->args);
|
||||||
|
|
||||||
|
if (compiler == T_Compiler_Cl) { expanded_args = str8f(arena, "/nologo %S", expanded_args); }
|
||||||
|
|
||||||
if (t_invoke(compiler_path, expanded_args, max_U64) == 0) {
|
if (t_invoke(compiler_path, expanded_args, max_U64) == 0) {
|
||||||
t_errorf("ERROR: failed to launch compiler: \"%S %S\"\n", compiler_path, expanded_args);
|
t_errorf("ERROR: failed to launch compiler: \"%S %S\"\n", compiler_path, expanded_args);
|
||||||
T_Ok(0);
|
T_Ok(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (compiler == T_Compiler_Cl) { g_output = str8_skip(g_output, str8_chop_line(&g_output).size); } // file name print
|
||||||
|
|
||||||
if (g_last_exit_code) {
|
if (g_last_exit_code) {
|
||||||
t_errorf("ERROR: %S:%llu: %S\n", script.file_path, (unsigned long long)directive->line, g_errors);
|
t_errorf("ERROR: %S:%llu: %S\n", script.file_path, (unsigned long long)directive->line, g_errors);
|
||||||
if (g_stop_on_first_fail_or_crash) {
|
if (g_stop_on_first_fail_or_crash) {
|
||||||
@@ -875,7 +941,7 @@ t_dbg_register_script_tests(Arena *arena, String8 folder_path)
|
|||||||
String8 file_name_escaped = str8_list_join(arena, &file_name_parts, &(StringJoin){.sep=str8_lit("-"), .post = str8_lit("\0") });
|
String8 file_name_escaped = str8_list_join(arena, &file_name_parts, &(StringJoin){.sep=str8_lit("-"), .post = str8_lit("\0") });
|
||||||
|
|
||||||
g_torture_tests_[g_torture_test_count++] = (T_Test){
|
g_torture_tests_[g_torture_test_count++] = (T_Test){
|
||||||
.group = T_Group,
|
.file = "raddbg",
|
||||||
.label = (char*)file_name_escaped.str,
|
.label = (char*)file_name_escaped.str,
|
||||||
.r = t_dbg_script_runner,
|
.r = t_dbg_script_runner,
|
||||||
.user_data = str8_copy(arena, file_path),
|
.user_data = str8_copy(arena, file_path),
|
||||||
@@ -885,4 +951,3 @@ t_dbg_register_script_tests(Arena *arena, String8 folder_path)
|
|||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef T_Group
|
|
||||||
|
|||||||
+23
-16
@@ -21,23 +21,28 @@ typedef struct
|
|||||||
T_DbgScriptFile *last;
|
T_DbgScriptFile *last;
|
||||||
} T_DbgScriptFileList;
|
} T_DbgScriptFileList;
|
||||||
|
|
||||||
|
#define T_DbgScriptCmdKind_XList \
|
||||||
|
X(Breakpoint, "bp") \
|
||||||
|
X(ClearBreakpoints, "bp_clear") \
|
||||||
|
X(Run, "run") \
|
||||||
|
X(Halt, "halt") \
|
||||||
|
X(StepOver, "step_over") \
|
||||||
|
X(StepInto, "step_into") \
|
||||||
|
X(StepOut, "step_out") \
|
||||||
|
X(StepOverInst, "step_over_inst") \
|
||||||
|
X(StepIntoInst, "step_over_inst") \
|
||||||
|
X(StepOverLine, "step_over_line") \
|
||||||
|
X(StepIntoLine, "step_into_line") \
|
||||||
|
X(KillAll, "kll_all") \
|
||||||
|
X(At, "at") \
|
||||||
|
X(Eval, "eval")
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
T_DbgScriptCmdKind_Null,
|
T_DbgScriptCmdKind_Null,
|
||||||
T_DbgScriptCmdKind_Breakpoint,
|
#define X(n,...) T_DbgScriptCmdKind_##n,
|
||||||
T_DbgScriptCmdKind_ClearBreakpoints,
|
T_DbgScriptCmdKind_XList
|
||||||
T_DbgScriptCmdKind_Run,
|
#undef X
|
||||||
T_DbgScriptCmdKind_Halt,
|
|
||||||
T_DbgScriptCmdKind_StepOver,
|
|
||||||
T_DbgScriptCmdKind_StepInto,
|
|
||||||
T_DbgScriptCmdKind_StepOut,
|
|
||||||
T_DbgScriptCmdKind_StepOverInst,
|
|
||||||
T_DbgScriptCmdKind_StepIntoInst,
|
|
||||||
T_DbgScriptCmdKind_StepOverLine,
|
|
||||||
T_DbgScriptCmdKind_StepIntoLine,
|
|
||||||
T_DbgScriptCmdKind_KillAll,
|
|
||||||
T_DbgScriptCmdKind_At,
|
|
||||||
T_DbgScriptCmdKind_Eval,
|
|
||||||
T_DbgScriptCmdKind_Count
|
T_DbgScriptCmdKind_Count
|
||||||
} T_DbgScriptCmdKind;
|
} T_DbgScriptCmdKind;
|
||||||
|
|
||||||
@@ -45,7 +50,8 @@ typedef struct T_DbgScriptCmd
|
|||||||
{
|
{
|
||||||
struct T_DbgScriptCmd *next;
|
struct T_DbgScriptCmd *next;
|
||||||
T_DbgScriptCmdKind kind;
|
T_DbgScriptCmdKind kind;
|
||||||
U64 line;
|
U64 line_num;
|
||||||
|
U64 col_num;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
S64 delta;
|
S64 delta;
|
||||||
@@ -78,6 +84,7 @@ typedef enum
|
|||||||
T_DbgScriptDirectiveKind_Compile,
|
T_DbgScriptDirectiveKind_Compile,
|
||||||
T_DbgScriptDirectiveKind_Link,
|
T_DbgScriptDirectiveKind_Link,
|
||||||
T_DbgScriptDirectiveKind_Launch,
|
T_DbgScriptDirectiveKind_Launch,
|
||||||
|
T_DbgScriptDirectiveKind_Skip,
|
||||||
T_DbgScriptDirectiveKind_Count,
|
T_DbgScriptDirectiveKind_Count,
|
||||||
} T_DbgScriptDirectiveKind;
|
} T_DbgScriptDirectiveKind;
|
||||||
|
|
||||||
@@ -89,7 +96,7 @@ typedef struct T_DbgScriptDirective
|
|||||||
String8 args;
|
String8 args;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
T_Compiler compiler;
|
T_Compiler cc;
|
||||||
} compile;
|
} compile;
|
||||||
};
|
};
|
||||||
} T_DbgScriptDirective;
|
} T_DbgScriptDirective;
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright (c) Epic Games Tools
|
// Copyright (c) Epic Games Tools
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
#define T_Group "Dwarf"
|
|
||||||
|
|
||||||
internal U64
|
internal U64
|
||||||
t_dw_test_uleb128(U64 v, U64 expected_length)
|
t_dw_test_uleb128(U64 v, U64 expected_length)
|
||||||
{
|
{
|
||||||
@@ -1040,4 +1038,3 @@ TEST(reg_split_spill)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef T_Group
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#define T_Group "MD"
|
#define T_Group "MD"
|
||||||
|
|
||||||
TEST(md_tokenizer)
|
SKIP(md_tokenizer)
|
||||||
{
|
{
|
||||||
MD_TokenizeResult result;
|
MD_TokenizeResult result;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
#define T_Group "p2r"
|
|
||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
|
|
||||||
// TODO: location is not baked consistently
|
// TODO: location is not baked consistently
|
||||||
@@ -127,5 +125,3 @@ TEST(p2r_determ)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef T_Group
|
|
||||||
|
|
||||||
|
|||||||
@@ -433,8 +433,6 @@ t_write_entry_obj(void)
|
|||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
#define T_Group "Linker"
|
|
||||||
|
|
||||||
TEST(machine_compat_check)
|
TEST(machine_compat_check)
|
||||||
{
|
{
|
||||||
// unknown.obj
|
// unknown.obj
|
||||||
@@ -4712,7 +4710,7 @@ TEST(relocate_undefined_section_symbol)
|
|||||||
T_Ok(t_write_def_obj(obj_name, (T_COFF_DefObj){
|
T_Ok(t_write_def_obj(obj_name, (T_COFF_DefObj){
|
||||||
.machine = T_COFF_DefSetMachine(X64),
|
.machine = T_COFF_DefSetMachine(X64),
|
||||||
.sections = (T_COFF_DefSection[]){
|
.sections = (T_COFF_DefSection[]){
|
||||||
{ target_name, sect_name, target_name, .flags = "r:data@1", .raw_flags = COFF_SectionFlag_LnkCOMDAT },
|
{ target_name, sect_name, str8_cstring(target_name), .flags = "r:data@1", .raw_flags = COFF_SectionFlag_LnkCOMDAT },
|
||||||
{0}
|
{0}
|
||||||
},
|
},
|
||||||
.symbols = (T_COFF_DefSymbol[]){
|
.symbols = (T_COFF_DefSymbol[]){
|
||||||
@@ -7203,4 +7201,3 @@ TEST(lib_member_reloc_apply_off_out_of_bounds)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef T_Group
|
|
||||||
|
|||||||
Reference in New Issue
Block a user