From 5f851ad1b0fc18dda669643e0261c7cbd2a3b3f3 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 21 May 2026 14:04:37 -0700 Subject: [PATCH] simplify testing ipc driving stuff in raddbg layer; put in formal eval/line-from-vaddr commands --- project.raddbg | 1 + src/dbg_engine/dbg_engine_user.c | 4 +- .../eval_visualization_core.c | 24 + .../eval_visualization_core.h | 3 + src/lib_rdi_make/rdi_make.c | 2 +- src/lib_rdi_make/rdi_make.h | 2 +- src/radbin/radbin.c | 127 +---- src/radbin/radbin_main.c | 4 - src/raddbg/generated/raddbg.meta.c | 14 +- src/raddbg/generated/raddbg.meta.h | 6 +- src/raddbg/raddbg.mdesk | 10 +- src/raddbg/raddbg_core.c | 478 ++++-------------- src/raddbg/raddbg_core.h | 21 - src/raddbg/raddbg_main.c | 4 - src/raddbg/raddbg_views.c | 2 +- src/rdi_make/rdi_make_local.c | 6 +- src/torture/torture_dbg.c | 420 ++++++++------- 17 files changed, 434 insertions(+), 694 deletions(-) diff --git a/project.raddbg b/project.raddbg index 4019e3e2..e3cfcebd 100644 --- a/project.raddbg +++ b/project.raddbg @@ -7,6 +7,7 @@ target: working_directory: build arguments: "--user:raddbg_test.user --project:raddbg_test.project" enabled: 1 + debug_subprocesses: 0 } target: { diff --git a/src/dbg_engine/dbg_engine_user.c b/src/dbg_engine/dbg_engine_user.c index c520e007..7e3d2661 100644 --- a/src/dbg_engine/dbg_engine_user.c +++ b/src/dbg_engine/dbg_engine_user.c @@ -994,7 +994,7 @@ d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key, override_n = override_n->next) { String8 file_path = override_n->string; - String8 file_path_normalized = rdim_normalize_path_str8(scratch.arena, file_path); + String8 file_path_normalized = rdim_normalized_from_path(scratch.arena, file_path); // rjf: binary -> rdi RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); @@ -1087,7 +1087,7 @@ d_lines_array_from_file_path_line_range(Arena *arena, String8 file_path, Rng1S64 override_n = override_n->next) { String8 file_path = override_n->string; - String8 file_path_normalized = rdim_normalize_path_str8(scratch.arena, file_path); + String8 file_path_normalized = rdim_normalized_from_path(scratch.arena, file_path); for EachIndex(idx, dbgi_keys.count) { Access *access = access_open(); diff --git a/src/eval_visualization/eval_visualization_core.c b/src/eval_visualization/eval_visualization_core.c index 3b0794b5..58471d35 100644 --- a/src/eval_visualization/eval_visualization_core.c +++ b/src/eval_visualization/eval_visualization_core.c @@ -2294,3 +2294,27 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string) return result; } + +//- rjf: eval -> string path + +internal String8 +ev_value_string_from_eval(Arena *arena, EV_StringParams *params, E_Eval eval, U64 cap) +{ + Temp scratch = scratch_begin(&arena, 1); + String8List strs = {0}; + EV_StringIter *iter = ev_string_iter_begin(scratch.arena, eval, params); + for(String8 string = {0}; ev_string_iter_next(scratch.arena, iter, &string);) + { + if(strs.total_size + string.size > cap) + { + String8 allowed_string = str8_chop(string, ((strs.total_size + string.size) - cap) + 3); + str8_list_push(scratch.arena, &strs, allowed_string); + str8_list_push(scratch.arena, &strs, str8_lit("...")); + break; + } + str8_list_push(scratch.arena, &strs, string); + } + String8 result = str8_list_join(arena, &strs, 0); + scratch_end(scratch); + return result; +} diff --git a/src/eval_visualization/eval_visualization_core.h b/src/eval_visualization/eval_visualization_core.h index 4a7067af..301ae947 100644 --- a/src/eval_visualization/eval_visualization_core.h +++ b/src/eval_visualization/eval_visualization_core.h @@ -383,4 +383,7 @@ internal String8 ev_escaped_from_raw_string(Arena *arena, String8 raw); internal EV_StringIter *ev_string_iter_begin(Arena *arena, E_Eval eval, EV_StringParams *params); internal B32 ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string); +//- rjf: eval -> string path +internal String8 ev_value_string_from_eval(Arena *arena, EV_StringParams *params, E_Eval eval, U64 cap); + #endif // EVAL_VISUALIZATION_CORE_H diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index ee96ff32..5f1e10b6 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -256,7 +256,7 @@ rdim_lower_from_str8(RDIM_Arena *arena, RDIM_String8 string) } RDI_PROC RDIM_String8 -rdim_normalize_path_str8(RDIM_Arena *arena, RDIM_String8 path) +rdim_normalized_from_path(RDIM_Arena *arena, RDIM_String8 path) { RDIM_String8 result = rdim_lower_from_str8(arena, path); for(RDI_U64 i = 0; i < result.RDIM_String8_SizeMember; i += 1) diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index 52c24443..66d6c826 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -1333,7 +1333,7 @@ RDI_PROC RDI_S32 rdim_str8_match(RDIM_String8 a, RDIM_String8 b, RDIM_StringMatc #define rdim_str8_struct(S) rdim_str8((RDI_U8*)(S), sizeof(*(S))) #define rdim_str8_struct_array(S, C) rdim_str8((RDI_U8*)(S), sizeof(*(S)) * (C)) RDI_PROC RDIM_String8 rdim_lower_from_str8(RDIM_Arena *arena, RDIM_String8 string); -RDI_PROC RDIM_String8 rdim_normalize_path_str8(RDIM_Arena *arena, RDIM_String8 path); +RDI_PROC RDIM_String8 rdim_normalized_from_path(RDIM_Arena *arena, RDIM_String8 path); //- rjf: string lists RDI_PROC void rdim_str8_list_push(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 string); diff --git a/src/radbin/radbin.c b/src/radbin/radbin.c index 74e7177b..edfc12a4 100644 --- a/src/radbin/radbin.c +++ b/src/radbin/radbin.c @@ -720,89 +720,7 @@ rb_thread_entry_point(void *p) else if(elf_w_dwarf) { log_infof("ELFs specified; converting DWARF data to RDI\n"); } // rjf: convert - D2R_ConvertParams convert_params = {0}; - { - B32 got_exe = 0; - B32 got_dbg = 0; - if(!got_exe && !got_dbg) - { - for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_PE].first; n != 0; n = n->next) - { - if(n->v->format_flags & RB_FileFormatFlag_HasDWARF) - { - got_exe = 1; - got_dbg = 1; - convert_params.dbg_name = n->v->path; - convert_params.dbg_data = n->v->data; - convert_params.exe_name = n->v->path; - convert_params.exe_data = n->v->data; - convert_params.exe_kind = ExecutableImageKind_CoffPe; - break; - } - } - } - if(!got_exe) - { - for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF32].first; n != 0; n = n->next) - { - got_exe = 1; - convert_params.exe_name = n->v->path; - convert_params.exe_data = n->v->data; - convert_params.exe_kind = ExecutableImageKind_Elf32; - if(!(n->v->format_flags & RB_FileFormatFlag_HasDWARF)) - { - break; - } - } - } - if(!got_exe) - { - for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF64].first; n != 0; n = n->next) - { - got_exe = 1; - convert_params.exe_name = n->v->path; - convert_params.exe_data = n->v->data; - convert_params.exe_kind = ExecutableImageKind_Elf64; - if(!(n->v->format_flags & RB_FileFormatFlag_HasDWARF)) - { - break; - } - } - } - if(!got_dbg) - { - for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF32].first; n != 0; n = n->next) - { - if(n->v->format_flags & RB_FileFormatFlag_HasDWARF) - { - got_dbg = 1; - convert_params.dbg_name = n->v->path; - convert_params.dbg_data = n->v->data; - break; - } - } - } - if(!got_dbg) - { - for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF64].first; n != 0; n = n->next) - { - if(n->v->format_flags & RB_FileFormatFlag_HasDWARF) - { - got_dbg = 1; - convert_params.dbg_name = n->v->path; - convert_params.dbg_data = n->v->data; - break; - } - } - } - convert_params.subset_flags = subset_flags; - convert_params.deterministic = cmd_line_has_flag(cmdline, str8_lit("deterministic")); - convert_params.is_parse_relaxed = 1; // TODO: switch - } -#if DWARF_2 - - // rjf: convert [2] - D2R2_ConvertParams convert_params_2 = {0}; + D2R2_ConvertParams convert_params = {0}; { B32 got_exe = 0; B32 got_dbg = 0; @@ -892,11 +810,11 @@ rb_thread_entry_point(void *p) String8 raw_sections = str8_substr(exe_data, pe.section_table_range); COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(raw_sections, 0, sizeof(COFF_SectionHeader) * pe.section_count); String8 string_table = str8_substr(exe_data, pe.string_table_range); - convert_params_2.arch = pe.arch; - convert_params_2.base_vaddr = pe.image_base; - convert_params_2.raw = dw_input_from_coff_section_table(scratch.arena, exe_data, string_table, pe.section_count, section_table); - convert_params_2.path_style = PathStyle_WindowsAbsolute; - convert_params_2.binary_sections = c2r_rdi_binary_sections_from_coff_sections(arena, exe_data, string_table, pe.section_count, section_table); + convert_params.arch = pe.arch; + convert_params.base_vaddr = pe.image_base; + convert_params.raw = dw_input_from_coff_section_table(scratch.arena, exe_data, string_table, pe.section_count, section_table); + convert_params.path_style = PathStyle_WindowsAbsolute; + convert_params.binary_sections = c2r_rdi_binary_sections_from_coff_sections(arena, exe_data, string_table, pe.section_count, section_table); scratch_end(scratch); }break; case ExecutableImageKind_Elf32: @@ -904,23 +822,20 @@ rb_thread_entry_point(void *p) { Temp scratch = scratch_begin(&arena, 1); ELF_Bin bin = elf_bin_from_data(scratch.arena, dbg_data); - convert_params_2.arch = arch_from_elf_machine(bin.hdr.e_machine); - convert_params_2.base_vaddr = elf_base_addr_from_bin(&bin); - convert_params_2.raw = dw_input_from_elf_bin(scratch.arena, dbg_data, &bin); - convert_params_2.path_style = PathStyle_UnixAbsolute; - convert_params_2.binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, dbg_data, &bin, &bin.shdrs); + convert_params.arch = arch_from_elf_machine(bin.hdr.e_machine); + convert_params.base_vaddr = elf_base_addr_from_bin(&bin); + convert_params.raw = dw_input_from_elf_bin(scratch.arena, dbg_data, &bin); + convert_params.path_style = PathStyle_UnixAbsolute; + convert_params.binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, dbg_data, &bin, &bin.shdrs); scratch_end(scratch); }break; } - convert_params_2.exe_name = exe_name; - convert_params_2.exe_data = exe_data; - convert_params_2.subset_flags = subset_flags; - convert_params_2.deterministic = cmd_line_has_flag(cmdline, str8_lit("deterministic")); + convert_params.exe_name = exe_name; + convert_params.exe_data = exe_data; + convert_params.subset_flags = subset_flags; + convert_params.deterministic = cmd_line_has_flag(cmdline, str8_lit("deterministic")); } - ProfScope("convert [2]") dwarf_bake_params_2 = d2r2_convert(arena, &convert_params_2); -#else - ProfScope("convert") dwarf_bake_params = d2r_convert(arena, &convert_params); -#endif + ProfScope("convert") dwarf_bake_params = d2r2_convert(arena, &convert_params); } //- rjf: PDB inputs => PDB -> RDI conversion @@ -995,11 +910,7 @@ rb_thread_entry_point(void *p) { bake_params = push_array(arena, RDIM_BakeParams, 1); rdim_bake_params_concat_in_place(bake_params, &pdb_bake_params); -#if DWARF_2 - rdim_bake_params_concat_in_place(bake_params, &dwarf_bake_params_2); -#else rdim_bake_params_concat_in_place(bake_params, &dwarf_bake_params); -#endif for EachNode(n, RDIM_BakeParamsNode, first_rdi_bake_params) { rdim_bake_params_concat_in_place(bake_params, &n->v); @@ -1334,14 +1245,14 @@ rb_thread_entry_point(void *p) PathStyle path_style = PathStyle_SystemAbsolute; if (str8_match_wildcard(top_part, str8_lit("?:"), 0)) { path_style = PathStyle_WindowsAbsolute; } else if(str8_match_wildcard(top_part, str8_lit("/*"), 0)) { path_style = PathStyle_UnixAbsolute; } - + String8 path = str8_from_rdi_path_node_idx(scratch.arena, rdi, path_style, src_file->file_path_node_idx); str8_list_pushf(arena, &output_blobs, "[inlined] %S %S:%u\n", inline_name, path, inline_line.line_num); } } } } - + // TODO: remove 'path_style' from the str8_from_rdi_path_node_idx and detect // path style based on the top node [c:|d:] -> windows, / -> unix String8 top_part = {0}; @@ -1357,7 +1268,7 @@ rb_thread_entry_point(void *p) PathStyle path_style = PathStyle_SystemAbsolute; if (str8_match_wildcard(top_part, str8_lit("?:"), 0)) { path_style = PathStyle_WindowsAbsolute; } else if(str8_match_wildcard(top_part, str8_lit("/*"), 0)) { path_style = PathStyle_UnixAbsolute; } - + String8 path = str8_from_rdi_path_node_idx(scratch.arena, rdi, path_style, src_file->file_path_node_idx); str8_list_pushf(arena, &output_blobs, "%S:%u\n", path, line.line_num); scratch_end(scratch); diff --git a/src/radbin/radbin_main.c b/src/radbin/radbin_main.c index 816544f6..fd1b2ad1 100644 --- a/src/radbin/radbin_main.c +++ b/src/radbin/radbin_main.c @@ -14,7 +14,6 @@ #include "base/base_inc.h" #include "x64/x64.h" #include "linker/hash_table.h" -#include "linker/lf_hash_table.h" #include "linker/base_ext/base_bit_array.h" #include "rdi/rdi_local.h" #include "rdi_make/rdi_make_local.h" @@ -36,7 +35,6 @@ #include "rdi_from_coff/rdi_from_coff.h" #include "rdi_from_elf/rdi_from_elf.h" #include "rdi_from_pdb/rdi_from_pdb.h" -#include "rdi_from_dwarf/rdi_from_dwarf.h" #include "rdi_from_dwarf/rdi_from_dwarf_2.h" #include "radbin/radbin.h" @@ -44,7 +42,6 @@ #include "base/base_inc.c" #include "x64/x64.c" #include "linker/hash_table.c" -#include "linker/lf_hash_table.c" #include "linker/base_ext/base_bit_array.c" #include "rdi/rdi_local.c" #include "rdi_make/rdi_make_local.c" @@ -66,7 +63,6 @@ #include "rdi_from_coff/rdi_from_coff.c" #include "rdi_from_elf/rdi_from_elf.c" #include "rdi_from_pdb/rdi_from_pdb.c" -#include "rdi_from_dwarf/rdi_from_dwarf.c" #include "rdi_from_dwarf/rdi_from_dwarf_2.c" #include "radbin/radbin.c" diff --git a/src/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index 5945b106..03b8a348 100644 --- a/src/raddbg/generated/raddbg.meta.c +++ b/src/raddbg/generated/raddbg.meta.c @@ -62,7 +62,7 @@ str8_lit_comp(""), str8_lit_comp(""), }; -RD_VocabInfo rd_vocab_info_table[361] = +RD_VocabInfo rd_vocab_info_table[363] = { {str8_lit_comp("type_view"), str8_lit_comp("type_views"), str8_lit_comp("Type View"), str8_lit_comp("Type Views"), RD_IconKind_Binoculars}, {str8_lit_comp("file_path_map"), str8_lit_comp("file_path_maps"), str8_lit_comp("File Path Map"), str8_lit_comp("File Path Maps"), RD_IconKind_FileOutline}, @@ -214,6 +214,9 @@ RD_VocabInfo rd_vocab_info_table[361] = {str8_lit_comp("open_palette"), str8_lit_comp(""), str8_lit_comp("Open Palette"), str8_lit_comp(""), RD_IconKind_List}, {str8_lit_comp("run_command"), str8_lit_comp(""), str8_lit_comp("Run Command"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("run_ext_driver_text_command"), str8_lit_comp(""), str8_lit_comp("Run External Driver Text Command"), str8_lit_comp(""), RD_IconKind_Null}, +{str8_lit_comp("state"), str8_lit_comp(""), str8_lit_comp("State"), str8_lit_comp(""), RD_IconKind_Null}, +{str8_lit_comp("eval"), str8_lit_comp(""), str8_lit_comp("Eval"), str8_lit_comp(""), RD_IconKind_Null}, +{str8_lit_comp("line_from_vaddr"), str8_lit_comp(""), str8_lit_comp("Line From Virtual Address"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("wm_event"), str8_lit_comp(""), str8_lit_comp("OS Event"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("select_thread"), str8_lit_comp(""), str8_lit_comp("Select Thread"), str8_lit_comp(""), RD_IconKind_Thread}, {str8_lit_comp("select_unwind"), str8_lit_comp(""), str8_lit_comp("Select Unwind"), str8_lit_comp(""), RD_IconKind_Null}, @@ -365,7 +368,6 @@ RD_VocabInfo rd_vocab_info_table[361] = {str8_lit_comp("enable_breakpoint"), str8_lit_comp(""), str8_lit_comp("Enable Breakpoint"), str8_lit_comp(""), RD_IconKind_CheckFilled}, {str8_lit_comp("disable_breakpoint"), str8_lit_comp(""), str8_lit_comp("Disable Breakpoint"), str8_lit_comp(""), RD_IconKind_CheckHollow}, {str8_lit_comp("clear_breakpoints"), str8_lit_comp(""), str8_lit_comp("Clear Breakpoints"), str8_lit_comp(""), RD_IconKind_Trash}, -{str8_lit_comp("list_breakpoints"), str8_lit_comp(""), str8_lit_comp("List Breakpoints"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("clear_output"), str8_lit_comp(""), str8_lit_comp("Clear Output"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("add_watch_pin"), str8_lit_comp(""), str8_lit_comp("Add Watch Pin"), str8_lit_comp(""), RD_IconKind_Pin}, {str8_lit_comp("toggle_watch_pin"), str8_lit_comp(""), str8_lit_comp("Toggle Watch Pin"), str8_lit_comp(""), RD_IconKind_Pin}, @@ -576,7 +578,7 @@ Rng1U64 rd_reg_slot_range_table[49] = {OffsetOf(RD_Regs, wm_event), OffsetOf(RD_Regs, wm_event) + sizeof(WM_Event *)}, }; -RD_CmdKindInfo rd_cmd_kind_info_table[249] = +RD_CmdKindInfo rd_cmd_kind_info_table[251] = { {0}, { str8_lit_comp("launch_and_run"), str8_lit_comp("Starts debugging a new instance of a target, then runs."), str8_lit_comp("launch,start,run,target"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:targets"), str8_lit_comp(""), D_EntityKind_Null}}, @@ -615,7 +617,10 @@ RD_CmdKindInfo rd_cmd_kind_info_table[249] = { str8_lit_comp("exit"), str8_lit_comp("Exits the debugger."), str8_lit_comp("quit,close,abort"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, { str8_lit_comp("open_palette"), str8_lit_comp("Opens the palette."), str8_lit_comp("help,cmd,lister"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, { str8_lit_comp("run_command"), str8_lit_comp("Runs a command from the command palette."), str8_lit_comp("help,cmd"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_CmdName, str8_lit_comp("query:commands"), str8_lit_comp("commands"), D_EntityKind_Null}}, -{ str8_lit_comp("run_ext_driver_text_command"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, +{ str8_lit_comp("run_ext_driver_text_command"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, +{ str8_lit_comp("state"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, +{ str8_lit_comp("eval"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Expr, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, +{ str8_lit_comp("line_from_vaddr"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Vaddr, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, { str8_lit_comp("wm_event"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, { str8_lit_comp("select_thread"), str8_lit_comp("Selects a thread."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Thread, str8_lit_comp("query:threads"), str8_lit_comp(""), D_EntityKind_Thread}}, { str8_lit_comp("select_unwind"), str8_lit_comp("Selects an unwind frame number for the selected thread."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp("query:call_stack"), str8_lit_comp(""), D_EntityKind_Null}}, @@ -767,7 +772,6 @@ RD_CmdKindInfo rd_cmd_kind_info_table[249] = { str8_lit_comp("enable_breakpoint"), str8_lit_comp("Enables a breakpoint."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:breakpoints"), str8_lit_comp(""), D_EntityKind_Null}}, { str8_lit_comp("disable_breakpoint"), str8_lit_comp("Disables a breakpoint."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:breakpoints"), str8_lit_comp(""), D_EntityKind_Null}}, { str8_lit_comp("clear_breakpoints"), str8_lit_comp("Removes all breakpoints."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, -{ str8_lit_comp("list_breakpoints"), str8_lit_comp("Lists all breakpoints."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, { str8_lit_comp("clear_output"), str8_lit_comp("Clears all output."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, { str8_lit_comp("add_watch_pin"), str8_lit_comp("Places a watch pin at a given location (file path and line number or address)."), str8_lit_comp(""), str8_lit_comp("$watch_pins,"), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Expr, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, { str8_lit_comp("toggle_watch_pin"), str8_lit_comp("Places or removes a watch pin at a given location (file path and line number or address)."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*1)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Expr, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}}, diff --git a/src/raddbg/generated/raddbg.meta.h b/src/raddbg/generated/raddbg.meta.h index 1440f4db..db003e8a 100644 --- a/src/raddbg/generated/raddbg.meta.h +++ b/src/raddbg/generated/raddbg.meta.h @@ -100,6 +100,9 @@ RD_CmdKind_Exit, RD_CmdKind_OpenPalette, RD_CmdKind_RunCommand, RD_CmdKind_RunExternalDriverTextCommand, +RD_CmdKind_State, +RD_CmdKind_Eval, +RD_CmdKind_LineFromVAddr, RD_CmdKind_WMEvent, RD_CmdKind_SelectThread, RD_CmdKind_SelectUnwind, @@ -251,7 +254,6 @@ RD_CmdKind_RemoveBreakpoint, RD_CmdKind_EnableBreakpoint, RD_CmdKind_DisableBreakpoint, RD_CmdKind_ClearBreakpoints, -RD_CmdKind_ListBreakpoints, RD_CmdKind_ClearOutput, RD_CmdKind_AddWatchPin, RD_CmdKind_ToggleWatchPin, @@ -603,7 +605,7 @@ Z(getting_started)\ C_LINKAGE_BEGIN extern String8 rd_tab_fast_path_view_name_table[25]; extern String8 rd_tab_fast_path_query_name_table[25]; -extern RD_VocabInfo rd_vocab_info_table[361]; +extern RD_VocabInfo rd_vocab_info_table[363]; extern RD_NameSchemaInfo rd_name_schema_info_table[39]; extern String8 rd_reg_slot_code_name_table[49]; extern Rng1U64 rd_reg_slot_range_table[49]; diff --git a/src/raddbg/raddbg.mdesk b/src/raddbg/raddbg.mdesk index b0168d61..2fb9b4ef 100644 --- a/src/raddbg/raddbg.mdesk +++ b/src/raddbg/raddbg.mdesk @@ -942,9 +942,14 @@ RD_CmdTable: // | | | | //- rjf: palette {OpenPalette 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 List "open_palette" "Open Palette" "Opens the palette." "help,cmd,lister" "" } - //- rjf: command runners + //- rjf: command fast-path {RunCommand 1 1 0 0 "query:commands" CmdName commands Nil Null 0 0 0 0 0 1 1 Null "run_command" "Run Command" "Runs a command from the command palette." "help,cmd" "" } - {RunExternalDriverTextCommand 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 1 1 Null "run_ext_driver_text_command" "Run External Driver Text Command" "" "" "" } + + //- rjf: external drivers + {RunExternalDriverTextCommand 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "run_ext_driver_text_command" "Run External Driver Text Command" "" "" "" } + {State 0 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "state" "State" "" "" "" } + {Eval 0 1 0 0 "" Expr null Nil Null 0 0 0 0 0 0 0 Null "eval" "Eval" "" "" "" } + {LineFromVAddr 0 1 0 0 "" Vaddr null Nil Null 0 0 0 0 0 0 0 Null "line_from_vaddr" "Line From Virtual Address" "" "" "" } //- rjf: os event passthrough {WMEvent 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "wm_event" "OS Event" "" "" "" } @@ -1152,7 +1157,6 @@ RD_CmdTable: // | | | | {EnableBreakpoint 1 1 0 0 "query:breakpoints" Cfg null Breakpoint Null 0 0 0 0 1 1 1 CheckFilled "enable_breakpoint" "Enable Breakpoint" "Enables a breakpoint." "" "" } {DisableBreakpoint 1 1 0 0 "query:breakpoints" Cfg null Breakpoint Null 0 0 0 0 1 1 1 CheckHollow "disable_breakpoint" "Disable Breakpoint" "Disables a breakpoint." "" "" } {ClearBreakpoints 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Trash "clear_breakpoints" "Clear Breakpoints" "Removes all breakpoints." "" "" } - {ListBreakpoints 0 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "list_breakpoints" "List Breakpoints" "Lists all breakpoints." "" "" } //- rjf: output {ClearOutput 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "clear_output" "Clear Output" "Clears all output." "" "" } diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index d6c4f3b7..525e4ecb 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -9227,26 +9227,6 @@ rd_value_string_from_eval(Arena *arena, String8 filter, EV_StringParams *params, return result; } -internal String8 -rd_value_string_from_eval2(Arena *arena, String8 filter, EV_StringParams *params, U64 cap, E_Eval eval) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List strs = {0}; - EV_StringIter *iter = ev_string_iter_begin(scratch.arena, eval, params); - for(String8 string = {0}; ev_string_iter_next(scratch.arena, iter, &string);) - { - if(strs.total_size + string.size > cap) - { - str8_list_push(scratch.arena, &strs, str8_lit("...")); - break; - } - str8_list_push(scratch.arena, &strs, string); - } - String8 result = str8_list_join(arena, &strs, 0); - scratch_end(scratch); - return result; -} - //////////////////////////////// //~ rjf: Hover Eval @@ -10302,264 +10282,6 @@ rd_next_view_cmd(RD_Cmd **cmd) return result; } -//////////////////////////////// -//~ IPC - -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 -rd_ipc_parse_string(MD_Node *node, String8 child_name, String8 *out) -{ - MD_Node *child = md_child_from_string(node, child_name, 0); - if (!md_node_is_nil(child) && !md_node_is_nil(child->first)) - { - if (out) { *out = child->first->string; } - return 1; - } - return 0; -} - -internal B32 -rd_ipc_parse_u32(MD_Node *node, String8 child_name, U32 *out) -{ - String8 value = {0}; - if (rd_ipc_parse_string(node, child_name, &value)) - { - U64 v64 = 0; - if (try_u64_from_str8_c_rules(value, &v64)) - { - if (out) { *out = safe_cast_u32(v64); } - return 1; - } - } - return 0; -} - -internal B32 -rd_ipc_parse_int_(MD_Node *node, String8 child_name, U64 out_size, void *out) -{ - String8 value = {0}; - if (rd_ipc_parse_string(node, child_name, &value)) - { - U64 v64 = 0; - if (try_u64_from_str8_c_rules(value, &v64)) - { - if (out) { MemoryCopy(out, &v64, out_size); } - return 1; - } - } - return 0; -} - -internal B32 -rd_ipc_parse_b32(MD_Node *node, String8 child_name, B32 *out) -{ - B32 is_ok = 0; - String8 s = {0}; - U64 value = 0; - if (rd_ipc_parse_string(node, child_name, &s)) - { - 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 - { - is_ok = try_u64_from_str8_c_rules(s, &value); - value = !!value; - } - } - if (is_ok && out) { *out = value; } - return is_ok; -} - -internal void -rd_ipc_reply_push(Arena *arena, String8List *out, char *name, String8 value) -{ - str8_list_pushf(arena, out, "%s: \"%S\"\n", name, escaped_from_raw_str8(arena, value)); -} - -internal void -rd_ipc_reply_block_begin(Arena *arena, String8List *out, char *name) -{ - str8_list_pushf(arena, out, "%s: {\n", name); -} - -internal void -rd_ipc_reply_block_end(Arena *arena, String8List *out) -{ - str8_list_pushf(arena, out, "}\n"); -} - -internal void -rd_ipc_reply_push_u64(Arena *arena, String8List *out, char *name, U64 value) -{ - str8_list_pushf(arena, out, "%s: %I64u\n", name, value); -} - -internal void -rd_ipc_reply_push_str8(Arena *arena, String8List *out, char *name, String8 value) -{ - str8_list_pushf(arena, out, "%s: \"%S\"\n", name, escaped_from_raw_str8(arena, value)); -} - -internal void -rd_ipc_reply_push_b32(Arena *arena, String8List *out, char *name, B32 value) -{ - rd_ipc_reply_push_u64(arena, out, name, !!value); -} - -internal String8 -rd_ipc_make_reply_ack(Arena *arena, String8 cmd, B32 ok) -{ - String8List s = {0}; - rd_ipc_reply_block_begin(arena, &s, "cmd_reply"); - rd_ipc_reply_push_b32(arena, &s, "ok", ok); - rd_ipc_reply_push (arena, &s, "cmd", cmd); - rd_ipc_reply_block_end(arena, &s); - return str8_list_join(arena, &s, 0); -} - -internal String8 -rd_ipc_make_reply_status(Arena *arena) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List s = {0}; - rd_ipc_reply_block_begin(arena, &s, "status"); - rd_ipc_reply_push_b32 (arena, &s, "ok", 1); - rd_ipc_reply_push_b32 (arena, &s, "running", d_ctrl_targets_running()); - rd_ipc_reply_push_u64 (arena, &s, "run_gen", d_run_gen()); - rd_ipc_reply_push_u64 (arena, &s, "ip", d_ctrl_last_stop_event().rip_vaddr); - rd_ipc_reply_block_end(arena, &s); - scratch_end(scratch); - return str8_list_join(arena, &s, 0); -} - -internal String8 -rd_ipc_make_reply_stop_event(Arena *arena) -{ - Temp scratch = scratch_begin(&arena, 1); - - D_Event e = d_ctrl_last_stop_event(); - - String8List stop_cause_list = {0}; - DR_FStrList stop_cause_fstr = rd_stop_explanation_fstrs_from_ctrl_event(scratch.arena, &e); - for EachNode (n, DR_FStrNode, stop_cause_fstr.first) { str8_list_push(scratch.arena, &stop_cause_list, n->v.string); } - String8 stop_cause = str8_list_join(arena, &stop_cause_list, &(StringJoin){.sep=str8_lit(" ")}); - - String8List s = {0}; - rd_ipc_reply_block_begin(arena, &s, "stop_event"); - rd_ipc_reply_push_b32 (arena, &s, "ok", 1); - rd_ipc_reply_push_u64 (arena, &s, "arch", e.arch); - rd_ipc_reply_push_u64 (arena, &s, "vaddr_min", e.vaddr_rng.min); - rd_ipc_reply_push_u64 (arena, &s, "vaddr_max", e.vaddr_rng.max); - rd_ipc_reply_push_u64 (arena, &s, "ip_vaddr", e.rip_vaddr); - rd_ipc_reply_push_u64 (arena, &s, "sp_base", e.stack_base); - rd_ipc_reply_push_u64 (arena, &s, "tls_root", e.tls_root); - rd_ipc_reply_push_u64 (arena, &s, "tls_index", e.tls_index); - rd_ipc_reply_push_u64 (arena, &s, "tls_offset", e.tls_offset); - rd_ipc_reply_push_u64 (arena, &s, "timestamp", e.timestamp); - rd_ipc_reply_push_u64 (arena, &s, "exception_code", e.exception_code); - rd_ipc_reply_push_u64 (arena, &s, "bp_flags", e.bp_flags); - rd_ipc_reply_push_str8(arena, &s, "string", e.string); - rd_ipc_reply_push_u64 (arena, &s, "target_os", e.target_os); - rd_ipc_reply_push_u64 (arena, &s, "tls_model", e.tls_model); - rd_ipc_reply_push_str8(arena, &s, "stop_cause", stop_cause); - rd_ipc_reply_block_end(arena, &s); - - String8 result = str8_list_join(arena, &s, 0); - scratch_end(scratch); - return result; -} - -internal String8 -rd_ipc_make_reply_eval(Arena *arena, String8 expr, E_Eval eval, U64 cap) -{ - Temp scratch = scratch_begin(&arena, 1); - - // gather value & type - EV_StringParams string_params = - { - .flags = EV_StringFlag_ReadOnlyDisplayRules|rd_state->eval_viz_base_string_flags, - .radix = 10, - }; - String8 value_string = rd_value_string_from_eval2(scratch.arena, str8_zero(), &string_params, cap, eval); - String8 type_string = e_type_string_from_key(scratch.arena, eval.irtree.type_key); - - String8List errors = {0}; - for EachNode(msg, E_Msg, eval.msgs.first) { str8_list_push(scratch.arena, &errors, msg->text); } - String8 error_string = str8_list_join(scratch.arena, &errors, &(StringJoin){.sep = str8_lit("; ")}); - - // format reply - String8List reply = {0}; - rd_ipc_reply_block_begin(arena, &reply, "eval"); - rd_ipc_reply_push_b32 (arena, &reply, "ok", 1); - rd_ipc_reply_push (arena, &reply, "cmd", str8_lit("eval")); - rd_ipc_reply_push (arena, &reply, "expr", expr); - rd_ipc_reply_push (arena, &reply, "value", value_string); - rd_ipc_reply_push (arena, &reply, "type", type_string); - rd_ipc_reply_push (arena, &reply, "error", error_string); - rd_ipc_reply_block_end(arena, &reply); - String8 result = str8_list_join(arena, &reply, 0); - - scratch_end(scratch); - return result; -} - -internal String8 -rd_ipc_make_reply_source_location_from_address(Arena *arena, U64 vaddr) -{ - Temp scratch = scratch_begin(&arena, 1); - - D_Entity *process = d_entity_from_handle(rd_base_regs()->process); - if(process == &d_entity_nil) - { - D_Entity *thread = d_entity_from_handle(rd_base_regs()->thread); - process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process); - } - - D_Entity *module = &d_entity_nil; - DI_Key dbgi_key = {0}; - U64 voff = 0; - D_LineList lines = {0}; - if(process != &d_entity_nil) - { - module = d_module_from_process_vaddr(process, vaddr); - if(module != &d_entity_nil) - { - dbgi_key = d_dbgi_key_from_module(module); - voff = d_voff_from_vaddr(module, vaddr); - lines = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, voff); - } - } - D_Line line = {0}; - if(lines.first != 0) - { - line = lines.first->v; - } - - B32 is_ok = (process != &d_entity_nil && module != &d_entity_nil && lines.first != 0); - - String8List reply = {0}; - rd_ipc_reply_block_begin(arena, &reply, "source_location_from_address"); - rd_ipc_reply_push_b32 (arena, &reply, "ok", is_ok); - rd_ipc_reply_push_u64 (arena, &reply, "vaddr", vaddr); - rd_ipc_reply_push_u64 (arena, &reply, "voff", voff); - rd_ipc_reply_push_str8(arena, &reply, "file_path", line.file_path); - rd_ipc_reply_push_u64 (arena, &reply, "line", line.pt.line); - rd_ipc_reply_push_u64 (arena, &reply, "column", line.pt.column); - rd_ipc_reply_push_u64 (arena, &reply, "voff_min", line.voff_range.min); - rd_ipc_reply_push_u64 (arena, &reply, "voff_max", line.voff_range.max); - rd_ipc_reply_block_end(arena, &reply); - String8 result = str8_list_join(arena, &reply, 0); - - scratch_end(scratch); - return result; -} - //////////////////////////////// //~ rjf: Main Layer Top-Level Calls @@ -12857,91 +12579,15 @@ rd_frame(void) } }break; - //- rjf: external driver textual commands + //- rjf: external drivers case RD_CmdKind_RunExternalDriverTextCommand: { - String8 msg = rd_regs()->string; - String8List msg_parts = str8_split(scratch.arena, msg, (U8 *)" ", 1, 0); - CmdLine msg_cmd_line = cmd_line_from_string_list(scratch.arena, msg_parts); - String8 cmd_kind_name = str8_list_first(&msg_cmd_line.inputs); + String8 msg = rd_regs()->string; + String8List msg_parts = str8_split(scratch.arena, msg, (U8 *)" ", 1, 0); + CmdLine msg_cmd_line = cmd_line_from_string_list(scratch.arena, msg_parts); + String8 cmd_kind_name = str8_list_first(&msg_cmd_line.inputs); RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_kind_name); - U64 cmd_args_pos = str8_find_needle(msg, 0, cmd_kind_name, StringMatchFlag_CaseInsensitive); - String8 cmd_args = str8_skip_chop_whitespace(str8_skip(msg, cmd_args_pos + cmd_kind_name.size)); - if(str8_match(cmd_kind_name, str8_lit("status"), 0)) - { - str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_status(rd_state->cmd_output_arena)); - } - else if(str8_match(cmd_kind_name, str8_lit("stop_event"), 0)) - { - str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_stop_event(rd_state->cmd_output_arena)); - } - else if(str8_match(cmd_kind_name, str8_lit("run"), 0)) - { - rd_cmd(RD_CmdKind_Run); - str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_ack(rd_state->cmd_output_arena, str8_lit("run"), 1)); - } - else if(str8_match(cmd_kind_name, str8_lit("halt"), 0)) - { - rd_cmd(RD_CmdKind_Halt); - str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_ack(rd_state->cmd_output_arena, str8_lit("halt"), 1)); - } - else if(str8_match(cmd_kind_name, str8_lit("kill_all"), 0)) - { - rd_cmd(RD_CmdKind_KillAll); - str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_ack(rd_state->cmd_output_arena, str8_lit("kill_all"), 1)); - } - else if(str8_match(cmd_kind_name, str8_lit("step_over"), 0)) - { - rd_cmd(RD_CmdKind_StepOver); - str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_ack(rd_state->cmd_output_arena, str8_lit("step_over"), 1)); - } - else if(str8_match(cmd_kind_name, str8_lit("step_into"), 0)) - { - rd_cmd(RD_CmdKind_StepInto); - str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_ack(rd_state->cmd_output_arena, str8_lit("step_into"), 1)); - } - else if(str8_match(cmd_kind_name, str8_lit("step_out"), 0)) - { - rd_cmd(RD_CmdKind_StepOut); - str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_ack(rd_state->cmd_output_arena, str8_lit("step_out"), 1)); - } - else if(str8_match(cmd_kind_name, str8_lit("step_over_inst"), 0)) - { - rd_cmd(RD_CmdKind_StepOverInst); - str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_ack(rd_state->cmd_output_arena, str8_lit("step_over_inst"), 1)); - } - else if(str8_match(cmd_kind_name, str8_lit("step_into_inst"), 0)) - { - rd_cmd(RD_CmdKind_StepIntoInst); - str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_ack(rd_state->cmd_output_arena, str8_lit("step_into_inst"), 1)); - } - else if(str8_match(cmd_kind_name, str8_lit("step_over_line"), 0)) - { - rd_cmd(RD_CmdKind_StepOverLine); - str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_ack(rd_state->cmd_output_arena, str8_lit("step_over_line"), 1)); - } - else if(str8_match(cmd_kind_name, str8_lit("step_into_line"), 0)) - { - rd_cmd(RD_CmdKind_StepIntoLine); - str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_ack(rd_state->cmd_output_arena, str8_lit("step_into_line"), 1)); - } - else if(str8_match(cmd_kind_name, str8_lit("eval"), 0)) - { - U64 cap_end = str8_find_needle(cmd_args, 0, str8_lit(" "), 0); - String8 cap_str = str8_substr(cmd_args, r1u64(0, cap_end)); - U64 cap = 0; - try_u64_from_str8_c_rules(cap_str, &cap); - String8 expr = str8_skip(cmd_args, cap_str.size); - str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_eval(rd_state->cmd_output_arena, expr, e_eval_from_string(expr), cap)); - } - else if(str8_match(cmd_kind_name, str8_lit("source_location_from_address"), 0)) - { - String8 vaddr_str = str8_skip_chop_whitespace(cmd_args); - U64 vaddr = 0; - try_u64_from_str8_c_rules(vaddr_str, &vaddr); - str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, rd_ipc_make_reply_source_location_from_address(rd_state->cmd_output_arena, vaddr)); - } - else if(cmd_kind_info != &rd_nil_cmd_kind_info) RD_RegsScope() + if(cmd_kind_info != &rd_nil_cmd_kind_info) RD_RegsScope() { for EachNonZeroEnumVal(RD_RegSlot, s) { @@ -12971,6 +12617,108 @@ rd_frame(void) log_user_errorf("`%S` is not a command.", cmd_kind_name); } }break; + case RD_CmdKind_State: + { + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, "state:\n{\n"); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " running: %i\n", d_ctrl_targets_running()); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " run_gen: %I64u\n", d_run_gen()); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " ip: 0x%I64x\n", d_ctrl_last_stop_event().rip_vaddr); + { + D_Event evt = d_ctrl_last_stop_event(); + DR_FStrList explanation_fstrs = rd_stop_explanation_fstrs_from_ctrl_event(scratch.arena, &evt); + String8 explanation_string = dr_string_from_fstrs(scratch.arena, &explanation_fstrs); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " stop_event:\n {\n"); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " arch: %S\n", string_from_arch(evt.arch)); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " vaddr_range: [0x%I64x, 0x%I64x)\n", evt.vaddr_rng.min, evt.vaddr_rng.max); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " ip_vaddr: 0x%I64x\n", evt.rip_vaddr); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " stack_base: 0x%I64x\n", evt.stack_base); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " tls_root: 0x%I64x\n", evt.tls_root); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " tls_index: 0x%I64x\n", evt.tls_index); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " timestamp: 0x%I64x\n", evt.timestamp); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " exception_code: 0x%I64x\n", (U64)evt.exception_code); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " bp_flags: 0x%I64x\n", (U64)evt.bp_flags); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " string: \"%S\"\n", escaped_from_raw_str8(scratch.arena, evt.string)); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " tls_model: 0x%I64x\n", evt.tls_model); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " explanation: \"%S\"\n", escaped_from_raw_str8(scratch.arena, explanation_string)); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " }\n"); + } + { + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " threads:\n {\n"); + D_EntityArray threads = d_entity_array_from_kind(D_EntityKind_Thread); + for EachIndex(idx, threads.count) + { + D_Entity *thread = threads.v[idx]; + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " {\n"); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " name: \"%S\"\n", escaped_from_raw_str8(scratch.arena, thread->string)); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " id: %I64u\n", thread->id); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " ip: 0x%I64x\n", d_query_cached_rip_from_thread(thread)); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " }\n"); + } + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " }\n"); + } + { + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " modules:\n {\n"); + D_EntityArray modules = d_entity_array_from_kind(D_EntityKind_Module); + for EachIndex(idx, modules.count) + { + D_Entity *module = modules.v[idx]; + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " {\n"); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " name: \"%S\"\n", escaped_from_raw_str8(scratch.arena, module->string)); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " vaddr_range: [0x%I64x, 0x%I64x)\n", module->vaddr_range.min, module->vaddr_range.max); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " }\n"); + } + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " }\n"); + } + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, "}\n"); + }break; + case RD_CmdKind_Eval: + { + String8 expr = rd_regs()->expr; + E_Eval eval = e_eval_from_string(expr); + E_Eval type_eval = e_eval_from_stringf("typeof(%S)", expr); + EV_StringParams string_params = + { + .flags = EV_StringFlag_ReadOnlyDisplayRules | rd_state->eval_viz_base_string_flags, + .radix = 10, + }; + String8 value_string = ev_value_string_from_eval(scratch.arena, &string_params, eval, 512); + String8 type_value_string = ev_value_string_from_eval(scratch.arena, &string_params, type_eval, 512); + String8List msgs_strings = {0}; + for EachNode(msg, E_Msg, eval.msgs.first) + { + str8_list_push(scratch.arena, &msgs_strings, msg->text); + } + StringJoin join = {.sep = s(". ")}; + String8 msgs_string = str8_list_join(scratch.arena, &msgs_strings, &join); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, "eval:\n{\n"); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " expr: %S\n", expr); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " value: \"%S\"\n", escaped_from_raw_str8(scratch.arena, value_string)); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " type: \"%S\"\n", escaped_from_raw_str8(scratch.arena, type_value_string)); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " msgs: \"%S\"\n", escaped_from_raw_str8(scratch.arena, msgs_string)); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, "}\n"); + }break; + case RD_CmdKind_LineFromVAddr: + { + U64 vaddr = rd_regs()->vaddr; + D_Entity *thread = d_entity_from_handle(rd_base_regs()->thread); + D_Entity *process = d_entity_ancestor_from_kind(thread, D_EntityKind_Process); + D_Entity *module = d_module_from_process_vaddr(process, vaddr); + U64 voff = d_voff_from_vaddr(module, vaddr); + DI_Key dbgi_key = d_dbgi_key_from_module(module); + D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, dbgi_key, voff); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, "lines:\n{\n"); + for EachNode(n, D_LineNode, lines.first) + { + D_Line line = n->v; + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " {\n"); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " file_path: \"%S\"\n", line.file_path); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " line_num: %I64d\n", line.pt.line); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " column_num: %I64d\n", line.pt.column); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " voff_range: [0x%I64x, 0x%I64x)\n", line.voff_range.min, line.voff_range.max); + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " }\n"); + } + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, "}\n"); + }break; //- rjf: exiting case RD_CmdKind_Exit: @@ -15810,16 +15558,6 @@ rd_frame(void) cfg_node_release(rd_state->cfg, n->v); } }break; - case RD_CmdKind_ListBreakpoints: - { - CFG_NodePtrList list = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("breakpoint")); - for(CFG_NodePtrNode *n = list.first; n != 0; n = n->next) - { - if(rd_cfg_is_project_filtered(n->v)){ continue; } - String8 string = cfg_string_from_tree(rd_state->cmd_output_arena, rd_state->cfg_schema_table, str8_zero(), n->v); - str8_list_push(rd_state->cmd_output_arena, &rd_state->cmd_outputs, string); - } - }break; //- rjf: output case RD_CmdKind_ClearOutput: diff --git a/src/raddbg/raddbg_core.h b/src/raddbg/raddbg_core.h index 72ac095f..e278f87e 100644 --- a/src/raddbg/raddbg_core.h +++ b/src/raddbg/raddbg_core.h @@ -93,17 +93,6 @@ enum RD_CmdKindFlag_ListInTextRng = (1<<4), }; -//////////////////////////////// -//~ IPC - -typedef struct RD_IpcReply RD_IpcReply; -struct RD_IpcReply -{ - MD_ParseResult parse; - MD_Node *root; - MD_Node *msg; -}; - //////////////////////////////// //~ rjf: Autocompletion Cursor Info Type @@ -762,7 +751,6 @@ internal void rd_window_frame(void); //~ rjf: Eval Visualization internal String8 rd_value_string_from_eval(Arena *arena, String8 filter, EV_StringParams *params, FNT_Tag font, F32 font_size, F32 max_size, E_Eval eval); -internal String8 rd_value_string_from_eval2(Arena *arena, String8 filter, EV_StringParams *params, U64 cap, E_Eval eval); //////////////////////////////// //~ rjf: Hover Eval @@ -848,15 +836,6 @@ internal void rd_push_cmd(String8 name, RD_Regs *regs); internal B32 rd_next_cmd(RD_Cmd **cmd); internal B32 rd_next_view_cmd(RD_Cmd **cmd); -//////////////////////////////// -//~ IPC - -internal RD_IpcReply rd_ipc_mdesk_reply_from_string(Arena *arena, String8 string); -internal B32 rd_ipc_parse_string(MD_Node *node, String8 child_name, String8 *out); -internal B32 rd_ipc_parse_int_(MD_Node *node, String8 child_name, U64 out_size, void *out); -#define rd_ipc_parse_int(a, b, c) rd_ipc_parse_int_(a, b, sizeof(*c), c) -internal B32 rd_ipc_parse_b32(MD_Node *node, String8 child_name, B32 *out); - //////////////////////////////// //~ rjf: Main Layer Top-Level Calls diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index fcf4b477..ab8f14df 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -295,7 +295,6 @@ #include "x64/x64.h" #include "win32/win32_inc.h" #include "linker/hash_table.h" -#include "linker/lf_hash_table.h" #include "linker/base_ext/base_bit_array.h" #include "artifact_cache/artifact_cache.h" #include "rdi/rdi_local.h" @@ -328,7 +327,6 @@ #include "rdi_from_coff/rdi_from_coff.h" #include "rdi_from_elf/rdi_from_elf.h" #include "rdi_from_pdb/rdi_from_pdb.h" -#include "rdi_from_dwarf/rdi_from_dwarf.h" #include "rdi_from_dwarf/rdi_from_dwarf_2.h" #include "radbin/radbin.h" #include "arch/arch_inc.h" @@ -351,7 +349,6 @@ #include "x64/x64.c" #include "win32/win32_inc.c" #include "linker/hash_table.c" -#include "linker/lf_hash_table.c" #include "linker/base_ext/base_bit_array.c" #include "artifact_cache/artifact_cache.c" #include "rdi/rdi_local.c" @@ -384,7 +381,6 @@ #include "rdi_from_coff/rdi_from_coff.c" #include "rdi_from_elf/rdi_from_elf.c" #include "rdi_from_pdb/rdi_from_pdb.c" -#include "rdi_from_dwarf/rdi_from_dwarf.c" #include "rdi_from_dwarf/rdi_from_dwarf_2.c" #include "radbin/radbin.c" #include "arch/arch_inc.c" diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index 3ce62e0d..0a532fc4 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -2313,7 +2313,7 @@ RD_VIEW_UI_FUNCTION_DEF(text) for EachNode(override_n, String8Node, overrides.first) { String8 file_path = override_n->string; - String8 file_path_normalized = rdim_normalize_path_str8(scratch.arena, file_path); + String8 file_path_normalized = rdim_normalized_from_path(scratch.arena, file_path); B32 good_src_id = 0; U32 src_id = 0; if(rdi != &rdi_parsed_nil) diff --git a/src/rdi_make/rdi_make_local.c b/src/rdi_make/rdi_make_local.c index b40298f9..c788c0fa 100644 --- a/src/rdi_make/rdi_make_local.c +++ b/src/rdi_make/rdi_make_local.c @@ -1202,7 +1202,7 @@ rdim_bake(Arena *arena, RDIM_BakeParams *params) Rng1U64 range = lane_range(n->count); for EachInRange(n_idx, range) { - RDIM_String8 normalized_path = rdim_normalize_path_str8(scratch.arena, n->v[n_idx].path); + RDIM_String8 normalized_path = rdim_normalized_from_path(scratch.arena, n->v[n_idx].path); rdim_bake_string_map_loose_insert(scratch.arena, top, lane_map, 1, normalized_path); } } @@ -1505,7 +1505,7 @@ rdim_bake(Arena *arena, RDIM_BakeParams *params) for EachInRange(n_idx, n_range) { RDIM_SrcFile *src_file = &n->v[n_idx]; - RDIM_String8 normalized_path = rdim_normalize_path_str8(scratch.arena, src_file->path); + RDIM_String8 normalized_path = rdim_normalized_from_path(scratch.arena, src_file->path); rdim_bake_name_map_insert(scratch.arena, top, map, 4, normalized_path, rdim_idx_from_src_file(src_file)); } } @@ -2450,7 +2450,7 @@ rdim_bake(Arena *arena, RDIM_BakeParams *params) //- rjf: fill file info Temp scratch2 = scratch_begin(&scratch.arena, 1); - String8 normalized_path = rdim_normalize_path_str8(scratch2.arena, src->path); + String8 normalized_path = rdim_normalized_from_path(scratch2.arena, src->path); B32 has_checksum = (RDI_ChecksumKind_NULL < src->checksum_kind && src->checksum_kind < RDI_ChecksumKind_COUNT && src->checksum.size != 0); dst->file_path_node_idx = rdim_bake_path_node_idx_from_string(path_tree, src->path); dst->normal_full_path_string_idx = rdim_bake_idx_from_string(bake_strings, normalized_path); diff --git a/src/torture/torture_dbg.c b/src/torture/torture_dbg.c index 6472810f..2a9f81c0 100644 --- a/src/torture/torture_dbg.c +++ b/src/torture/torture_dbg.c @@ -7,6 +7,88 @@ extern B32 g_stop_on_first_fail_or_crash; +//////////////////////////////// +// Debugger IPC Replies + +typedef struct RD_IpcReply RD_IpcReply; +struct RD_IpcReply +{ + MD_ParseResult parse; + MD_Node *root; + MD_Node *msg; +}; + +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 +rd_ipc_parse_string(MD_Node *node, String8 child_name, String8 *out) +{ + MD_Node *child = md_child_from_string(node, child_name, 0); + if (!md_node_is_nil(child) && !md_node_is_nil(child->first)) + { + if (out) { *out = child->first->string; } + return 1; + } + return 0; +} + +internal B32 +rd_ipc_parse_u32(MD_Node *node, String8 child_name, U32 *out) +{ + String8 value = {0}; + if (rd_ipc_parse_string(node, child_name, &value)) + { + U64 v64 = 0; + if (try_u64_from_str8_c_rules(value, &v64)) + { + if (out) { *out = safe_cast_u32(v64); } + return 1; + } + } + return 0; +} + +internal B32 +rd_ipc_parse_int_(MD_Node *node, String8 child_name, U64 out_size, void *out) +{ + String8 value = {0}; + if (rd_ipc_parse_string(node, child_name, &value)) + { + U64 v64 = 0; + if (try_u64_from_str8_c_rules(value, &v64)) + { + if (out) { MemoryCopy(out, &v64, out_size); } + return 1; + } + } + return 0; +} + +internal B32 +rd_ipc_parse_b32(MD_Node *node, String8 child_name, B32 *out) +{ + B32 is_ok = 0; + String8 s = {0}; + U64 value = 0; + if (rd_ipc_parse_string(node, child_name, &s)) + { + 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 + { + is_ok = try_u64_from_str8_c_rules(s, &value); + value = !!value; + } + } + if (is_ok && out) { *out = value; } + return is_ok; +} + //////////////////////////////// // IPC Controller @@ -17,14 +99,14 @@ t_dbg_send_cmd(String8 cmd, U64 timeout_us, Arena *reply_arena, RD_IpcReply *rep { Temp scratch = scratch_begin(&reply_arena, 1); B32 is_sent = 0; - - + + // send command String8 cmdline = str8f(scratch.arena, "--gen_crash_dump --ipc --pid:%u %S", g_dbg_pid, cmd); if (t_invoke(t_raddbg_path(), cmdline, timeout_us) == 0) { goto exit; } - + B32 has_reply = 1; - + char *no_reply_cmds[] = { "add_breakpoint", "add_function_breakpoint", @@ -37,23 +119,23 @@ t_dbg_send_cmd(String8 cmd, U64 timeout_us, Arena *reply_arena, RD_IpcReply *rep break; } } - + if (has_reply) { // parse reply Arena *a = reply_arena ? reply_arena : scratch.arena; String8 reply_text = str8_copy(a, g_output); RD_IpcReply reply = rd_ipc_mdesk_reply_from_string(a, reply_text); - + //fprintf(stderr, "Reply: %.*s\n", str8_varg(reply_text)); - + // validate reply if (reply.parse.msgs.worst_message_kind >= MD_MsgKind_Error) { goto exit; } if (md_node_is_nil(reply.msg)) { goto exit; } //if ( ! str8_matchi(reply.parse.root->first->string, cmd)) { Assert(0); goto exit; } - + if (reply_arena && reply_out) { *reply_out = reply; } } - + is_sent = 1; exit:; scratch_end(scratch); @@ -77,21 +159,21 @@ internal B32 t_dbg_status(T_DbgStatus *status_out, U64 timeout_us) { Temp scratch = scratch_begin(0, 0); - + B32 is_ok = 0; T_DbgStatus status = {0}; - + // send status request RD_IpcReply reply = {0}; if ( ! t_dbg_send_cmd(str8_lit("status"), timeout_us, scratch.arena, &reply)) { goto exit; } - + // parse reply if ( ! rd_ipc_parse_b32(reply.msg, str8_lit("ok"), &is_ok)) { t_errorf("ERROR: failed to parse reply member: ok\n"); Assert(0); goto exit; } if ( ! rd_ipc_parse_b32(reply.msg, str8_lit("running"), &status.running)) { t_errorf("ERROR: failed to parse reply member: running\n"); Assert(0); goto exit; } if ( ! rd_ipc_parse_int(reply.msg, str8_lit("run_gen"), &status.run_gen)) { t_errorf("ERROR: failed to parse reply member: run_gen\n"); Assert(0); goto exit; } if ( ! rd_ipc_parse_int(reply.msg, str8_lit("ip"), &status.ip)) { t_errorf("ERROR: failed to parse reply member: ip\n"); Assert(0); goto exit; } if (status_out != 0) { *status_out = status; } - + exit:; if ( ! is_ok && reply.parse.root) { t_errorf("\tReply: %S\n", reply.parse.root->raw_string); @@ -104,14 +186,14 @@ internal B32 t_dbg_stop_event(Arena *arena, T_DbgStopEvent *out, U64 timeout_us) { Temp scratch = scratch_begin(0, 0); - + T_DbgStopEvent v = {0}; B32 is_ok = 0; - + // send status request RD_IpcReply reply = {0}; if ( ! t_dbg_send_cmd(str8_lit("stop_event"), timeout_us, arena ? arena : scratch.arena, &reply)) { goto exit; } - + // parse reply if ( ! rd_ipc_parse_b32 (reply.msg, str8_lit("ok"), &is_ok)) { AssertAlways(0); goto exit; } if ( ! rd_ipc_parse_int (reply.msg, str8_lit("arch"), &v.arch)) { AssertAlways(0); goto exit; } @@ -129,9 +211,9 @@ t_dbg_stop_event(Arena *arena, T_DbgStopEvent *out, U64 timeout_us) if ( ! rd_ipc_parse_int (reply.msg, str8_lit("target_os"), &v.target_os)) { AssertAlways(0); goto exit; } if ( ! rd_ipc_parse_int (reply.msg, str8_lit("tls_model"), &v.tls_model)) { AssertAlways(0); goto exit; } if ( ! rd_ipc_parse_string (reply.msg, str8_lit("stop_cause"), &v.stop_cause)) { AssertAlways(0); goto exit; } - + if (arena && out != 0) { *out = v; } - + exit:; return is_ok; } @@ -140,14 +222,14 @@ internal B32 t_dbg_src_line(Arena *arena, U64 vaddr, T_DbgSourceLocation *loc_out, U64 timeout_us) { Temp scratch = scratch_begin(&arena, 1); - + B32 is_ok = 0; - + RD_IpcReply reply = {0}; if(!t_dbg_send_cmdf(timeout_us, arena, &reply, "source_location_from_address 0x%llx", vaddr)) { goto exit; } - + T_DbgSourceLocation loc = {0}; - + if ( ! rd_ipc_parse_b32 (reply.msg, str8_lit("ok"), &is_ok)) { AssertAlways(0); goto exit; } if ( ! rd_ipc_parse_int (reply.msg, str8_lit("vaddr"), &loc.vaddr)) { AssertAlways(0); goto exit; } if ( ! rd_ipc_parse_int (reply.msg, str8_lit("voff"), &loc.voff)) { AssertAlways(0); goto exit; } @@ -156,9 +238,9 @@ t_dbg_src_line(Arena *arena, U64 vaddr, T_DbgSourceLocation *loc_out, U64 timeou if ( ! rd_ipc_parse_int (reply.msg, str8_lit("column"), &loc.pt.column)) { AssertAlways(0); goto exit; } if ( ! rd_ipc_parse_int (reply.msg, str8_lit("voff_min"), &loc.voff_range.min)){ AssertAlways(0); goto exit; } if ( ! rd_ipc_parse_int (reply.msg, str8_lit("voff_max"), &loc.voff_range.max)){ AssertAlways(0); goto exit; } - + if (loc_out != 0) { *loc_out = loc; } - + exit:; scratch_end(scratch); return is_ok; @@ -190,37 +272,37 @@ t_dbg_send_cmd_and_wait_stop(String8 cmd, U64 timeout_us) { Temp scratch = scratch_begin(0,0); B32 is_stopped = 0; - + // snapshot status T_DbgStatus status_before = {0}; if (t_dbg_status(&status_before, max_U64) == 0) { Assert(0 && "failed to snapshot status"); goto exit; } - + // send command if (t_dbg_send_cmd(cmd, max_U64, 0, 0) == 0) { Assert(0 && "failed to the command"); goto exit; } - + // wait for debugger to stop U64 t = ENDT_US(timeout_us); for (;;) { // query debugger status T_DbgStatus status = {0}; if (t_dbg_status(&status, t) == 0) { Assert(0 && "failed to acquire debugger status"); goto exit; } - + // did state change? -> break if (!status.running && status.run_gen != status_before.run_gen) { is_stopped = 1; break; } - + // "solve" the wait problem if (now_time_us() >= t) { Assert(0 && "timeout"); goto exit; } sleep_ms(10); } - + //--- Status --------------------- if (0 && is_stopped) { T_DbgStatus status = {0}; AssertAlways(t_dbg_status(&status, T_Dbg_DefaultTimeout)); - + String8 process_id = str8_skip(str8_chop(t_dbg_value_from_exprf(scratch.arena, "query:current_process.id"), 2), 2); String8 process_label = str8_chop(str8_skip(t_dbg_value_from_exprf(scratch.arena, "query:current_process.label"), 2), 2); String8 process_active = t_dbg_value_from_exprf(scratch.arena, "query:current_process.active"); @@ -229,13 +311,13 @@ t_dbg_send_cmd_and_wait_stop(String8 cmd, U64 timeout_us) String8 thread_label = str8_skip(str8_chop(t_dbg_value_from_exprf(scratch.arena, "query:current_thread.label"), 2), 2); String8 ip = t_dbg_value_from_exprf(scratch.arena, "hex(reg:rip)"); String8 sp = t_dbg_value_from_exprf(scratch.arena, "hex(reg:rsp)"); - + T_DbgStopEvent last_stop = {0}; AssertAlways(t_dbg_stop_event(scratch.arena, &last_stop, T_Dbg_DefaultTimeout)); - + T_DbgSourceLocation loc = {0}; AssertAlways(t_dbg_src_line(scratch.arena, last_stop.ip_vaddr, &loc, T_Dbg_DefaultTimeout)); - + printf("------------------------------------------------------------------------------------------------------------------------\n"); printf(" Process: %.*s [%.*s] (Active: %.*s)\n", str8_varg(process_id), str8_varg(process_label), str8_varg(process_active)); printf(" Thread: %.*s [%.*s] (Active: %.*s)\n", str8_varg(thread_id), str8_varg(thread_label), str8_varg(thread_active)); @@ -249,7 +331,7 @@ t_dbg_send_cmd_and_wait_stop(String8 cmd, U64 timeout_us) fflush(stdout); } //-------------------------------- - + exit:; scratch_end(scratch); return is_stopped; @@ -265,11 +347,11 @@ t_dbg_launch(String8 cmdline, U64 timeout_us) { Temp scratch = scratch_begin(0, 0); B32 dbg_ready = 0; - + String8 user_path = t_make_file_path(scratch.arena, str8_lit("test.raddbg_user")); String8 project_path = t_make_file_path(scratch.arena, str8_lit("test.raddbg_project")); cmdline = str8f(scratch.arena, "%S --gen_crash_dump --user:\"%S\" --project:\"%S\" --logs:\"%S\" %S", t_raddbg_path(), user_path, project_path, g_wdir, cmdline); - + // launch debugger ProcessLaunchParams launch_opts = { .path = g_wdir, @@ -279,7 +361,7 @@ t_dbg_launch(String8 cmdline, U64 timeout_us) }; Process dbg_handle = process_launch(&launch_opts); if (process_match(dbg_handle, process_zero())) { AssertAlways(0 && "failed to launch debugger"); goto exit; } - + #if OS_WINDOWS // cache debugger PID g_dbg_pid = GetProcessId((HANDLE)dbg_handle.u64[0]); @@ -288,22 +370,22 @@ t_dbg_launch(String8 cmdline, U64 timeout_us) #else # error NotImplemented #endif - + // close debugger handle process_detach(dbg_handle); - + // now wait for debugger to init U64 t = ENDT_US(timeout_us); for (;;) { // time the ping dbg_ready = t_dbg_ping(t); if (dbg_ready) { break; } - + // "solve" the wait problem if (now_time_us() >= t) { Assert(0 && "timeout"); break; } sleep_ms(10); } - + exit:; scratch_end(scratch); return dbg_ready; @@ -313,18 +395,18 @@ internal B32 t_dbg_eval(Arena *arena, String8 expr, T_Eval *eval_out) { Temp scratch = scratch_begin(&arena, 1); - + RD_IpcReply reply = {0}; String8 cmd = str8f(scratch.arena, "eval %llu %S", /* value char cap: */ 10000, expr); B32 is_ok = t_dbg_send_cmd(cmd, T_Dbg_DefaultTimeout, arena, &reply); - + T_Eval e = {0}; if ( ! rd_ipc_parse_string(reply.msg, str8_lit("expr"), &e.expr)) { t_errorf("ERROR: failed to parse reply member: expr\n"); Assert(0); goto exit; } if ( ! rd_ipc_parse_string(reply.msg, str8_lit("value"), &e.value)) { t_errorf("ERROR: failed to parse reply member: value\n"); Assert(0); goto exit; } if ( ! rd_ipc_parse_string(reply.msg, str8_lit("type"), &e.type)) { t_errorf("ERROR: failed to parse reply member: type\n"); Assert(0); goto exit; } if ( ! rd_ipc_parse_string(reply.msg, str8_lit("error"), &e.error)) { t_errorf("ERROR: failed to parse reply member: error\n"); Assert(0); goto exit; } if (eval_out) { *eval_out = e; } - + exit:; scratch_end(scratch); return is_ok; @@ -350,22 +432,22 @@ internal String8 t_string_from_dbg_script_cmd_kind(T_DbgScriptCmdKind v) { switch (v) { - case T_DbgScriptCmdKind_Null: return str8_zero(); - case T_DbgScriptCmdKind_Breakpoint: return str8_lit("bp"); - 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; + case T_DbgScriptCmdKind_Null: return str8_zero(); + case T_DbgScriptCmdKind_Breakpoint: return str8_lit("bp"); + 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(); } @@ -386,7 +468,7 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS B32 is_ok = 0; T_DbgScript script = { .file_path = push_str8_copy(arena, file_path) }; - + // scrape MD comment tokens out of source while preserving original source offsets MD_TokenArray script_tokens = {0}; { @@ -415,11 +497,11 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS } script_tokens = md_token_array_from_chunk_list(scratch.arena, &script_token_chunks); } - + // script tokens -> mdesk tree MD_ParseResult script_parse = md_parse_from_text_tokens(scratch.arena, file_path, source, script_tokens); AssertAlways(script_parse.msgs.worst_message_kind < MD_MsgKind_Error); - + // test { MD_Node *test = script_parse.root->first; @@ -428,32 +510,32 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS for MD_EachNode(n, test->first) { OperatingSystem os = operating_system_from_string(n->string); AssertAlways(os != OperatingSystem_Null); - + for MD_EachNode(field, n->first) { T_DbgScriptDirectiveKind kind = T_DbgScriptDirectiveKind_Null; 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("launch"))) { kind = T_DbgScriptDirectiveKind_Launch; } AssertAlways(kind != T_DbgScriptDirectiveKind_Null); - + // syntax check AssertAlways( !md_node_is_nil(field->first)); AssertAlways(md_node_is_nil(field->first->next)); Assert(field->first->flags & MD_NodeFlag_StringLiteral); - + // src_offset -> line // // TODO: super silly!! mdesk should export line numbers 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); n->kind = kind; n->line = line; n->args = str8_copy(arena, field->first->string); // TODO: expand % in compile: and link: to current source file name and esacpe with %% - + T_DbgScriptDirectiveList *list = &script.directives[os][kind]; SLLQueuePush(list->first, list->last, n); list->count += 1; @@ -464,7 +546,7 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS goto exit; } } - + // file { MD_Node *last_file = 0; @@ -475,19 +557,19 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS AssertAlways( ! md_node_is_nil(n->first)); AssertAlways(md_node_is_nil(n->first->next)); } - + if (last_file) { // 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)); U64 file_dir_end = str8_find_needle(sub_source, 0, str8_lit("\n"), 0); U64 next_file_dir_begin = str8_find_needle_reverse(sub_source, 0, str8_lit("\n"), n->src_offset); sub_source = str8_substr(sub_source, r1u64(file_dir_end + 1, next_file_dir_begin)); - + T_DbgScriptFile *file = push_array(arena, T_DbgScriptFile, 1); file->path = t_make_file_path(arena, last_file->first->string); file->source = sub_source; @@ -495,11 +577,11 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS SLLQueuePush(script.files.first, script.files.last, file); script.files.count += 1; } - + last_file = n; } } - + // no file directives? assume script file as main source file if (last_file == 0) { T_DbgScriptFile *file = push_array(arena, T_DbgScriptFile, 1); @@ -509,7 +591,7 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS script.files.count += 1; } } - + // programs { HashTable *ht = hash_table_init(scratch.arena, 256); // @@ -523,7 +605,7 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS } } AssertAlways(file != 0); - + // src_offset -> line // // TODO: super silly!! mdesk should export line numbers @@ -541,7 +623,7 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS } else { t_errorf("ERROR: duplicate order number %llu found on line %llu\n", (unsigned long long)order, (unsigned long long)p->line); } - + for MD_EachNode(cmd_n, n->first) { // push new cmd T_DbgScriptCmd *cmd = push_array(arena, T_DbgScriptCmd, 1); @@ -550,7 +632,7 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS Assert(cmd->kind != T_DbgScriptCmdKind_Null); SLLQueuePush(p->first, p->last, cmd); p->count += 1; - + // parse cmd args MD_Node *cmd_arg = cmd_n->first; if ( ! md_node_is_nil(cmd_arg)) { @@ -565,12 +647,12 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS } } } - + script.program_count = ht->count; script.programs = values_from_hash_table_raw(arena, ht); radsort(script.programs, script.program_count, t_dbg_script_program_is_before); } - + is_ok = 1; exit:; if (script_out) { @@ -584,80 +666,80 @@ internal B32 t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us) { Temp scratch = scratch_begin(0,0); - + B32 is_ok = 0; - + for EachIndex(i, script->program_count) { T_DbgScriptProgram *program = script->programs[i]; - + if (program->os == OperatingSystem_CURRENT) { 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)); - + switch (cmd->kind) { - case T_DbgScriptCmdKind_Null: break; - case T_DbgScriptCmdKind_Halt: t_dbg_send_cmd_and_wait_stop(str8_lit("halt"), timeout_us); break; // NOTE: does not auto-magically select main thread on stop - case T_DbgScriptCmdKind_StepOver: t_dbg_send_cmd_and_wait_stop(str8_lit("step_over"), timeout_us); break; - case T_DbgScriptCmdKind_StepInto: t_dbg_send_cmd_and_wait_stop(str8_lit("step_into"), timeout_us); break; - case T_DbgScriptCmdKind_StepOut: t_dbg_send_cmd_and_wait_stop(str8_lit("step_out"), timeout_us); break; - case T_DbgScriptCmdKind_StepOverInst: t_dbg_send_cmd_and_wait_stop(str8_lit("step_over_inst"), timeout_us); break; - case T_DbgScriptCmdKind_StepIntoInst: t_dbg_send_cmd_and_wait_stop(str8_lit("step_into_inst"), timeout_us); break; - case T_DbgScriptCmdKind_StepOverLine: t_dbg_send_cmd_and_wait_stop(str8_lit("step_over_line"), timeout_us); break; - case T_DbgScriptCmdKind_StepIntoLine: t_dbg_send_cmd_and_wait_stop(str8_lit("step_into_line"), timeout_us); break; - case T_DbgScriptCmdKind_KillAll: t_dbg_send_cmd_and_wait_stop(str8_lit("kill_all"), timeout_us); break; - case T_DbgScriptCmdKind_Breakpoint: NotImplemented; break; - case T_DbgScriptCmdKind_ClearBreakpoints: t_dbg_send_cmdf(0,0,0, "clear_breakpoints"); break; - case T_DbgScriptCmdKind_Run: t_dbg_send_cmd(str8_lit("run"), timeout_us, 0, 0); break; - case T_DbgScriptCmdKind_At: { - // TODO: debugger does not populate eval cache with registers before first frame, - // so this racy, for now use lower level option + case T_DbgScriptCmdKind_Null: break; + case T_DbgScriptCmdKind_Halt: t_dbg_send_cmd_and_wait_stop(str8_lit("halt"), timeout_us); break; // NOTE: does not auto-magically select main thread on stop + case T_DbgScriptCmdKind_StepOver: t_dbg_send_cmd_and_wait_stop(str8_lit("step_over"), timeout_us); break; + case T_DbgScriptCmdKind_StepInto: t_dbg_send_cmd_and_wait_stop(str8_lit("step_into"), timeout_us); break; + case T_DbgScriptCmdKind_StepOut: t_dbg_send_cmd_and_wait_stop(str8_lit("step_out"), timeout_us); break; + case T_DbgScriptCmdKind_StepOverInst: t_dbg_send_cmd_and_wait_stop(str8_lit("step_over_inst"), timeout_us); break; + case T_DbgScriptCmdKind_StepIntoInst: t_dbg_send_cmd_and_wait_stop(str8_lit("step_into_inst"), timeout_us); break; + case T_DbgScriptCmdKind_StepOverLine: t_dbg_send_cmd_and_wait_stop(str8_lit("step_over_line"), timeout_us); break; + case T_DbgScriptCmdKind_StepIntoLine: t_dbg_send_cmd_and_wait_stop(str8_lit("step_into_line"), timeout_us); break; + case T_DbgScriptCmdKind_KillAll: t_dbg_send_cmd_and_wait_stop(str8_lit("kill_all"), timeout_us); break; + case T_DbgScriptCmdKind_Breakpoint: NotImplemented; break; + case T_DbgScriptCmdKind_ClearBreakpoints: t_dbg_send_cmdf(0,0,0, "clear_breakpoints"); break; + case T_DbgScriptCmdKind_Run: t_dbg_send_cmd(str8_lit("run"), timeout_us, 0, 0); break; + case T_DbgScriptCmdKind_At: { + // TODO: debugger does not populate eval cache with registers before first frame, + // so this racy, for now use lower level option #if 0 - U64 ip = u64_from_str8(t_dbg_value_from_exprf(scratch.arena, "reg:rip"), 10); - if (ip == 0) { - fprintf(stderr, "ERROR: invalid IP address: 0x%llx\n", (unsigned long long)ip); - goto exit; - } + U64 ip = u64_from_str8(t_dbg_value_from_exprf(scratch.arena, "reg:rip"), 10); + if (ip == 0) { + fprintf(stderr, "ERROR: invalid IP address: 0x%llx\n", (unsigned long long)ip); + goto exit; + } #else - T_DbgStatus temp_status = {0}; - if ( ! t_dbg_status(&temp_status, T_Dbg_DefaultTimeout)) { - t_errorf("ERROR: %S:%llu: failed to query IP\n", script->file_path, (unsigned long long)cmd->line); - goto exit; - } - U64 ip = temp_status.ip; + T_DbgStatus temp_status = {0}; + if ( ! t_dbg_status(&temp_status, T_Dbg_DefaultTimeout)) { + t_errorf("ERROR: %S:%llu: failed to query IP\n", script->file_path, (unsigned long long)cmd->line); + goto exit; + } + U64 ip = temp_status.ip; #endif - - // map IP -> source location - T_DbgSourceLocation loc = {0}; - if (t_dbg_src_line(scratch.arena, ip, &loc, 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); - goto exit; - } - - // compute line where debugger must be - S64 at_line_s64 = (S64)(program->line - program->file->line) + cmd->at.delta; - U64 at_line_u64 = at_line_s64 >= 0 ? (U64)at_line_s64 : 0; - AssertAlways(at_line_u64 > 0); - - // match expected vs current debugger locations - B32 mismatch = loc.pt.line != at_line_u64 || - !str8_match(loc.file_path, program->file->path, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive); - if (mismatch) { - t_errorf("ERROR: %S:%llu: location check did not pass:\n", script->file_path, (unsigned long long)cmd->line); - t_errorf(" Expected: %S:%llu\n", program->file->path, (unsigned long long)at_line_u64); - t_errorf(" Got : %S:%llu\n", loc.file_path, (unsigned long long)loc.pt.line); - t_errorf(" IP : 0x%llx\n", (unsigned long long)ip); - goto exit; - } - } break; - case T_DbgScriptCmdKind_Eval: NotImplemented; break; - default: { InvalidPath; } + + // map IP -> source location + T_DbgSourceLocation loc = {0}; + if (t_dbg_src_line(scratch.arena, ip, &loc, 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); + goto exit; + } + + // compute line where debugger must be + S64 at_line_s64 = (S64)(program->line - program->file->line) + cmd->at.delta; + U64 at_line_u64 = at_line_s64 >= 0 ? (U64)at_line_s64 : 0; + AssertAlways(at_line_u64 > 0); + + // match expected vs current debugger locations + B32 mismatch = loc.pt.line != at_line_u64 || + !str8_match(loc.file_path, program->file->path, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive); + if (mismatch) { + t_errorf("ERROR: %S:%llu: location check did not pass:\n", script->file_path, (unsigned long long)cmd->line); + t_errorf(" Expected: %S:%llu\n", program->file->path, (unsigned long long)at_line_u64); + t_errorf(" Got : %S:%llu\n", loc.file_path, (unsigned long long)loc.pt.line); + t_errorf(" IP : 0x%llx\n", (unsigned long long)ip); + goto exit; + } + } break; + case T_DbgScriptCmdKind_Eval: NotImplemented; break; + default: { InvalidPath; } } } } - + is_ok = (i+1 == script->program_count); } - + exit:; scratch_end(scratch); return is_ok; @@ -670,20 +752,20 @@ T_RunSig(dbg_script_runner) t_errorf("ERROR: failed to find debugger \"%S\"\n", t_raddbg_path()); T_Ok(0); } - + // read source file String8 source = data_from_file_path(arena, user_data); if (source.size == 0) { t_errorf("ERROR: failed to read script: \"%S\"\n", user_data); T_Ok(0); } - + // source -> script T_DbgScript script = {0}; if ( ! t_dbg_script_from_source(arena, user_data, source, &script)) { goto exit; } - + // write source files to test folder for EachNode(file, T_DbgScriptFile, script.files.first) { if (write_data_to_file_path(file->path, file->source) == 0) { @@ -691,32 +773,32 @@ T_RunSig(dbg_script_runner) T_Ok(0); } } - + // compiler vars HashTable *script_vars = hash_table_init(arena, 1000); hash_table_push_path_string(arena, script_vars, str8_lit("CWD"), g_wdir); - + // run compilers for EachNode(directive, T_DbgScriptDirective, script.directives[OperatingSystem_CURRENT][T_DbgScriptDirectiveKind_Compile].first) { T_Compiler compiler = directive->compile.compiler; - + // pick default compiler if none selected if (compiler == T_Compiler_Null) { switch (OperatingSystem_CURRENT) { - case OperatingSystem_Windows: { compiler = T_Compiler_Cl; } break; - case OperatingSystem_Linux: { compiler = T_Compiler_Clang; } break; + case OperatingSystem_Windows: { compiler = T_Compiler_Cl; } break; + case OperatingSystem_Linux: { compiler = T_Compiler_Clang; } break; } } - + // get compiler path String8 compiler_path = {0}; switch (compiler) { - case T_Compiler_Null: break; - case T_Compiler_Cl: compiler_path = t_cl_path(); break; - case T_Compiler_Clang: compiler_path = t_clang_path(); break; - case T_Compiler_Gcc: compiler_path = t_gcc_path(); break; + case T_Compiler_Null: break; + case T_Compiler_Cl: compiler_path = t_cl_path(); break; + case T_Compiler_Clang: compiler_path = t_clang_path(); break; + case T_Compiler_Gcc: compiler_path = t_gcc_path(); break; } - + // invoke compiler with arguments from directive String8 expanded_args = lnk_expand_env_vars_windows(arena, script_vars, directive->args); if (t_invoke(compiler_path, expanded_args, max_U64) == 0) { @@ -730,7 +812,7 @@ T_RunSig(dbg_script_runner) } } } - + // run linkers String8 linker_path = t_radlink_path(); for EachNode(directive, T_DbgScriptDirective, script.directives[OperatingSystem_CURRENT][T_DbgScriptDirectiveKind_Link].first) { @@ -744,7 +826,7 @@ T_RunSig(dbg_script_runner) T_Ok(0); } } - + // launch targets for EachNode(directive, T_DbgScriptDirective, script.directives[OperatingSystem_CURRENT][T_DbgScriptDirectiveKind_Launch].first) { String8 expanded_args = lnk_expand_env_vars_windows(arena, script_vars, directive->args); @@ -754,13 +836,13 @@ T_RunSig(dbg_script_runner) T_Ok(0); } } - + // debugger is ready -- now invoke script if (t_dbg_script_invoke(&script, T_Dbg_DefaultTimeout) == 0) { t_errorf("ERROR: %S: failed to run to completion\n", user_data); T_Ok(0); } - + // clean up #if OS_WINDOWS HANDLE dbg_handle = OpenProcess(PROCESS_ALL_ACCESS, 0, g_dbg_pid); @@ -771,7 +853,7 @@ T_RunSig(dbg_script_runner) #else kill(g_dbg_pid, SIGKILL); #endif - + exit:; g_dbg_pid = 0; } @@ -780,31 +862,31 @@ internal void t_dbg_register_script_tests(Arena *arena, String8 folder_path) { Temp scratch = scratch_begin(&arena, 1); - + if ( ! folder_path_exists(folder_path)) { t_errorf("ERROR: this folder does not exists: %S\n", folder_path); return; } - + // gather file paths in a folder String8List paths = t_file_paths_from_dir(arena, folder_path); - + // register a test for each file for EachNode(n, String8Node, paths.first) { String8 file_path = n->string; - + // test files may contain dots for extensions we have to escape them when creating output folder for a test String8List file_name_parts = str8_split_by_string_chars(scratch.arena, str8_skip_last_slash(file_path), 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){ - .group = T_Group, - .label = (char*)file_name_escaped.str, - .r = t_dbg_script_runner, - .user_data = str8_copy(arena, file_path), + .group = T_Group, + .label = (char*)file_name_escaped.str, + .r = t_dbg_script_runner, + .user_data = str8_copy(arena, file_path), }; } - + scratch_end(scratch); }