From 804a8406b9f65eaaa621f1dcdee8e57959e8e018 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 23 Jan 2024 14:26:43 -0800 Subject: [PATCH] eliminate assumptions of module presence in unwinding codepaths, & callstack UI; fixes callstacks for JIT'd code --- src/df/core/df_core.c | 7 ---- src/df/gfx/df_views.c | 36 +++++++++++++--- src/pe/pe.c | 86 +++++++++++++++++++------------------- src/scratch/ryan_scratch.c | 53 +++++------------------ 4 files changed, 84 insertions(+), 98 deletions(-) diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index 13aa73b3..7250ec17 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -3621,13 +3621,6 @@ df_push_unwind_from_thread(Arena *arena, DF_Entity *thread) DBGI_Parse *dbgi = dbgi_parse_from_exe_path(scope, binary_full_path, 0); String8 binary_data = str8((U8 *)dbgi->exe_base, dbgi->exe_props.size); - // rjf: cancel on bad data - if(binary_data.size == 0) - { - unwind.error = 1; - break; - } - // rjf: valid step -> push frame DF_UnwindFrame *frame = push_array(arena, DF_UnwindFrame, 1); frame->rip = rip; diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 4f45ea90..9ed2d0c6 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -1797,7 +1797,7 @@ DF_VIEW_UI_FUNCTION_DEF(Empty) UI_Flags(UI_BoxFlag_DrawBorder) UI_TextAlignment(UI_TextAlign_Center) df_cmd_binding_button(spec); - ui_labelf(", or start typing, to open command menu"); + ui_labelf("to open command menu"); } } scratch_end(scratch); @@ -3914,8 +3914,8 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) // rjf: rip_vaddr => module DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); - // rjf: module => validity? - B32 frame_valid = !df_entity_is_nil(module); + // rjf: rip => validity? + B32 frame_valid = (rip_vaddr != 0); // rjf: build row if(frame_valid) UI_NamedTableVectorF("###callstack_%p_%I64x", view, frame_idx) @@ -3951,7 +3951,21 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) // rjf: build cell for module UI_TableCell UI_FocusHot((row_selected && cs->cursor.x == 1) ? UI_FocusKind_On : UI_FocusKind_Off) { - df_entity_desc_button(ws, module); + if(df_entity_is_nil(module)) UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText)) + { + UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_DrawText|UI_BoxFlag_Clickable, "(No Module)###moduleless_frame_%I64x", frame_idx); + UI_Signal sig = ui_signal_from_box(box); + if(sig.pressed) + { + next_cursor = v2s64(1, (S64)frame_idx+1); + DF_CmdParams p = df_cmd_params_from_panel(ws, panel); + df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FocusPanel)); + } + } + else + { + df_entity_desc_button(ws, module); + } } // rjf: build cell for function name @@ -5628,9 +5642,19 @@ DF_VIEW_CMD_FUNCTION_DEF(Disassembly) default: break; case DF_CoreCmdKind_GoToAddress: { - if(!df_entity_is_nil(df_entity_from_handle(params.entity))) + DF_Entity *entity = df_entity_from_handle(params.entity); + if(!df_entity_is_nil(entity) && + (entity->kind == DF_EntityKind_Process || + entity->kind == DF_EntityKind_Thread || + entity->kind == DF_EntityKind_Module)) { - dv->process = params.entity; + DF_Entity *process = entity; + if(entity->kind == DF_EntityKind_Thread || + entity->kind == DF_EntityKind_Module) + { + process = df_entity_ancestor_from_kind(process, DF_EntityKind_Process); + } + dv->process = df_handle_from_entity(process); } dv->base_vaddr = params.vaddr; dv->goto_vaddr = params.vaddr; diff --git a/src/pe/pe.c b/src/pe/pe.c index c41e2d0b..1e539c60 100644 --- a/src/pe/pe.c +++ b/src/pe/pe.c @@ -236,56 +236,56 @@ pe_bin_info_from_data(Arena *arena, String8 data) internal U64 pe_intel_pdata_off_from_voff__binary_search(String8 data, PE_BinInfo *bin, U64 voff) { - // TODO(allen): cleanup pass. - Assert(bin->arch == Architecture_x86 || bin->arch == Architecture_x64); - Rng1U64 range = bin->data_dir_franges[PE_DataDirectoryIndex_EXCEPTIONS]; - U64 pdata_off = range.min; - U64 pdata_count = (range.max - range.min)/sizeof(PE_IntelPdata); - U64 result = 0; - - // check if this bin includes a pdata array - if(pdata_count > 0) + if(bin->arch != Architecture_Null) { - PE_IntelPdata *pdata_array = (PE_IntelPdata*)(data.str + pdata_off); - if(voff >= pdata_array[0].voff_first) + Rng1U64 range = bin->data_dir_franges[PE_DataDirectoryIndex_EXCEPTIONS]; + U64 pdata_off = range.min; + U64 pdata_count = (range.max - range.min)/sizeof(PE_IntelPdata); + + // check if this bin includes a pdata array + if(pdata_count > 0) { - // binary search: - // find max index s.t. pdata_array[index].voff_first <= voff - // we assume (i < j) -> (pdata_array[i].voff_first < pdata_array[j].voff_first) - U64 index = pdata_count; - U64 min = 0; - U64 opl = pdata_count; - for(;;) + PE_IntelPdata *pdata_array = (PE_IntelPdata*)(data.str + pdata_off); + if(voff >= pdata_array[0].voff_first) { - U64 mid = (min + opl)/2; - PE_IntelPdata *pdata = pdata_array + mid; - if(voff < pdata->voff_first) + // binary search: + // find max index s.t. pdata_array[index].voff_first <= voff + // we assume (i < j) -> (pdata_array[i].voff_first < pdata_array[j].voff_first) + U64 index = pdata_count; + U64 min = 0; + U64 opl = pdata_count; + for(;;) { - opl = mid; + U64 mid = (min + opl)/2; + PE_IntelPdata *pdata = pdata_array + mid; + if(voff < pdata->voff_first) + { + opl = mid; + } + else if(pdata->voff_first < voff) + { + min = mid; + } + else + { + index = mid; + break; + } + if(min + 1 >= opl) + { + index = min; + break; + } } - else if(pdata->voff_first < voff) + + // if we are in range fill result { - min = mid; - } - else - { - index = mid; - break; - } - if(min + 1 >= opl) - { - index = min; - break; - } - } - - // if we are in range fill result - { - PE_IntelPdata *pdata = pdata_array + index; - if(pdata->voff_first <= voff && voff < pdata->voff_one_past_last) - { - result = pdata_off + index*sizeof(PE_IntelPdata); + PE_IntelPdata *pdata = pdata_array + index; + if(pdata->voff_first <= voff && voff < pdata->voff_one_past_last) + { + result = pdata_off + index*sizeof(PE_IntelPdata); + } } } } diff --git a/src/scratch/ryan_scratch.c b/src/scratch/ryan_scratch.c index 142e4219..ab90d162 100644 --- a/src/scratch/ryan_scratch.c +++ b/src/scratch/ryan_scratch.c @@ -1,49 +1,18 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -// build with: -// cl /Zi /nologo look_at_raddbg.c - -#include +#include #include -#include "raddbg_format/raddbg_format.h" -#include "raddbg_format/raddbg_format_parse.h" -#include "raddbg_format/raddbg_format.c" -#include "raddbg_format/raddbg_format_parse.c" +#include -typedef struct Foo Foo; -struct Foo -{ - int x; - int y; - int z; -}; - -int main(int argument_count, char **arguments) -{ - Foo foo = {123, 456, 789}; - HANDLE file = CreateFileA(arguments[1], GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - DWORD size_hi32 = 0; - DWORD size_lo32 = GetFileSize(file, &size_hi32); - HANDLE map = CreateFileMappingA(file, 0, PAGE_READONLY, 0, 0, 0); - uint64_t data_size = (size_lo32 | ((uint64_t)size_hi32 << 32)); - uint8_t *data = (uint8_t *)MapViewOfFile(map, FILE_MAP_READ, 0, 0, data_size); - RADDBG_Parsed rdbg = {0}; - RADDBG_ParseStatus parse_status = raddbg_parse(data, data_size, &rdbg); - uint64_t foo_count = 0; - for(uint64_t idx = 0; idx < rdbg.type_node_count; idx += 1) - { - RADDBG_TypeNode *type_node = &rdbg.type_nodes[idx]; - if(RADDBG_TypeKind_FirstUserDefined <= type_node->kind && type_node->kind <= RADDBG_TypeKind_LastUserDefined) - { - uint64_t name_size = 0; - uint8_t *name = raddbg_string_from_idx(&rdbg, type_node->user_defined.name_string_idx, &name_size); - if(name_size == 3 && name[0] == 'f' && name[1] == 'o' && name[2] == 'o') - { - foo_count += 1; - } - } - } - printf("%s -> %I64u foos\n", arguments[1], foo_count); +int main(void) { + printf("1\n"); + + VOID *code = VirtualAlloc(0, 0x1000, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE); + *((uint32_t*)code) = 0xCCCCCCCC; + + ((void (__fastcall *)()) code)(); + + printf("2\n"); return 0; }