mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-05 21:38:40 +00:00
stdout redirection support in os command line launch helper; do rdi dumps in determinism test
This commit is contained in:
+37
-1
@@ -163,16 +163,52 @@ os_cmd_line_launch(String8 string)
|
|||||||
OS_Handle handle = {0};
|
OS_Handle handle = {0};
|
||||||
if(parts.node_count != 0)
|
if(parts.node_count != 0)
|
||||||
{
|
{
|
||||||
|
// rjf: unpack exe part
|
||||||
String8 exe = parts.first->string;
|
String8 exe = parts.first->string;
|
||||||
String8 exe_folder = str8_chop_last_slash(exe);
|
String8 exe_folder = str8_chop_last_slash(exe);
|
||||||
if(exe_folder.size == 0)
|
if(exe_folder.size == 0)
|
||||||
{
|
{
|
||||||
exe_folder = os_get_current_path(scratch.arena);
|
exe_folder = os_get_current_path(scratch.arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rjf: find stdout delimiter
|
||||||
|
String8Node *stdout_delimiter_n = 0;
|
||||||
|
for(String8Node *n = parts.first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
if(str8_match(n->string, str8_lit(">"), 0))
|
||||||
|
{
|
||||||
|
stdout_delimiter_n = n;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: read stdout path
|
||||||
|
String8 stdout_path = {0};
|
||||||
|
if(stdout_delimiter_n && stdout_delimiter_n->next)
|
||||||
|
{
|
||||||
|
stdout_path = stdout_delimiter_n->next->string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: open stdout handle
|
||||||
|
OS_Handle stdout_handle = {0};
|
||||||
|
if(stdout_path.size != 0)
|
||||||
|
{
|
||||||
|
stdout_handle = os_file_open(OS_AccessFlag_Write|OS_AccessFlag_Append|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite|OS_AccessFlag_Inherited, stdout_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: form command line
|
||||||
|
String8List cmdline = {0};
|
||||||
|
for(String8Node *n = parts.first; n != stdout_delimiter_n && n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
str8_list_push(scratch.arena, &cmdline, n->string);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: launch
|
||||||
OS_ProcessLaunchParams params = {0};
|
OS_ProcessLaunchParams params = {0};
|
||||||
params.cmd_line = parts;
|
params.cmd_line = cmdline;
|
||||||
params.path = exe_folder;
|
params.path = exe_folder;
|
||||||
params.inherit_env = 1;
|
params.inherit_env = 1;
|
||||||
|
params.stdout_file = stdout_handle;
|
||||||
handle = os_process_launch(¶ms);
|
handle = os_process_launch(¶ms);
|
||||||
}
|
}
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
|
|||||||
+15
-13
@@ -44,6 +44,7 @@ enum
|
|||||||
OS_AccessFlag_Append = (1<<3),
|
OS_AccessFlag_Append = (1<<3),
|
||||||
OS_AccessFlag_ShareRead = (1<<4),
|
OS_AccessFlag_ShareRead = (1<<4),
|
||||||
OS_AccessFlag_ShareWrite = (1<<5),
|
OS_AccessFlag_ShareWrite = (1<<5),
|
||||||
|
OS_AccessFlag_Inherited = (1<<6),
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@@ -79,19 +80,6 @@ struct OS_FileID
|
|||||||
U64 v[3];
|
U64 v[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Process Launch Parameters
|
|
||||||
|
|
||||||
typedef struct OS_ProcessLaunchParams OS_ProcessLaunchParams;
|
|
||||||
struct OS_ProcessLaunchParams
|
|
||||||
{
|
|
||||||
String8List cmd_line;
|
|
||||||
String8 path;
|
|
||||||
String8List env;
|
|
||||||
B32 inherit_env;
|
|
||||||
B32 consoleless;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Handle Type
|
//~ rjf: Handle Type
|
||||||
|
|
||||||
@@ -123,6 +111,20 @@ struct OS_HandleArray
|
|||||||
U64 count;
|
U64 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Process Launch Parameters
|
||||||
|
|
||||||
|
typedef struct OS_ProcessLaunchParams OS_ProcessLaunchParams;
|
||||||
|
struct OS_ProcessLaunchParams
|
||||||
|
{
|
||||||
|
String8List cmd_line;
|
||||||
|
String8 path;
|
||||||
|
String8List env;
|
||||||
|
B32 inherit_env;
|
||||||
|
B32 consoleless;
|
||||||
|
OS_Handle stdout_file;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Globally Unique IDs
|
//~ rjf: Globally Unique IDs
|
||||||
|
|
||||||
|
|||||||
@@ -293,14 +293,19 @@ os_file_open(OS_AccessFlags flags, String8 path)
|
|||||||
DWORD access_flags = 0;
|
DWORD access_flags = 0;
|
||||||
DWORD share_mode = 0;
|
DWORD share_mode = 0;
|
||||||
DWORD creation_disposition = OPEN_EXISTING;
|
DWORD creation_disposition = OPEN_EXISTING;
|
||||||
|
SECURITY_ATTRIBUTES security_attributes = {sizeof(security_attributes), 0, 0};
|
||||||
if(flags & OS_AccessFlag_Read) {access_flags |= GENERIC_READ;}
|
if(flags & OS_AccessFlag_Read) {access_flags |= GENERIC_READ;}
|
||||||
if(flags & OS_AccessFlag_Write) {access_flags |= GENERIC_WRITE;}
|
if(flags & OS_AccessFlag_Write) {access_flags |= GENERIC_WRITE;}
|
||||||
if(flags & OS_AccessFlag_Execute) {access_flags |= GENERIC_EXECUTE;}
|
if(flags & OS_AccessFlag_Execute) {access_flags |= GENERIC_EXECUTE;}
|
||||||
if(flags & OS_AccessFlag_ShareRead) {share_mode |= FILE_SHARE_READ;}
|
if(flags & OS_AccessFlag_ShareRead) {share_mode |= FILE_SHARE_READ;}
|
||||||
if(flags & OS_AccessFlag_ShareWrite) {share_mode |= FILE_SHARE_WRITE|FILE_SHARE_DELETE;}
|
if(flags & OS_AccessFlag_ShareWrite) {share_mode |= FILE_SHARE_WRITE|FILE_SHARE_DELETE;}
|
||||||
if(flags & OS_AccessFlag_Write) {creation_disposition = CREATE_ALWAYS;}
|
if(flags & OS_AccessFlag_Write) {creation_disposition = CREATE_ALWAYS;}
|
||||||
if(flags & OS_AccessFlag_Append) {creation_disposition = OPEN_ALWAYS;}
|
if(flags & OS_AccessFlag_Append) {creation_disposition = OPEN_ALWAYS; access_flags |= FILE_APPEND_DATA; }
|
||||||
HANDLE file = CreateFileW((WCHAR *)path16.str, access_flags, share_mode, 0, creation_disposition, FILE_ATTRIBUTE_NORMAL, 0);
|
if(flags & OS_AccessFlag_Inherited)
|
||||||
|
{
|
||||||
|
security_attributes.bInheritHandle = 1;
|
||||||
|
}
|
||||||
|
HANDLE file = CreateFileW((WCHAR *)path16.str, access_flags, share_mode, &security_attributes, creation_disposition, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
if(file != INVALID_HANDLE_VALUE)
|
if(file != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
result.u64[0] = (U64)file;
|
result.u64[0] = (U64)file;
|
||||||
@@ -926,9 +931,17 @@ os_process_launch(OS_ProcessLaunchParams *params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: launch
|
//- rjf: launch
|
||||||
|
BOOL inherit_handles = 0;
|
||||||
STARTUPINFOW startup_info = {sizeof(startup_info)};
|
STARTUPINFOW startup_info = {sizeof(startup_info)};
|
||||||
|
if(!os_handle_match(params->stdout_file, os_handle_zero()))
|
||||||
|
{
|
||||||
|
HANDLE stdout_handle = (HANDLE)params->stdout_file.u64[0];
|
||||||
|
startup_info.hStdOutput = stdout_handle;
|
||||||
|
startup_info.dwFlags |= STARTF_USESTDHANDLES;
|
||||||
|
inherit_handles = 1;
|
||||||
|
}
|
||||||
PROCESS_INFORMATION process_info = {0};
|
PROCESS_INFORMATION process_info = {0};
|
||||||
if(CreateProcessW(0, (WCHAR*)cmd16.str, 0, 0, 0, creation_flags, use_null_env_arg ? 0 : (WCHAR*)env16.str, (WCHAR*)dir16.str, &startup_info, &process_info))
|
if(CreateProcessW(0, (WCHAR*)cmd16.str, 0, 0, inherit_handles, creation_flags, use_null_env_arg ? 0 : (WCHAR*)env16.str, (WCHAR*)dir16.str, &startup_info, &process_info))
|
||||||
{
|
{
|
||||||
result.u64[0] = (U64)process_info.hProcess;
|
result.u64[0] = (U64)process_info.hProcess;
|
||||||
CloseHandle(process_info.hThread);
|
CloseHandle(process_info.hThread);
|
||||||
|
|||||||
+60
-36
@@ -44,59 +44,83 @@ entry_point(CmdLine *cmdline)
|
|||||||
B32 good = 1;
|
B32 good = 1;
|
||||||
String8List out = {0};
|
String8List out = {0};
|
||||||
{
|
{
|
||||||
name = str8_lit("PDB -> RDI determinism");
|
name = str8_lit("pdb2rdi_determinism");
|
||||||
OS_HandleList processes = {0};
|
|
||||||
String8List rdi_paths = {0};
|
|
||||||
U64 num_repeats_per_pdb = 4;
|
U64 num_repeats_per_pdb = 4;
|
||||||
String8 pdb_paths[] =
|
String8 pdb_paths[] =
|
||||||
{
|
{
|
||||||
str8_lit_comp("odintest/test.pdb"),
|
str8_lit_comp("odintest/test.pdb"),
|
||||||
|
str8_lit_comp("mule_main.pdb"),
|
||||||
};
|
};
|
||||||
for EachElement(pdb_idx, pdb_paths)
|
for EachElement(pdb_idx, pdb_paths)
|
||||||
{
|
{
|
||||||
|
// rjf: unpack paths, make output directory
|
||||||
String8 pdb_path = path_normalized_from_string(arena, pdb_paths[pdb_idx]);
|
String8 pdb_path = path_normalized_from_string(arena, pdb_paths[pdb_idx]);
|
||||||
String8 pdb_folder = str8_chop_last_slash(pdb_path);
|
String8 pdb_folder = str8_chop_last_slash(pdb_path);
|
||||||
String8 repeat_folder = push_str8f(arena, "%S/pdb2rdi_determinism", pdb_folder);
|
String8 repeat_folder = push_str8f(arena, "%S/%S", pdb_folder, name);
|
||||||
os_make_directory(repeat_folder);
|
os_make_directory(repeat_folder);
|
||||||
for EachIndex(repeat_idx, num_repeats_per_pdb)
|
|
||||||
|
// rjf: generate all RDIs
|
||||||
|
String8List rdi_paths = {0};
|
||||||
{
|
{
|
||||||
String8 rdi_path = push_str8f(arena, "%S/repeat_%I64u.rdi", repeat_folder, repeat_idx);
|
OS_HandleList processes = {0};
|
||||||
str8_list_push(arena, &rdi_paths, rdi_path);
|
for EachIndex(repeat_idx, num_repeats_per_pdb)
|
||||||
os_handle_list_push(arena, &processes, os_cmd_line_launchf("rdi_from_pdb --pdb:%S --out:%S", pdb_path, rdi_path));
|
{
|
||||||
|
String8 rdi_path = push_str8f(arena, "%S/repeat_%I64u.rdi", repeat_folder, repeat_idx);
|
||||||
|
str8_list_push(arena, &rdi_paths, rdi_path);
|
||||||
|
os_handle_list_push(arena, &processes, os_cmd_line_launchf("rdi_from_pdb --pdb:%S --out:%S", pdb_path, rdi_path));
|
||||||
|
}
|
||||||
|
for(OS_HandleNode *n = processes.first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
os_process_join(n->v, max_U64);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
for(OS_HandleNode *n = processes.first; n != 0; n = n->next)
|
// rjf: generate all dumps
|
||||||
{
|
|
||||||
os_process_join(n->v, max_U64);
|
|
||||||
}
|
|
||||||
U64 hashes_count = rdi_paths.node_count;
|
|
||||||
U128 *hashes = push_array(arena, U128, hashes_count);
|
|
||||||
String8 *paths = push_array(arena, String8, hashes_count);
|
|
||||||
{
|
|
||||||
U64 idx = 0;
|
|
||||||
for(String8Node *n = rdi_paths.first; n != 0; n = n->next, idx += 1)
|
|
||||||
{
|
{
|
||||||
String8 path = n->string;
|
OS_HandleList processes = {0};
|
||||||
String8 data = os_data_from_file_path(arena, path);
|
for(String8Node *n = rdi_paths.first; n != 0; n = n->next)
|
||||||
hashes[idx] = hs_hash_from_data(data);
|
{
|
||||||
paths[idx] = path;
|
String8 rdi_path = n->string;
|
||||||
|
String8 dump_path = push_str8f(arena, "%S.dump", rdi_path);
|
||||||
|
os_handle_list_push(arena, &processes, os_cmd_line_launchf("rdi_dump %S > %S", rdi_path, dump_path));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
B32 matches = 1;
|
// rjf: gather all hashes/paths
|
||||||
for EachIndex(idx, hashes_count)
|
U64 hashes_count = rdi_paths.node_count;
|
||||||
{
|
U128 *hashes = push_array(arena, U128, hashes_count);
|
||||||
if(!u128_match(hashes[idx], hashes[0]))
|
String8 *paths = push_array(arena, String8, hashes_count);
|
||||||
{
|
{
|
||||||
matches = 0;
|
U64 idx = 0;
|
||||||
break;
|
for(String8Node *n = rdi_paths.first; n != 0; n = n->next, idx += 1)
|
||||||
|
{
|
||||||
|
String8 path = n->string;
|
||||||
|
String8 data = os_data_from_file_path(arena, path);
|
||||||
|
hashes[idx] = hs_hash_from_data(data);
|
||||||
|
paths[idx] = path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if(!matches)
|
// rjf: determine if all hashes match
|
||||||
{
|
B32 matches = 1;
|
||||||
good = 0;
|
|
||||||
for EachIndex(idx, hashes_count)
|
for EachIndex(idx, hashes_count)
|
||||||
{
|
{
|
||||||
str8_list_pushf(arena, &out, " [%I64u] (%S): 0x%I64x:%I64x\n", idx, paths[idx], hashes[idx].u64[0], hashes[idx].u64[1]);
|
if(!u128_match(hashes[idx], hashes[0]))
|
||||||
|
{
|
||||||
|
matches = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: output bad case info
|
||||||
|
if(!matches)
|
||||||
|
{
|
||||||
|
good = 0;
|
||||||
|
str8_list_pushf(arena, &out, " pdb[%I64u] \"%S\"\n", pdb_idx, pdb_path);
|
||||||
|
for EachIndex(idx, hashes_count)
|
||||||
|
{
|
||||||
|
str8_list_pushf(arena, &out, " rdi[%I64u] \"%S\": 0x%I64x:%I64x\n", idx, paths[idx], hashes[idx].u64[0], hashes[idx].u64[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,7 +128,7 @@ entry_point(CmdLine *cmdline)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- rjf: dump results
|
//- rjf: dump results
|
||||||
//
|
//
|
||||||
fprintf(stderr, "[%s] %.*s\n", good ? "." : "X", str8_varg(name));
|
fprintf(stderr, "[%s] \"%.*s\"\n", good ? "." : "X", str8_varg(name));
|
||||||
if(!good)
|
if(!good)
|
||||||
{
|
{
|
||||||
for(String8Node *n = out.first; n != 0; n = n->next)
|
for(String8Node *n = out.first; n != 0; n = n->next)
|
||||||
|
|||||||
Reference in New Issue
Block a user