mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
WIP DWARF line table conversion tester
This commit is contained in:
+105
-1
@@ -417,6 +417,7 @@ rb_thread_entry_point(void *p)
|
|||||||
OutputKind_RDI,
|
OutputKind_RDI,
|
||||||
OutputKind_Dump,
|
OutputKind_Dump,
|
||||||
OutputKind_Breakpad,
|
OutputKind_Breakpad,
|
||||||
|
OutputKind_VOff2Line,
|
||||||
OutputKind_COUNT
|
OutputKind_COUNT
|
||||||
}
|
}
|
||||||
OutputKind;
|
OutputKind;
|
||||||
@@ -431,6 +432,7 @@ rb_thread_entry_point(void *p)
|
|||||||
{str8_lit_comp("rdi"), str8_lit_comp("RAD Debug Info (.rdi) Conversion")},
|
{str8_lit_comp("rdi"), str8_lit_comp("RAD Debug Info (.rdi) Conversion")},
|
||||||
{str8_lit_comp("dump"), str8_lit_comp("Textual Dumping")},
|
{str8_lit_comp("dump"), str8_lit_comp("Textual Dumping")},
|
||||||
{str8_lit_comp("breakpad"), str8_lit_comp("Breakpad Debug Info Conversion")},
|
{str8_lit_comp("breakpad"), str8_lit_comp("Breakpad Debug Info Conversion")},
|
||||||
|
{str8_lit_comp("voff2line"), str8_lit_comp("Map virtual offset to a source line")},
|
||||||
};
|
};
|
||||||
OutputKind output_kind = OutputKind_Null;
|
OutputKind output_kind = OutputKind_Null;
|
||||||
String8 output_path = cmd_line_string(cmdline, str8_lit("out"));
|
String8 output_path = cmd_line_string(cmdline, str8_lit("out"));
|
||||||
@@ -534,6 +536,8 @@ rb_thread_entry_point(void *p)
|
|||||||
fprintf(stderr, "--breakpad Specifies that the utility should convert debug information\n");
|
fprintf(stderr, "--breakpad Specifies that the utility should convert debug information\n");
|
||||||
fprintf(stderr, " data to the textual Breakpad format.\n\n");
|
fprintf(stderr, " data to the textual Breakpad format.\n\n");
|
||||||
|
|
||||||
|
fprintf(stderr, "--VOff2Line Specifies that the utility should map virtual offset to source line.\n\n");
|
||||||
|
|
||||||
fprintf(stderr, "--out:<path> Specifies the path to which output data should be written. If\n");
|
fprintf(stderr, "--out:<path> Specifies the path to which output data should be written. If\n");
|
||||||
fprintf(stderr, " not specified, the utility will choose a fallback. If dumping\n");
|
fprintf(stderr, " not specified, the utility will choose a fallback. If dumping\n");
|
||||||
fprintf(stderr, " textual contents, the utility will write to `stdout`. If\n");
|
fprintf(stderr, " textual contents, the utility will write to `stdout`. If\n");
|
||||||
@@ -587,7 +591,7 @@ rb_thread_entry_point(void *p)
|
|||||||
{
|
{
|
||||||
fprintf(stderr, "All input files specified on the command line will be dumped. The following\n");
|
fprintf(stderr, "All input files specified on the command line will be dumped. The following\n");
|
||||||
fprintf(stderr, "formats are currently supported: PE, COFF, RDI, and ELF\n\n");
|
fprintf(stderr, "formats are currently supported: PE, COFF, RDI, and ELF\n\n");
|
||||||
}
|
}break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: unpack subset flags
|
//- rjf: unpack subset flags
|
||||||
@@ -1276,6 +1280,106 @@ rb_thread_entry_point(void *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
|
case OutputKind_VOff2Line:
|
||||||
|
{
|
||||||
|
if(lane_idx() != 0) { break; }
|
||||||
|
|
||||||
|
if(cmdline->inputs.node_count == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ARGUMENTS\n\n");
|
||||||
|
fprintf(stderr, "--voff:OFFSET Map specified virtual offset to a source line.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cmdline->inputs.node_count > 1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: too many input files!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!cmd_line_has_argument(cmdline, str8_lit("voff"))) {
|
||||||
|
fprintf(stderr, "ERROR: missing -voff\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
String8 voff_str = cmd_line_string(cmdline, str8_lit("voff"));
|
||||||
|
if(voff_str.size == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: missing argument for -voff\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
U64 voff = 0;
|
||||||
|
if(!try_u64_from_str8_c_rules(voff_str, &voff))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: invalid argument for -voff\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_File *f = input_files.first->v;
|
||||||
|
if(f->format != RB_FileFormat_RDI)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: input file must be RDI.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RDI_Parsed rdi = {0};
|
||||||
|
RDI_ParseStatus rdi_parse_status = rdi_parse(f->data.str, f->data.size, &rdi);
|
||||||
|
if(rdi_parse_status != RDI_ParseStatus_Good)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: failed to parse RDI with code %d\n", rdi_parse_status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RDI_Line line = rdi_line_from_voff(&rdi, voff);
|
||||||
|
if(line.file_idx == 0 || line.line_num == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: failed to find mapping for virtual offset 0x%llx.\n", voff);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RDI_SourceFile *src_file = rdi_element_from_name_idx(&rdi, SourceFiles, line.file_idx);
|
||||||
|
if(src_file == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: failed to find source file with index %u.\n", line.file_idx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
|
||||||
|
// format inline site stack
|
||||||
|
{
|
||||||
|
RDI_Scope *voff_scope = rdi_scope_from_voff(&rdi, voff);
|
||||||
|
for(RDI_Scope *scope = voff_scope, *null_scope = rdi_element_from_name_idx(&rdi, Scopes, 0); scope != 0 && scope != null_scope; scope = rdi_parent_from_scope(&rdi, scope))
|
||||||
|
{
|
||||||
|
RDI_InlineSite *inline_site = rdi_inline_site_from_scope(&rdi, scope);
|
||||||
|
RDI_InlineSite *null_inline_site = rdi_element_from_name_idx(&rdi, InlineSites, 0);
|
||||||
|
if(inline_site && inline_site != null_inline_site)
|
||||||
|
{
|
||||||
|
RDI_LineTable *inline_line_table = rdi_element_from_name_idx(&rdi, LineTables, inline_site->line_table_idx);
|
||||||
|
RDI_LineTable *null_inline_line_table = rdi_element_from_name_idx(&rdi, LineTables, 0);
|
||||||
|
if(inline_line_table && inline_line_table != null_inline_line_table)
|
||||||
|
{
|
||||||
|
String8 inline_name = str8_from_rdi_string_idx(&rdi, inline_site->name_string_idx);
|
||||||
|
RDI_Line inline_line = rdi_line_from_line_table_voff(&rdi, inline_line_table, voff);
|
||||||
|
RDI_SourceFile *inline_src_file = rdi_element_from_name_idx(&rdi, SourceFiles, inline_line.file_idx);
|
||||||
|
RDI_SourceFile *null_inline_src_file = rdi_element_from_name_idx(&rdi, SourceFiles, 0);
|
||||||
|
if(inline_src_file && inline_src_file != null_inline_src_file)
|
||||||
|
{
|
||||||
|
String8 path = str8_from_rdi_path_node_idx(scratch.arena, &rdi, PathStyle_SystemAbsolute, src_file->file_path_node_idx);
|
||||||
|
fprintf(stdout, "[inlined] %.*s %.*s:%u\n", str8_varg(inline_name), str8_varg(path), inline_line.line_num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String8 path = str8_from_rdi_path_node_idx(scratch.arena, &rdi, PathStyle_SystemAbsolute, src_file->file_path_node_idx);
|
||||||
|
fprintf(stdout, "%.*s:%u\n", str8_varg(path), line.line_num);
|
||||||
|
|
||||||
|
scratch_end(scratch);
|
||||||
|
}break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|||||||
@@ -30,6 +30,24 @@ str8_from_rdi_string_idx(RDI_Parsed *rdi, U32 idx)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal String8
|
||||||
|
str8_from_rdi_path_node_idx(Arena *arena, RDI_Parsed *rdi, PathStyle path_style, U32 path_node_idx)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
String8List path_parts = {0};
|
||||||
|
for(RDI_FilePathNode *fpn = rdi_element_from_name_idx(rdi, FilePathNodes, path_node_idx);
|
||||||
|
fpn != rdi_element_from_name_idx(rdi, FilePathNodes, 0);
|
||||||
|
fpn = rdi_element_from_name_idx(rdi, FilePathNodes, fpn->parent_path_node))
|
||||||
|
{
|
||||||
|
String8 path_part = {0};
|
||||||
|
path_part.str = rdi_string_from_idx(rdi, fpn->name_string_idx, &path_part.size);
|
||||||
|
str8_list_push_front(scratch.arena, &path_parts, path_part);
|
||||||
|
}
|
||||||
|
String8 path = str8_path_list_join_by_style(arena, &path_parts, path_style);
|
||||||
|
scratch_end(scratch);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: String <=> Enum
|
//~ rjf: String <=> Enum
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ internal Arch arch_from_rdi_arch(RDI_Arch arch);
|
|||||||
//~ rjf: Lookup Helpers
|
//~ rjf: Lookup Helpers
|
||||||
|
|
||||||
internal String8 str8_from_rdi_string_idx(RDI_Parsed *rdi, U32 idx);
|
internal String8 str8_from_rdi_string_idx(RDI_Parsed *rdi, U32 idx);
|
||||||
|
internal String8 str8_from_rdi_path_node_idx(Arena *arean, RDI_Parsed *rdi, PathStyle path_style, U32 path_node_idx);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: String <=> Enum
|
//~ rjf: String <=> Enum
|
||||||
|
|||||||
+97
-32
@@ -91,25 +91,73 @@ t_run(T_Run run)
|
|||||||
return ctx.result;
|
return ctx.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal B32
|
internal String8
|
||||||
t_invoke(String8 exe_path, String8 cmdline, U64 timeout)
|
t_radbin_path(void)
|
||||||
{
|
{
|
||||||
Temp scratch = scratch_begin(0,0);
|
local_persist String8 path = {0};
|
||||||
|
if (path.size == 0) {
|
||||||
|
local_persist U8 buffer[4096];
|
||||||
|
ArenaParams params = { .reserve_size = sizeof(buffer), .commit_size = sizeof(buffer), .optional_backing_buffer = buffer };
|
||||||
|
Arena *arena = arena_alloc_(¶ms);
|
||||||
|
#if OS_WINDOWS
|
||||||
|
path = os_full_path_from_path(arena, str8_lit("radbin.exe"));
|
||||||
|
#else
|
||||||
|
path = os_full_path_from_path(arena, str8_lit("radbin"));
|
||||||
|
#endif
|
||||||
|
AssertAlways(path.size);
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String8
|
||||||
|
t_radlink_path(void)
|
||||||
|
{
|
||||||
|
local_persist String8 path = {0};
|
||||||
|
if (path.size == 0) {
|
||||||
|
local_persist U8 buffer[4096];
|
||||||
|
ArenaParams params = { .reserve_size = sizeof(buffer), .commit_size = sizeof(buffer), .optional_backing_buffer = buffer };
|
||||||
|
Arena *arena = arena_alloc_(¶ms);
|
||||||
|
#if OS_WINDOWS
|
||||||
|
path = os_full_path_from_path(arena, str8_lit("radlink.exe"));
|
||||||
|
#else
|
||||||
|
path = os_full_path_from_path(arena, str8_lit("radlink"));
|
||||||
|
#endif
|
||||||
|
AssertAlways(path.size);
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
t_invoke_(String8 exe_path, String8 cmdline, U64 timeout, Arena *output_arena, String8 *output_out)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(&output_arena,1);
|
||||||
|
|
||||||
B32 is_ok = 0;
|
B32 is_ok = 0;
|
||||||
|
|
||||||
OS_Handle output_redirect = {0};
|
B32 capture_output = output_out || g_redirect_stdout;
|
||||||
if (g_redirect_stdout) {
|
|
||||||
output_redirect = os_file_open(OS_AccessFlag_Append|OS_AccessFlag_ShareRead|OS_AccessFlag_ShareWrite|OS_AccessFlag_Inherited, g_stdout_file_name);
|
g_last_exit_code = -1;
|
||||||
|
|
||||||
|
OS_Handle 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 = (OS_Handle){ .u64[0] = (U64)read_pipe };
|
||||||
|
write_pipe_handle = (OS_Handle){ .u64[0] = (U64)write_pipe };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build Launch Options
|
// Build Launch Options
|
||||||
OS_ProcessLaunchParams launch_opts = { .path = g_wdir, .inherit_env = 1, .stdout_file = output_redirect, .stderr_file = output_redirect };
|
OS_ProcessLaunchParams launch_opts = {
|
||||||
str8_list_push(scratch.arena, &launch_opts.cmd_line, exe_path);
|
.path = g_wdir,
|
||||||
{
|
.inherit_env = 1,
|
||||||
String8List parsed_cmdline = lnk_arg_list_parse_windows_rules(scratch.arena, cmdline);
|
.stdout_file = write_pipe_handle,
|
||||||
str8_list_concat_in_place(&launch_opts.cmd_line, &parsed_cmdline);
|
.stderr_file = write_pipe_handle,
|
||||||
}
|
.cmd_line = lnk_arg_list_parse_windows_rules(scratch.arena, cmdline),
|
||||||
|
};
|
||||||
|
str8_list_push_front(scratch.arena, &launch_opts.cmd_line, exe_path);
|
||||||
|
|
||||||
if (g_verbose) {
|
if (g_verbose) {
|
||||||
String8 full_cmd_line = str8_list_join(scratch.arena, &launch_opts.cmd_line, &(StringJoin){ .sep = str8_lit(" ") });
|
String8 full_cmd_line = str8_list_join(scratch.arena, &launch_opts.cmd_line, &(StringJoin){ .sep = str8_lit(" ") });
|
||||||
@@ -117,37 +165,54 @@ t_invoke(String8 exe_path, String8 cmdline, U64 timeout)
|
|||||||
fprintf(stdout, "Working Dir: %.*s\n", str8_varg(g_wdir));
|
fprintf(stdout, "Working Dir: %.*s\n", str8_varg(g_wdir));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoke Exe
|
// invoke exe
|
||||||
int exit_code = -1;
|
|
||||||
{
|
|
||||||
OS_Handle process_handle = os_process_launch(&launch_opts);
|
OS_Handle process_handle = os_process_launch(&launch_opts);
|
||||||
if (!os_handle_match(process_handle, os_handle_zero())) {
|
|
||||||
|
// close handle so last to ReadFile does not block
|
||||||
|
os_file_close(write_pipe_handle);
|
||||||
|
|
||||||
|
if ( ! os_handle_match(process_handle, os_handle_zero())) {
|
||||||
|
if (capture_output) {
|
||||||
|
// capture process output
|
||||||
|
String8List output = {0};
|
||||||
|
for (;;) {
|
||||||
|
String8 string = os_file_read_cstring(scratch.arena, read_pipe_handle, 0);
|
||||||
|
if (string.size == 0) { break; }
|
||||||
|
str8_list_push(scratch.arena, &output, string);
|
||||||
|
}
|
||||||
|
os_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) {
|
||||||
|
os_write_data_list_to_file_path(g_stdout_file_name, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
U64 exit_code_u64 = 0;
|
U64 exit_code_u64 = 0;
|
||||||
is_ok = os_process_join(process_handle, timeout, &exit_code_u64);
|
if (os_process_join(process_handle, timeout, &exit_code_u64)) {
|
||||||
exit_code = (int)exit_code_u64;
|
g_last_exit_code = (int)exit_code_u64;
|
||||||
if (!is_ok) {
|
is_ok = 1;
|
||||||
|
} else {
|
||||||
os_process_kill(process_handle);
|
os_process_kill(process_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
os_process_detach(process_handle);
|
os_process_detach(process_handle);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// close handles
|
|
||||||
if (g_redirect_stdout) {
|
|
||||||
os_file_close(output_redirect);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update global exit code
|
|
||||||
if (is_ok) {
|
|
||||||
g_last_exit_code = exit_code;
|
|
||||||
} else {
|
|
||||||
g_last_exit_code = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
return is_ok;
|
return is_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
t_invoke(String8 exe_path, String8 cmdline, U64 timeout)
|
||||||
|
{
|
||||||
|
return t_invoke_(exe_path, cmdline, timeout, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
internal int
|
internal int
|
||||||
t_test_is_before(void *raw_a, void *raw_b)
|
t_test_is_before(void *raw_a, void *raw_b)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ d2r_rdi_from_dwarf_writer(Arena *arena, DW_Writer *writer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Assert(t_write_file(str8_lit("a.obj"), raw_coff));
|
Assert(t_write_file(str8_lit("a.obj"), raw_coff));
|
||||||
t_invoke(str8_lit("radlink.exe"), str8_lit("/subsystem:console /out:a.exe /entry:main /DEBUG:FULL /opt:noref /opt:noicf a.obj"), max_U64);
|
t_invoke(t_radlink_path(), str8_lit("/subsystem:console /out:a.exe /entry:main /DEBUG:FULL /opt:noref /opt:noicf a.obj"), max_U64);
|
||||||
Assert(g_last_exit_code == 0);
|
Assert(g_last_exit_code == 0);
|
||||||
String8 exe = t_read_file(scratch.arena, str8_lit("a.exe"));
|
String8 exe = t_read_file(scratch.arena, str8_lit("a.exe"));
|
||||||
Assert(exe.size > 0);
|
Assert(exe.size > 0);
|
||||||
@@ -28,7 +28,7 @@ d2r_rdi_from_dwarf_writer(Arena *arena, DW_Writer *writer)
|
|||||||
B32 was_pdb_deleted = os_delete_file_at_path(t_make_file_path(scratch.arena, str8_lit("a.pdb")));
|
B32 was_pdb_deleted = os_delete_file_at_path(t_make_file_path(scratch.arena, str8_lit("a.pdb")));
|
||||||
Assert(was_pdb_deleted);
|
Assert(was_pdb_deleted);
|
||||||
|
|
||||||
t_invoke(str8_lit("radbin.exe"), str8_lit("-rdi a.exe"), max_U64);
|
t_invoke_(t_radbin_path(), str8_lit("-rdi a.exe -out:a.rdi"), max_U64, 0, 0);
|
||||||
Assert(g_last_exit_code == 0);
|
Assert(g_last_exit_code == 0);
|
||||||
|
|
||||||
String8 raw_rdi = t_read_file(arena, str8_lit("a.rdi"));
|
String8 raw_rdi = t_read_file(arena, str8_lit("a.rdi"));
|
||||||
@@ -222,6 +222,60 @@ T_BeginTest(d2r_types)
|
|||||||
}
|
}
|
||||||
T_EndTest;
|
T_EndTest;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
T_BeginTest(d2r_line_table)
|
||||||
|
{
|
||||||
|
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_name = str8_lit("test.c");
|
||||||
|
|
||||||
|
DW_WriterFile *file = dw_writer_new_file(writer, comp_name);
|
||||||
|
file->md5 = *(U128 *)&(U8[]){ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc };
|
||||||
|
|
||||||
|
struct {
|
||||||
|
DW_WriterFile *file; U64 ln; U64 line_size; U64 voff;
|
||||||
|
} test_table[] = {
|
||||||
|
{ file, 6, 1 },
|
||||||
|
{ file, 4, 2 },
|
||||||
|
{ file, 2, 3 },
|
||||||
|
{ file, 1, 4 },
|
||||||
|
{ file, 8, 5 },
|
||||||
|
};
|
||||||
|
|
||||||
|
U64 exe_base = coff_default_exe_base_from_machine(COFF_MachineType_X64);
|
||||||
|
U64 voff = 0x1000;
|
||||||
|
for EachElement(i, test_table) {
|
||||||
|
test_table[i].voff = voff;
|
||||||
|
dw_writer_line_emit(writer, test_table[i].file, test_table[i].ln, 0, exe_base + voff);
|
||||||
|
voff += test_table[i].line_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
dw_writer_tag_begin(writer, DW_TagKind_CompileUnit);
|
||||||
|
dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
|
||||||
|
dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, comp_dir);
|
||||||
|
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name);
|
||||||
|
dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, exe_base);
|
||||||
|
dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, exe_base + voff);
|
||||||
|
dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0);
|
||||||
|
dw_writer_tag_end(writer);
|
||||||
|
|
||||||
|
d2r_rdi_from_dwarf_writer(scratch.arena, writer);
|
||||||
|
|
||||||
|
for EachElement(i, test_table) {
|
||||||
|
for EachIndex(k, test_table[i].line_size) {
|
||||||
|
String8 cmd_line = str8f(scratch.arena, "-voff2line -voff:%llx, a.rdi", test_table[i].voff + k);
|
||||||
|
String8 output = {0};
|
||||||
|
t_invoke_(str8_lit("radbin.exe"), cmd_line, max_U64, scratch.arena, &output);
|
||||||
|
T_Ok(g_last_exit_code == 0);
|
||||||
|
T_MatchLinef(&output, "%S:/%llu", test_table[i].file->path, test_table[i].ln);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dw_writer_end(&writer);
|
||||||
|
}
|
||||||
|
T_EndTest;
|
||||||
|
#endif
|
||||||
|
|
||||||
T_BeginTest(d2r_general)
|
T_BeginTest(d2r_general)
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
|||||||
Reference in New Issue
Block a user