mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-05 21:38:40 +00:00
eliminate assumptions of module presence in unwinding codepaths, & callstack UI; fixes callstacks for JIT'd code
This commit is contained in:
@@ -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);
|
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);
|
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
|
// rjf: valid step -> push frame
|
||||||
DF_UnwindFrame *frame = push_array(arena, DF_UnwindFrame, 1);
|
DF_UnwindFrame *frame = push_array(arena, DF_UnwindFrame, 1);
|
||||||
frame->rip = rip;
|
frame->rip = rip;
|
||||||
|
|||||||
+30
-6
@@ -1797,7 +1797,7 @@ DF_VIEW_UI_FUNCTION_DEF(Empty)
|
|||||||
UI_Flags(UI_BoxFlag_DrawBorder)
|
UI_Flags(UI_BoxFlag_DrawBorder)
|
||||||
UI_TextAlignment(UI_TextAlign_Center)
|
UI_TextAlignment(UI_TextAlign_Center)
|
||||||
df_cmd_binding_button(spec);
|
df_cmd_binding_button(spec);
|
||||||
ui_labelf(", or start typing, to open command menu");
|
ui_labelf("to open command menu");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
@@ -3914,8 +3914,8 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack)
|
|||||||
// rjf: rip_vaddr => module
|
// rjf: rip_vaddr => module
|
||||||
DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
|
DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
|
||||||
|
|
||||||
// rjf: module => validity?
|
// rjf: rip => validity?
|
||||||
B32 frame_valid = !df_entity_is_nil(module);
|
B32 frame_valid = (rip_vaddr != 0);
|
||||||
|
|
||||||
// rjf: build row
|
// rjf: build row
|
||||||
if(frame_valid) UI_NamedTableVectorF("###callstack_%p_%I64x", view, frame_idx)
|
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
|
// rjf: build cell for module
|
||||||
UI_TableCell UI_FocusHot((row_selected && cs->cursor.x == 1) ? UI_FocusKind_On : UI_FocusKind_Off)
|
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
|
// rjf: build cell for function name
|
||||||
@@ -5628,9 +5642,19 @@ DF_VIEW_CMD_FUNCTION_DEF(Disassembly)
|
|||||||
default: break;
|
default: break;
|
||||||
case DF_CoreCmdKind_GoToAddress:
|
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->base_vaddr = params.vaddr;
|
||||||
dv->goto_vaddr = params.vaddr;
|
dv->goto_vaddr = params.vaddr;
|
||||||
|
|||||||
+45
-45
@@ -236,56 +236,56 @@ pe_bin_info_from_data(Arena *arena, String8 data)
|
|||||||
internal U64
|
internal U64
|
||||||
pe_intel_pdata_off_from_voff__binary_search(String8 data, PE_BinInfo *bin, U64 voff)
|
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;
|
U64 result = 0;
|
||||||
|
if(bin->arch != Architecture_Null)
|
||||||
// check if this bin includes a pdata array
|
|
||||||
if(pdata_count > 0)
|
|
||||||
{
|
{
|
||||||
PE_IntelPdata *pdata_array = (PE_IntelPdata*)(data.str + pdata_off);
|
Rng1U64 range = bin->data_dir_franges[PE_DataDirectoryIndex_EXCEPTIONS];
|
||||||
if(voff >= pdata_array[0].voff_first)
|
U64 pdata_off = range.min;
|
||||||
{
|
U64 pdata_count = (range.max - range.min)/sizeof(PE_IntelPdata);
|
||||||
// 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(;;)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we are in range fill result
|
// check if this bin includes a pdata array
|
||||||
|
if(pdata_count > 0)
|
||||||
|
{
|
||||||
|
PE_IntelPdata *pdata_array = (PE_IntelPdata*)(data.str + pdata_off);
|
||||||
|
if(voff >= pdata_array[0].voff_first)
|
||||||
{
|
{
|
||||||
PE_IntelPdata *pdata = pdata_array + index;
|
// binary search:
|
||||||
if(pdata->voff_first <= voff && voff < pdata->voff_one_past_last)
|
// 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(;;)
|
||||||
{
|
{
|
||||||
result = pdata_off + index*sizeof(PE_IntelPdata);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-41
@@ -1,49 +1,18 @@
|
|||||||
// Copyright (c) 2024 Epic Games Tools
|
// Copyright (c) 2024 Epic Games Tools
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
// build with:
|
#include <stdio.h>
|
||||||
// cl /Zi /nologo look_at_raddbg.c
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "raddbg_format/raddbg_format.h"
|
#include <windows.h>
|
||||||
#include "raddbg_format/raddbg_format_parse.h"
|
|
||||||
#include "raddbg_format/raddbg_format.c"
|
|
||||||
#include "raddbg_format/raddbg_format_parse.c"
|
|
||||||
|
|
||||||
typedef struct Foo Foo;
|
int main(void) {
|
||||||
struct Foo
|
printf("1\n");
|
||||||
{
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
int z;
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argument_count, char **arguments)
|
VOID *code = VirtualAlloc(0, 0x1000, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||||
{
|
*((uint32_t*)code) = 0xCCCCCCCC;
|
||||||
Foo foo = {123, 456, 789};
|
|
||||||
HANDLE file = CreateFileA(arguments[1], GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
((void (__fastcall *)()) code)();
|
||||||
DWORD size_hi32 = 0;
|
|
||||||
DWORD size_lo32 = GetFileSize(file, &size_hi32);
|
printf("2\n");
|
||||||
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);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user