mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-09-22 17:20:05 +00:00
Compare commits
28
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2d72bd7ab | ||
|
|
268ca9ab53 | ||
|
|
dea5e88906 | ||
|
|
25c31b0d77 | ||
|
|
ea2066063a | ||
|
|
bdecb6d522 | ||
|
|
739d0977b6 | ||
|
|
717572c202 | ||
|
|
d3931fd3e2 | ||
|
|
a0a6fc0988 | ||
|
|
7d8f0d478e | ||
|
|
d849b83acb | ||
|
|
adbe42c907 | ||
|
|
99b2d9d6d0 | ||
|
|
5c179adb68 | ||
|
|
de6c94ce8f | ||
|
|
743984c318 | ||
|
|
a026ae41f1 | ||
|
|
114dd96e50 | ||
|
|
e2e1382508 | ||
|
|
1c40afc067 | ||
|
|
79677875c4 | ||
|
|
c2e90225b9 | ||
|
|
057a6f3e8e | ||
|
|
a9ec1a05b1 | ||
|
|
2454d426ed | ||
|
|
cf58137b0f | ||
|
|
c40d0b3acc |
@@ -43,11 +43,11 @@ if "%asan%"=="1" set auto_compile_flags=%auto_compile_flags% -fsanitize=add
|
|||||||
:: --- Compile/Link Line Definitions ------------------------------------------
|
:: --- Compile/Link Line Definitions ------------------------------------------
|
||||||
set cl_common= /I..\src\ /I..\local\ /nologo /FC /Z7 /MP
|
set cl_common= /I..\src\ /I..\local\ /nologo /FC /Z7 /MP
|
||||||
set clang_common= -I..\src\ -I..\local\ -maes -mssse3 -msse4 -gcodeview -fdiagnostics-absolute-paths -Wall -Wno-unknown-warning-option -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf
|
set clang_common= -I..\src\ -I..\local\ -maes -mssse3 -msse4 -gcodeview -fdiagnostics-absolute-paths -Wall -Wno-unknown-warning-option -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf
|
||||||
set cl_debug= call cl /Od /D_DEBUG %cl_common%
|
set cl_debug= call cl /Od %cl_common%
|
||||||
set cl_release= call cl /O2 /DNDEBUG %cl_common%
|
set cl_release= call cl /O2 /DNDEBUG %cl_common%
|
||||||
set clang_debug= call clang -g -O0 -D_DEBUG %clang_common%
|
set clang_debug= call clang -g -O0 %clang_common%
|
||||||
set clang_release= call clang -g -O3 -DNDEBUG %clang_common%
|
set clang_release= call clang -g -O3 -DNDEBUG %clang_common%
|
||||||
set cl_link= /link /natvis:"%~dp0\src\natvis\base.natvis"
|
set cl_link= /link /INCREMENTAL:NO /natvis:"%~dp0\src\natvis\base.natvis"
|
||||||
set clang_link= -Xlinker /natvis:"%~dp0\src\natvis\base.natvis"
|
set clang_link= -Xlinker /natvis:"%~dp0\src\natvis\base.natvis"
|
||||||
set cl_out= /out:
|
set cl_out= /out:
|
||||||
set clang_out= -o
|
set clang_out= -o
|
||||||
@@ -90,9 +90,11 @@ if "%raddbg_from_pdb%"=="1" %compile% ..\src\raddbg_convert\pdb\r
|
|||||||
if "%raddbg_from_dwarf%"=="1" %compile% ..\src\raddbg_convert\dwarf\raddbg_from_dwarf.c %compile_link% %out%raddbg_from_dwarf.exe
|
if "%raddbg_from_dwarf%"=="1" %compile% ..\src\raddbg_convert\dwarf\raddbg_from_dwarf.c %compile_link% %out%raddbg_from_dwarf.exe
|
||||||
if "%raddbg_dump%"=="1" %compile% ..\src\raddbg_dump\raddbg_dump.c %compile_link% %out%raddbg_dump.exe
|
if "%raddbg_dump%"=="1" %compile% ..\src\raddbg_dump\raddbg_dump.c %compile_link% %out%raddbg_dump.exe
|
||||||
if "%ryan_scratch%"=="1" %compile% ..\src\scratch\ryan_scratch.c %compile_link% %out%ryan_scratch.exe
|
if "%ryan_scratch%"=="1" %compile% ..\src\scratch\ryan_scratch.c %compile_link% %out%ryan_scratch.exe
|
||||||
|
if "%cpp_tests%"=="1" %compile% ..\src\scratch\i_hate_c_plus_plus.cpp %compile_link% %out%cpp_tests.exe
|
||||||
if "%look_at_raddbg%"=="1" %compile% ..\src\scratch\look_at_raddbg.c %compile_link% %out%look_at_raddbg.exe
|
if "%look_at_raddbg%"=="1" %compile% ..\src\scratch\look_at_raddbg.c %compile_link% %out%look_at_raddbg.exe
|
||||||
if "%mule_main%"=="1" del vc*.pdb mule*.pdb && %cl_release% /c ..\src\mule\mule_inline.cpp && %cl_release% /c ..\src\mule\mule_o2.cpp && %cl_debug% /EHsc ..\src\mule\mule_main.cpp ..\src\mule\mule_c.c mule_inline.obj mule_o2.obj
|
if "%mule_main%"=="1" del vc*.pdb mule*.pdb && %cl_release% /MT /c ..\src\mule\mule_inline.cpp && %cl_release% /MT /c ..\src\mule\mule_o2.cpp && %cl_debug% /MT /EHsc ..\src\mule\mule_main.cpp ..\src\mule\mule_c.c mule_inline.obj mule_o2.obj
|
||||||
if "%mule_module%"=="1" %compile% ..\src\mule\mule_module.cpp %compile_link% %link_dll% %out%mule_module.dll
|
if "%mule_module%"=="1" %compile% ..\src\mule\mule_module.cpp %compile_link% %link_dll% %out%mule_module.dll
|
||||||
|
if "%mule_hotload%"=="1" %compile% ..\src\mule\mule_hotload_main.c %compile_link% %out%mule_hotload.exe & %compile% ..\src\mule\mule_hotload_module_main.c %compile_link% %link_dll% %out%mule_hotload_module.dll
|
||||||
popd
|
popd
|
||||||
|
|
||||||
:: --- Unset ------------------------------------------------------------------
|
:: --- Unset ------------------------------------------------------------------
|
||||||
|
|||||||
@@ -54,6 +54,15 @@ commands =
|
|||||||
.save_dirty_files = true,
|
.save_dirty_files = true,
|
||||||
.cursor_at_end = false,
|
.cursor_at_end = false,
|
||||||
},
|
},
|
||||||
|
.rjf_f2 =
|
||||||
|
{
|
||||||
|
.win = "build raddbg_from_pdb",
|
||||||
|
.linux = "",
|
||||||
|
.out = "*compilation*",
|
||||||
|
.footer_panel = true,
|
||||||
|
.save_dirty_files = true,
|
||||||
|
.cursor_at_end = false,
|
||||||
|
},
|
||||||
.rjf_f3 =
|
.rjf_f3 =
|
||||||
{
|
{
|
||||||
.win = "pushd build && raddbg.exe && popd",
|
.win = "pushd build && raddbg.exe && popd",
|
||||||
@@ -121,6 +130,7 @@ fkey_command_override =
|
|||||||
.rjf =
|
.rjf =
|
||||||
{
|
{
|
||||||
.F1 = "rjf_f1",
|
.F1 = "rjf_f1",
|
||||||
|
.F2 = "rjf_f2",
|
||||||
.F3 = "rjf_f3",
|
.F3 = "rjf_f3",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ arena_alloc__sized(U64 init_res, U64 init_cmt)
|
|||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
cmt = res;
|
cmt = res;
|
||||||
#else
|
#else
|
||||||
cmt AlignPow2(init_cmt, page_size);
|
cmt = AlignPow2(init_cmt, page_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memory = os_reserve_large(res);
|
memory = os_reserve_large(res);
|
||||||
|
|||||||
+52
-42
@@ -1366,6 +1366,7 @@ ctrl_thread__next_demon_event(Arena *arena, CTRL_Msg *msg, DEMON_RunCtrls *run_c
|
|||||||
Temp scratch = scratch_begin(&arena, 1);
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
|
||||||
//- rjf: loop -> try to get event, run, repeat
|
//- rjf: loop -> try to get event, run, repeat
|
||||||
|
U64 spoof_old_ip_value = 0;
|
||||||
ProfScope("loop -> try to get event, run, repeat") for(B32 got_event = 0; got_event == 0;)
|
ProfScope("loop -> try to get event, run, repeat") for(B32 got_event = 0; got_event == 0;)
|
||||||
{
|
{
|
||||||
//- rjf: get next event
|
//- rjf: get next event
|
||||||
@@ -1437,7 +1438,6 @@ ctrl_thread__next_demon_event(Arena *arena, CTRL_Msg *msg, DEMON_RunCtrls *run_c
|
|||||||
{
|
{
|
||||||
// rjf: prep spoof
|
// rjf: prep spoof
|
||||||
B32 do_spoof = (spoof != 0 && run_ctrls->single_step_thread == 0);
|
B32 do_spoof = (spoof != 0 && run_ctrls->single_step_thread == 0);
|
||||||
U64 spoof_old_ip_value = 0;
|
|
||||||
U64 size_of_spoof = 0;
|
U64 size_of_spoof = 0;
|
||||||
if(do_spoof) ProfScope("prep spoof")
|
if(do_spoof) ProfScope("prep spoof")
|
||||||
{
|
{
|
||||||
@@ -1487,6 +1487,18 @@ ctrl_thread__next_demon_event(Arena *arena, CTRL_Msg *msg, DEMON_RunCtrls *run_c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- rjf: irrespective of what event came back, we should ALWAYS check the
|
||||||
|
// spoof's thread and see if it hit the spoof address, because we may have
|
||||||
|
// simply been sent other debug events first
|
||||||
|
if(spoof != 0)
|
||||||
|
{
|
||||||
|
U64 spoof_thread_rip = demon_read_ip(ctrl_demon_handle_from_ctrl(spoof->thread));
|
||||||
|
if(spoof_thread_rip == spoof->new_ip_value)
|
||||||
|
{
|
||||||
|
demon_write_ip(ctrl_demon_handle_from_ctrl(spoof->thread), spoof_old_ip_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//- rjf: push ctrl events associated with this demon event
|
//- rjf: push ctrl events associated with this demon event
|
||||||
CTRL_EventList evts = {0};
|
CTRL_EventList evts = {0};
|
||||||
ProfScope("push ctrl events associated with this demon event") switch(event->kind)
|
ProfScope("push ctrl events associated with this demon event") switch(event->kind)
|
||||||
@@ -1821,6 +1833,8 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
|
|||||||
str8_lit("wmain"),
|
str8_lit("wmain"),
|
||||||
str8_lit("WinMainCRTStartup"),
|
str8_lit("WinMainCRTStartup"),
|
||||||
str8_lit("wWinMainCRTStartup"),
|
str8_lit("wWinMainCRTStartup"),
|
||||||
|
str8_lit("mainCRTStartup"),
|
||||||
|
str8_lit("wmainCRTStartup"),
|
||||||
};
|
};
|
||||||
|
|
||||||
// rjf: find voff for one of the custom entry points attached to this msg
|
// rjf: find voff for one of the custom entry points attached to this msg
|
||||||
@@ -2122,10 +2136,14 @@ ctrl_thread__run(CTRL_Msg *msg)
|
|||||||
DEMON_Handle target_process = ctrl_demon_handle_from_ctrl(msg->parent);
|
DEMON_Handle target_process = ctrl_demon_handle_from_ctrl(msg->parent);
|
||||||
U64 spoof_ip_vaddr = 911;
|
U64 spoof_ip_vaddr = 911;
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
//- rjf: gather processes
|
//- rjf: gather processes
|
||||||
|
//
|
||||||
DEMON_HandleArray processes = demon_all_processes(scratch.arena);
|
DEMON_HandleArray processes = demon_all_processes(scratch.arena);
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
//- rjf: gather all initial breakpoints
|
//- rjf: gather all initial breakpoints
|
||||||
|
//
|
||||||
DEMON_TrapChunkList user_traps = {0};
|
DEMON_TrapChunkList user_traps = {0};
|
||||||
{
|
{
|
||||||
// rjf: resolve module-dependent user bps
|
// rjf: resolve module-dependent user bps
|
||||||
@@ -2147,6 +2165,7 @@ ctrl_thread__run(CTRL_Msg *msg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
//- rjf: single step "stuck threads"
|
//- rjf: single step "stuck threads"
|
||||||
//
|
//
|
||||||
// "Stuck threads" are threads that are already on a User BP and would hit
|
// "Stuck threads" are threads that are already on a User BP and would hit
|
||||||
@@ -2251,7 +2270,9 @@ ctrl_thread__run(CTRL_Msg *msg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
//- rjf: resolve trap net
|
//- rjf: resolve trap net
|
||||||
|
//
|
||||||
DEMON_TrapChunkList trap_net_traps = {0};
|
DEMON_TrapChunkList trap_net_traps = {0};
|
||||||
for(CTRL_TrapNode *node = msg->traps.first;
|
for(CTRL_TrapNode *node = msg->traps.first;
|
||||||
node != 0;
|
node != 0;
|
||||||
@@ -2261,14 +2282,18 @@ ctrl_thread__run(CTRL_Msg *msg)
|
|||||||
demon_trap_chunk_list_push(scratch.arena, &trap_net_traps, 256, &trap);
|
demon_trap_chunk_list_push(scratch.arena, &trap_net_traps, 256, &trap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
//- rjf: join user breakpoints and trap net traps
|
//- rjf: join user breakpoints and trap net traps
|
||||||
|
//
|
||||||
DEMON_TrapChunkList joined_traps = {0};
|
DEMON_TrapChunkList joined_traps = {0};
|
||||||
{
|
{
|
||||||
demon_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &user_traps);
|
demon_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &user_traps);
|
||||||
demon_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &trap_net_traps);
|
demon_trap_chunk_list_concat_shallow_copy(scratch.arena, &joined_traps, &trap_net_traps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
//- rjf: record start
|
//- rjf: record start
|
||||||
|
//
|
||||||
if(stop_event == 0)
|
if(stop_event == 0)
|
||||||
{
|
{
|
||||||
CTRL_EventList evts = {0};
|
CTRL_EventList evts = {0};
|
||||||
@@ -2277,31 +2302,37 @@ ctrl_thread__run(CTRL_Msg *msg)
|
|||||||
ctrl_c2u_push_events(&evts);
|
ctrl_c2u_push_events(&evts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
//- rjf: run loop
|
//- rjf: run loop
|
||||||
|
//
|
||||||
if(stop_event == 0)
|
if(stop_event == 0)
|
||||||
{
|
{
|
||||||
U64 sp_check_value = demon_read_sp(target_thread);
|
U64 sp_check_value = demon_read_sp(target_thread);
|
||||||
B32 spoof_mode = 0;
|
B32 spoof_mode = 0;
|
||||||
CTRL_Spoof spoof = {0};
|
CTRL_Spoof spoof = {0};
|
||||||
U64 spoof_1_return_ip = 0;
|
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
//////////////////////////
|
||||||
//- rjf: choose low level traps
|
//- rjf: choose low level traps
|
||||||
|
//
|
||||||
DEMON_TrapChunkList *trap_list = &joined_traps;
|
DEMON_TrapChunkList *trap_list = &joined_traps;
|
||||||
if(spoof_mode)
|
if(spoof_mode)
|
||||||
{
|
{
|
||||||
trap_list = &user_traps;
|
trap_list = &user_traps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
//- rjf: choose spoof
|
//- rjf: choose spoof
|
||||||
|
//
|
||||||
CTRL_Spoof *run_spoof = 0;
|
CTRL_Spoof *run_spoof = 0;
|
||||||
if(spoof_mode)
|
if(spoof_mode)
|
||||||
{
|
{
|
||||||
run_spoof = &spoof;
|
run_spoof = &spoof;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
//- rjf: setup run controls
|
//- rjf: setup run controls
|
||||||
|
//
|
||||||
DEMON_RunCtrls run_ctrls = {0};
|
DEMON_RunCtrls run_ctrls = {0};
|
||||||
run_ctrls.ignore_previous_exception = 1;
|
run_ctrls.ignore_previous_exception = 1;
|
||||||
run_ctrls.run_entity_count = msg->freeze_state_threads.count;
|
run_ctrls.run_entity_count = msg->freeze_state_threads.count;
|
||||||
@@ -2315,12 +2346,16 @@ ctrl_thread__run(CTRL_Msg *msg)
|
|||||||
idx += 1;
|
idx += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
run_ctrls.traps = *trap_list;
|
run_ctrls.traps = *trap_list;
|
||||||
|
|
||||||
//- rjf: get an event
|
//////////////////////////
|
||||||
|
//- rjf: get next event
|
||||||
|
//
|
||||||
DEMON_Event *event = ctrl_thread__next_demon_event(scratch.arena, msg, &run_ctrls, run_spoof);
|
DEMON_Event *event = ctrl_thread__next_demon_event(scratch.arena, msg, &run_ctrls, run_spoof);
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
//- rjf: determine event handling
|
//- rjf: determine event handling
|
||||||
|
//
|
||||||
B32 hard_stop = 0;
|
B32 hard_stop = 0;
|
||||||
CTRL_EventCause hard_stop_cause = ctrl_event_cause_from_demon_event_kind(event->kind);
|
CTRL_EventCause hard_stop_cause = ctrl_event_cause_from_demon_event_kind(event->kind);
|
||||||
B32 use_stepping_logic = 0;
|
B32 use_stepping_logic = 0;
|
||||||
@@ -2354,7 +2389,9 @@ ctrl_thread__run(CTRL_Msg *msg)
|
|||||||
}break;
|
}break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
//- rjf: unpack info about thread attached to event
|
//- rjf: unpack info about thread attached to event
|
||||||
|
//
|
||||||
Architecture arch = demon_arch_from_object(event->thread);
|
Architecture arch = demon_arch_from_object(event->thread);
|
||||||
U64 reg_size = regs_block_size_from_architecture(arch);
|
U64 reg_size = regs_block_size_from_architecture(arch);
|
||||||
void *thread_regs_block = demon_read_regs(event->thread);
|
void *thread_regs_block = demon_read_regs(event->thread);
|
||||||
@@ -2380,11 +2417,14 @@ ctrl_thread__run(CTRL_Msg *msg)
|
|||||||
temp_end(temp);
|
temp_end(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
//////////////////////////
|
||||||
//- rjf: stepping logic -//
|
//- rjf: stepping logic
|
||||||
|
//
|
||||||
//{
|
//{
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
//- rjf: handle if hitting a spoof or baked in trap
|
//- rjf: handle if hitting a spoof or baked in trap
|
||||||
|
//
|
||||||
B32 hit_spoof = 0;
|
B32 hit_spoof = 0;
|
||||||
B32 exception_stop = 0;
|
B32 exception_stop = 0;
|
||||||
if(use_stepping_logic)
|
if(use_stepping_logic)
|
||||||
@@ -2409,28 +2449,9 @@ ctrl_thread__run(CTRL_Msg *msg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- TODO(rjf): Jeff is hitting a bug where a spoof IP (911) has been
|
|
||||||
// hit by a thread, !!!BUT!!! we seemingly don't catch that until a
|
|
||||||
// subsequent run of this loop, probably because there are other
|
|
||||||
// events in the queue that we report first, losing all state about
|
|
||||||
// spoof mode.
|
|
||||||
//
|
|
||||||
// I'm throwing in some detection for this case, so that we can diagnose
|
|
||||||
// it further from there.
|
|
||||||
//
|
|
||||||
if(event->kind == DEMON_EventKind_Exception &&
|
|
||||||
event->instruction_pointer == 911 &&
|
|
||||||
(hit_spoof == 0 || spoof_mode == 0))
|
|
||||||
{
|
|
||||||
os_graphical_message(1, str8_lit("RADDBG INTERNAL DEVELOPMENT MESSAGE"), str8_lit("a bad, rare bug that Jeff found has been detected to occur - attach with debugger now"));
|
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: handle spoof hit
|
//- rjf: handle spoof hit
|
||||||
if(hit_spoof)
|
if(hit_spoof)
|
||||||
{
|
{
|
||||||
// rjf: restore 1 ip
|
|
||||||
demon_write_ip(target_thread, spoof_1_return_ip);
|
|
||||||
|
|
||||||
// rjf: clear spoof mode
|
// rjf: clear spoof mode
|
||||||
spoof_mode = 0;
|
spoof_mode = 0;
|
||||||
MemoryZeroStruct(&spoof);
|
MemoryZeroStruct(&spoof);
|
||||||
@@ -2673,15 +2694,12 @@ ctrl_thread__run(CTRL_Msg *msg)
|
|||||||
{
|
{
|
||||||
// rjf: setup spoof mode
|
// rjf: setup spoof mode
|
||||||
begin_spoof_mode = 1;
|
begin_spoof_mode = 1;
|
||||||
|
|
||||||
U64 spoof_sp = demon_read_sp(target_thread);
|
U64 spoof_sp = demon_read_sp(target_thread);
|
||||||
spoof_mode = 1;
|
spoof_mode = 1;
|
||||||
spoof.process = ctrl_handle_from_demon(target_process);
|
spoof.process = ctrl_handle_from_demon(target_process);
|
||||||
|
spoof.thread = ctrl_handle_from_demon(target_thread);
|
||||||
spoof.vaddr = spoof_sp;
|
spoof.vaddr = spoof_sp;
|
||||||
spoof.new_ip_value = spoof_ip_vaddr;
|
spoof.new_ip_value = spoof_ip_vaddr;
|
||||||
|
|
||||||
// rjf: remember 1 return ip
|
|
||||||
demon_read_memory(target_process, &spoof_1_return_ip, spoof_sp, sizeof(spoof_1_return_ip));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2715,7 +2733,8 @@ ctrl_thread__run(CTRL_Msg *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//}
|
//}
|
||||||
//- rjf: stepping logic -//
|
//
|
||||||
|
//- rjf: stepping logic
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
//- rjf: handle step past trap net
|
//- rjf: handle step past trap net
|
||||||
@@ -2786,20 +2805,11 @@ ctrl_thread__run(CTRL_Msg *msg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: unstick silently-hit spoofs
|
|
||||||
if(stop_event != 0 && stop_event->thread != target_thread && spoof_mode != 0)
|
|
||||||
{
|
|
||||||
U64 target_thread_rip = demon_read_ip(target_thread);
|
|
||||||
if(target_thread_rip == spoof.new_ip_value)
|
|
||||||
{
|
|
||||||
// rjf: restore 1 ip
|
|
||||||
demon_write_ip(target_thread, spoof_1_return_ip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
//- rjf: record stop
|
//- rjf: record stop
|
||||||
|
//
|
||||||
if(stop_event != 0)
|
if(stop_event != 0)
|
||||||
{
|
{
|
||||||
CTRL_EventList evts = {0};
|
CTRL_EventList evts = {0};
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ typedef struct CTRL_Spoof CTRL_Spoof;
|
|||||||
struct CTRL_Spoof
|
struct CTRL_Spoof
|
||||||
{
|
{
|
||||||
CTRL_Handle process;
|
CTRL_Handle process;
|
||||||
|
CTRL_Handle thread;
|
||||||
U64 vaddr;
|
U64 vaddr;
|
||||||
U64 new_ip_value;
|
U64 new_ip_value;
|
||||||
};
|
};
|
||||||
|
|||||||
+38
-66
@@ -44,7 +44,6 @@ dbgi_init(void)
|
|||||||
{
|
{
|
||||||
dbgi_shared->parse_threads[idx] = os_launch_thread(dbgi_parse_thread_entry_point, (void *)idx, 0);
|
dbgi_shared->parse_threads[idx] = os_launch_thread(dbgi_parse_thread_entry_point, (void *)idx, 0);
|
||||||
}
|
}
|
||||||
dbgi_shared->evictor_thread = os_launch_thread(dbgi_evictor_thread_entry_point, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@@ -253,9 +252,34 @@ dbgi_binary_close(String8 exe_path)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
B32 need_deletion = 0;
|
||||||
if(binary != 0 && binary->refcount>0)
|
if(binary != 0 && binary->refcount>0)
|
||||||
{
|
{
|
||||||
binary->refcount -= 1;
|
binary->refcount -= 1;
|
||||||
|
need_deletion = (binary->refcount == 0);
|
||||||
|
}
|
||||||
|
if(need_deletion) for(;;)
|
||||||
|
{
|
||||||
|
os_rw_mutex_drop_w(stripe->rw_mutex);
|
||||||
|
for(U64 start_t = os_now_microseconds();
|
||||||
|
os_now_microseconds() <= start_t + 250;);
|
||||||
|
os_rw_mutex_take_w(stripe->rw_mutex);
|
||||||
|
if(binary->refcount == 0 && ins_atomic_u64_eval(&binary->scope_touch_count) == 0)
|
||||||
|
{
|
||||||
|
if(binary->parse.arena != 0) { arena_release(binary->parse.arena); }
|
||||||
|
if(binary->parse.exe_base != 0) { os_file_map_view_close(binary->exe_file_map, binary->parse.exe_base); }
|
||||||
|
if(!os_handle_match(os_handle_zero(), binary->exe_file_map)) { os_file_map_close(binary->exe_file_map); }
|
||||||
|
if(!os_handle_match(os_handle_zero(), binary->exe_file)) { os_file_close(binary->exe_file); }
|
||||||
|
if(binary->parse.dbg_base != 0) { os_file_map_view_close(binary->dbg_file_map, binary->parse.dbg_base); }
|
||||||
|
if(!os_handle_match(os_handle_zero(), binary->dbg_file_map)) { os_file_map_close(binary->dbg_file_map); }
|
||||||
|
if(!os_handle_match(os_handle_zero(), binary->dbg_file)) { os_file_close(binary->dbg_file); }
|
||||||
|
binary->exe_file_map = binary->exe_file = os_handle_zero();
|
||||||
|
binary->dbg_file_map = binary->dbg_file = os_handle_zero();
|
||||||
|
MemoryZeroStruct(&binary->parse);
|
||||||
|
binary->last_time_enqueued_for_parse_us = 0;
|
||||||
|
binary->gen = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
@@ -294,7 +318,7 @@ dbgi_parse_from_exe_path(DBGI_Scope *scope, String8 exe_path, U64 endt_us)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if(!sent &&
|
else if(!sent &&
|
||||||
os_now_microseconds() >= ins_atomic_u64_eval(&binary->last_time_enqueued_for_parse_us)+1000000 &&
|
ins_atomic_u64_eval(&binary->last_time_enqueued_for_parse_us) == 0 &&
|
||||||
dbgi_u2p_enqueue_exe_path(exe_path, endt_us))
|
dbgi_u2p_enqueue_exe_path(exe_path, endt_us))
|
||||||
{
|
{
|
||||||
sent = 1;
|
sent = 1;
|
||||||
@@ -451,7 +475,7 @@ dbgi_parse_thread_entry_point(void *p)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(binary == 0 || binary->flags&DBGI_BinaryFlag_ParseInFlight)
|
if(binary == 0 || binary->flags&DBGI_BinaryFlag_ParseInFlight || binary->refcount == 0)
|
||||||
{
|
{
|
||||||
task_is_taken_by_other_thread = 1;
|
task_is_taken_by_other_thread = 1;
|
||||||
}
|
}
|
||||||
@@ -708,8 +732,10 @@ dbgi_parse_thread_entry_point(void *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: cache write, step 1: check if either EXE or raddbg file is new. if
|
//- rjf: cache write, step 1: check if refcount is still nonzero, &
|
||||||
// so, clear all old results & store new top-level info
|
// either EXE or raddbg file is new. if so, clear all old results &
|
||||||
|
// store new top-level info
|
||||||
|
B32 binary_refcount_is_zero = 0;
|
||||||
B32 raddbg_or_exe_file_is_updated = 0;
|
B32 raddbg_or_exe_file_is_updated = 0;
|
||||||
if(do_task) ProfScope("cache write, step 1: check if raddbg is new & clear")
|
if(do_task) ProfScope("cache write, step 1: check if raddbg is new & clear")
|
||||||
{
|
{
|
||||||
@@ -717,6 +743,11 @@ dbgi_parse_thread_entry_point(void *p)
|
|||||||
{
|
{
|
||||||
if(str8_match(bin->exe_path, exe_path, 0))
|
if(str8_match(bin->exe_path, exe_path, 0))
|
||||||
{
|
{
|
||||||
|
if(bin->refcount == 0)
|
||||||
|
{
|
||||||
|
binary_refcount_is_zero = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if(bin->parse.dbg_props.modified != raddbg_file_props.modified ||
|
if(bin->parse.dbg_props.modified != raddbg_file_props.modified ||
|
||||||
bin->parse.exe_props.modified != exe_file_props.modified)
|
bin->parse.exe_props.modified != exe_file_props.modified)
|
||||||
{
|
{
|
||||||
@@ -751,7 +782,7 @@ dbgi_parse_thread_entry_point(void *p)
|
|||||||
|
|
||||||
//- rjf: raddbg file or exe is not new? cache can stay unmodified, close
|
//- rjf: raddbg file or exe is not new? cache can stay unmodified, close
|
||||||
// handles & skip to end.
|
// handles & skip to end.
|
||||||
if(do_task) if(!raddbg_or_exe_file_is_updated) if(raddbg_file_is_up_to_date)
|
if(do_task) if((!raddbg_or_exe_file_is_updated && raddbg_file_is_up_to_date) || binary_refcount_is_zero)
|
||||||
{
|
{
|
||||||
os_file_map_view_close(raddbg_file_map, raddbg_file_base);
|
os_file_map_view_close(raddbg_file_map, raddbg_file_base);
|
||||||
os_file_map_close(raddbg_file_map);
|
os_file_map_close(raddbg_file_map);
|
||||||
@@ -759,6 +790,7 @@ dbgi_parse_thread_entry_point(void *p)
|
|||||||
os_file_map_view_close(exe_file_map, exe_file_base);
|
os_file_map_view_close(exe_file_map, exe_file_base);
|
||||||
os_file_map_close(exe_file_map);
|
os_file_map_close(exe_file_map);
|
||||||
os_file_close(exe_file);
|
os_file_close(exe_file);
|
||||||
|
arena_release(parse_arena);
|
||||||
do_task = 0;
|
do_task = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -826,63 +858,3 @@ dbgi_parse_thread_entry_point(void *p)
|
|||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Evictor Thread
|
|
||||||
|
|
||||||
internal void
|
|
||||||
dbgi_evictor_thread_entry_point(void *p)
|
|
||||||
{
|
|
||||||
TCTX tctx_;
|
|
||||||
tctx_init_and_equip(&tctx_);
|
|
||||||
ProfThreadName("[dbgi] evictor");
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
ProfBegin("eviction scan");
|
|
||||||
U64 slots_per_stripe = dbgi_shared->binary_slots_count/dbgi_shared->binary_stripes_count;
|
|
||||||
for(U64 stripe_idx = 0; stripe_idx < dbgi_shared->binary_stripes_count; stripe_idx += 1)
|
|
||||||
{
|
|
||||||
DBGI_BinaryStripe *stripe = &dbgi_shared->binary_stripes[stripe_idx];
|
|
||||||
for(U64 slot_in_stripe_idx = 0; slot_in_stripe_idx < slots_per_stripe; slot_in_stripe_idx += 1)
|
|
||||||
{
|
|
||||||
U64 slot_idx = slots_per_stripe*stripe_idx + slot_in_stripe_idx;
|
|
||||||
DBGI_BinarySlot *slot = &dbgi_shared->binary_slots[slot_idx];
|
|
||||||
B32 slot_needs_work = 0;
|
|
||||||
OS_MutexScopeR(stripe->rw_mutex)
|
|
||||||
{
|
|
||||||
for(DBGI_Binary *bin = slot->first; bin != 0; bin = bin->next)
|
|
||||||
{
|
|
||||||
if(bin->refcount == 0 && bin->scope_touch_count == 0 && bin->flags == 0 && bin->gen > 1)
|
|
||||||
{
|
|
||||||
slot_needs_work = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(slot_needs_work) ProfScope("eviction task (slot %I64u)", slot_idx) OS_MutexScopeW(stripe->rw_mutex)
|
|
||||||
{
|
|
||||||
for(DBGI_Binary *bin = slot->first; bin != 0; bin = bin->next)
|
|
||||||
{
|
|
||||||
if(bin->refcount == 0 && bin->scope_touch_count == 0 && bin->flags == 0)
|
|
||||||
{
|
|
||||||
if(bin->parse.arena != 0) { arena_release(bin->parse.arena); }
|
|
||||||
if(bin->parse.exe_base != 0) { os_file_map_view_close(bin->exe_file_map, bin->parse.exe_base); }
|
|
||||||
if(!os_handle_match(os_handle_zero(), bin->exe_file_map)) { os_file_map_close(bin->exe_file_map); }
|
|
||||||
if(!os_handle_match(os_handle_zero(), bin->exe_file)) { os_file_close(bin->exe_file); }
|
|
||||||
if(bin->parse.dbg_base != 0) { os_file_map_view_close(bin->dbg_file_map, bin->parse.dbg_base); }
|
|
||||||
if(!os_handle_match(os_handle_zero(), bin->dbg_file_map)) { os_file_map_close(bin->dbg_file_map); }
|
|
||||||
if(!os_handle_match(os_handle_zero(), bin->dbg_file)) { os_file_close(bin->dbg_file); }
|
|
||||||
bin->exe_file_map = bin->exe_file = os_handle_zero();
|
|
||||||
bin->dbg_file_map = bin->dbg_file = os_handle_zero();
|
|
||||||
MemoryZeroStruct(&bin->parse);
|
|
||||||
bin->last_time_enqueued_for_parse_us = 0;
|
|
||||||
bin->gen = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ProfEnd();
|
|
||||||
os_sleep_milliseconds(250);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -198,7 +198,6 @@ struct DBGI_Shared
|
|||||||
// rjf: threads
|
// rjf: threads
|
||||||
U64 parse_thread_count;
|
U64 parse_thread_count;
|
||||||
OS_Handle *parse_threads;
|
OS_Handle *parse_threads;
|
||||||
OS_Handle evictor_thread;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@@ -254,9 +253,4 @@ internal DBGI_EventList dbgi_p2u_pop_events(Arena *arena, U64 endt_us);
|
|||||||
|
|
||||||
internal void dbgi_parse_thread_entry_point(void *p);
|
internal void dbgi_parse_thread_entry_point(void *p);
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ rjf: Evictor Thread
|
|
||||||
|
|
||||||
internal void dbgi_evictor_thread_entry_point(void *p);
|
|
||||||
|
|
||||||
#endif //DBGI_H
|
#endif //DBGI_H
|
||||||
|
|||||||
+211
-31
@@ -2642,6 +2642,98 @@ df_debug_info_path_from_module(Arena *arena, DF_Entity *module)
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Stepping "Trap Net" Builders
|
//~ rjf: Stepping "Trap Net" Builders
|
||||||
|
|
||||||
|
// NOTE(rjf): Stepping Algorithm Overview (2024/01/17)
|
||||||
|
//
|
||||||
|
// The basic idea behind all stepping algorithms in the debugger are setting up
|
||||||
|
// a "trap net". A "trap net" is just a collection of high-level traps that are
|
||||||
|
// meant to "catch" a thread after letting it run. This trap net is submitted
|
||||||
|
// when the debugger frontend sends a "run" command (it is just empty if doing
|
||||||
|
// an actual 'run' or 'continue'). The debugger control thread then uses this
|
||||||
|
// trap net to program a state machine, to appropriately respond to a variety
|
||||||
|
// of debug events which it is passed from the OS.
|
||||||
|
//
|
||||||
|
// These are "high-level traps" because they can have specific behavioral info
|
||||||
|
// attached to them. These are encoded via the `CTRL_TrapFlags` type, which
|
||||||
|
// allow expression of the following behaviors:
|
||||||
|
//
|
||||||
|
// - end-stepping: when this trap is hit, it will end the stepping operation,
|
||||||
|
// and the target will not continue.
|
||||||
|
// - ignore-stack-pointer-check: when a trap in the trap net is hit, it will
|
||||||
|
// by-default be ignored if the thread's stack pointer has changed. this
|
||||||
|
// flag disables that behavior, for when the stack pointer is expected to
|
||||||
|
// change (e.g. step-out).
|
||||||
|
// - single-step-after-hit: when a trap with this flag is hit, the debugger
|
||||||
|
// will immediately single-step the thread which hit it.
|
||||||
|
// - save-stack-pointer: when a trap with this flag is hit, it will rewrite
|
||||||
|
// the stack pointer which is used to compare against, when deciding
|
||||||
|
// whether or not to filter a trap (based on stack pointer changes).
|
||||||
|
// - begin-spoof-mode: this enables "spoof mode". "spoof mode" is a special
|
||||||
|
// mode that disables the trap net entirely, and lets the thread run
|
||||||
|
// freely - but it catches the thread not with a trap, but a false return
|
||||||
|
// address. the debugger will overwrite a specific return address on the
|
||||||
|
// stack. this address will be overwritten with an address which does NOT
|
||||||
|
// point to a valid page, such that when the thread returns out of a
|
||||||
|
// particular call frame, the debugger will receive a debug event, at
|
||||||
|
// which point it can move the thread back to the correct return address,
|
||||||
|
// and resume with the trap net enabled. this is used in "step over"
|
||||||
|
// operations, because it avoids target <-> debugger "roundtrips" (e.g.
|
||||||
|
// target being stopped, debugger being called with debug events, then
|
||||||
|
// target resumes when debugger's control thread is done running) for
|
||||||
|
// recursions. (it doesn't make a difference with non-recursive calls,
|
||||||
|
// but the debugger can't detect the difference).
|
||||||
|
//
|
||||||
|
// Each stepping command prepares its trap net differently.
|
||||||
|
//
|
||||||
|
// --- Instruction Step Into --------------------------------------------------
|
||||||
|
// In this case, no trap net is prepared, and only a low-level single-step is
|
||||||
|
// performed.
|
||||||
|
//
|
||||||
|
// --- Instruction Step Over --------------------------------------------------
|
||||||
|
// To build a trap net for an instruction-level step-over, the next instruction
|
||||||
|
// at the thread's current instruction pointer is decoded. If it is a call
|
||||||
|
// instruction, or if it is a repeating instruction, then a trap with the
|
||||||
|
// 'end-stepping' behavior is placed at the instruction immediately following
|
||||||
|
// the 'call' instruction.
|
||||||
|
//
|
||||||
|
// --- Line Step Into ---------------------------------------------------------
|
||||||
|
// For a source-line step-into, the thread's instruction pointer is first used
|
||||||
|
// to look up into the debug info's line info, to find the machine code in the
|
||||||
|
// thread's current source line. Every instruction in this range is decoded.
|
||||||
|
// Traps are then built in the following way:
|
||||||
|
//
|
||||||
|
// - 'call' instruction -> if can decode call destination address, place
|
||||||
|
// "end-stepping | ignore-stack-pointer-check" trap at destination. if
|
||||||
|
// can't, "end-stepping | single-step-after | ignore-stack-pointer-check"
|
||||||
|
// trap at call.
|
||||||
|
// - 'jmp' (both unconditional & conditional) -> if can decode jump destination
|
||||||
|
// address, AND if jump leaves the line, place "end-stepping | ignore-
|
||||||
|
// stack-pointer-check" trap at destination. if can't, "end-stepping |
|
||||||
|
// single-step-after | ignore-stack-pointer-check" trap at jmp. if jump
|
||||||
|
// stays within the line, do nothing.
|
||||||
|
// - 'return' -> place "end-stepping | single-step-after" trap at return inst.
|
||||||
|
// - "end-stepping" trap is placed at the first address after the line, to
|
||||||
|
// catch all steps which simply proceed linearly through the instruction
|
||||||
|
// stream.
|
||||||
|
//
|
||||||
|
// --- Line Step Over ---------------------------------------------------------
|
||||||
|
// For a source-line step-over, the thread's instruction pointer is first used
|
||||||
|
// to look up into the debug info's line info, to find the machine code in the
|
||||||
|
// thread's current source line. Every instruction in this range is decoded.
|
||||||
|
// Traps are then built in the following way:
|
||||||
|
//
|
||||||
|
// - 'call' instruction -> place "single-step-after | begin-spoof-mode" trap at
|
||||||
|
// call instruction.
|
||||||
|
// - 'jmp' (both unconditional & conditional) -> if can decode jump destination
|
||||||
|
// address, AND if jump leaves the line, place "end-stepping" trap at
|
||||||
|
// destination. if can't, "end-stepping | single-step-after" trap at jmp.
|
||||||
|
// if jump stays within the line, do nothing.
|
||||||
|
// - 'return' -> place "end-stepping | single-step-after" trap at return inst.
|
||||||
|
// - "end-stepping" trap is placed at the first address after the line, to
|
||||||
|
// catch all steps which simply proceed linearly through the instruction
|
||||||
|
// stream.
|
||||||
|
// - for any instructions which may change the stack pointer, traps are placed
|
||||||
|
// at them with the "save-stack-pointer | single-step-after" behaviors.
|
||||||
|
|
||||||
internal CTRL_TrapList
|
internal CTRL_TrapList
|
||||||
df_trap_net_from_thread__step_over_inst(Arena *arena, DF_Entity *thread)
|
df_trap_net_from_thread__step_over_inst(Arena *arena, DF_Entity *thread)
|
||||||
{
|
{
|
||||||
@@ -2869,23 +2961,6 @@ df_trap_net_from_thread__step_into_line(Arena *arena, DF_Entity *thread)
|
|||||||
{
|
{
|
||||||
trap_addr = point->jump_dest_vaddr;
|
trap_addr = point->jump_dest_vaddr;
|
||||||
flags &= ~CTRL_TrapFlag_SingleStepAfterHit;
|
flags &= ~CTRL_TrapFlag_SingleStepAfterHit;
|
||||||
|
|
||||||
// rjf: read instruction one layer deep after a jump and determine if
|
|
||||||
// it is just jumping to an unconditional jump (e.g. a function
|
|
||||||
// dispatch table) - if so, then just follow one more layer
|
|
||||||
String8 dst_machine_code = {0};
|
|
||||||
dst_machine_code.str = push_array_no_zero(scratch.arena, U8, max_instruction_size_from_arch(arch));
|
|
||||||
dst_machine_code.size = ctrl_process_read(process->ctrl_machine_id, process->ctrl_handle, r1u64(trap_addr, trap_addr+max_instruction_size_from_arch(arch)), dst_machine_code.str);
|
|
||||||
if(dst_machine_code.size != 0)
|
|
||||||
{
|
|
||||||
DF_Inst inst = df_single_inst_from_machine_code(scratch.arena, arch, 0, dst_machine_code);
|
|
||||||
if((inst.flags & DF_InstFlag_UnconditionalJump ||
|
|
||||||
inst.flags & DF_InstFlag_Call) &&
|
|
||||||
inst.rel_voff != 0)
|
|
||||||
{
|
|
||||||
trap_addr = (U64)(trap_addr + (S64)((S32)inst.rel_voff));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3015,7 +3090,7 @@ df_symbol_name_from_binary_voff(Arena *arena, DF_Entity *binary, U64 voff)
|
|||||||
String8 path = df_full_path_from_entity(scratch.arena, binary);
|
String8 path = df_full_path_from_entity(scratch.arena, binary);
|
||||||
DBGI_Parse *dbgi = dbgi_parse_from_exe_path(scope, path, 0);
|
DBGI_Parse *dbgi = dbgi_parse_from_exe_path(scope, path, 0);
|
||||||
RADDBG_Parsed *rdbg = &dbgi->rdbg;
|
RADDBG_Parsed *rdbg = &dbgi->rdbg;
|
||||||
if(rdbg->scope_vmap != 0)
|
if(result.size == 0 && rdbg->scope_vmap != 0)
|
||||||
{
|
{
|
||||||
U64 scope_idx = raddbg_vmap_idx_from_voff(rdbg->scope_vmap, rdbg->scope_vmap_count, voff);
|
U64 scope_idx = raddbg_vmap_idx_from_voff(rdbg->scope_vmap, rdbg->scope_vmap_count, voff);
|
||||||
RADDBG_Scope *scope = &rdbg->scopes[scope_idx];
|
RADDBG_Scope *scope = &rdbg->scopes[scope_idx];
|
||||||
@@ -3025,6 +3100,14 @@ df_symbol_name_from_binary_voff(Arena *arena, DF_Entity *binary, U64 voff)
|
|||||||
U8 *name_ptr = raddbg_string_from_idx(rdbg, procedure->name_string_idx, &name_size);
|
U8 *name_ptr = raddbg_string_from_idx(rdbg, procedure->name_string_idx, &name_size);
|
||||||
result = push_str8_copy(arena, str8(name_ptr, name_size));
|
result = push_str8_copy(arena, str8(name_ptr, name_size));
|
||||||
}
|
}
|
||||||
|
if(result.size == 0 && rdbg->global_vmap != 0)
|
||||||
|
{
|
||||||
|
U64 global_idx = raddbg_vmap_idx_from_voff(rdbg->global_vmap, rdbg->global_vmap_count, voff);
|
||||||
|
RADDBG_GlobalVariable *global_var = &rdbg->global_variables[global_idx];
|
||||||
|
U64 name_size = 0;
|
||||||
|
U8 *name_ptr = raddbg_string_from_idx(rdbg, global_var->name_string_idx, &name_size);
|
||||||
|
result = push_str8_copy(arena, str8(name_ptr, name_size));
|
||||||
|
}
|
||||||
dbgi_scope_close(scope);
|
dbgi_scope_close(scope);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
@@ -4064,6 +4147,19 @@ df_eval_from_string(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- rjf: unpack module info & produce eval machine
|
||||||
|
DF_Entity *module = df_module_from_process_vaddr(process, thread_unwind_ip_vaddr);
|
||||||
|
U64 module_base = df_base_vaddr_from_module(module);
|
||||||
|
U64 tls_base = df_tls_base_vaddr_from_thread(thread);
|
||||||
|
EVAL_Machine machine = {0};
|
||||||
|
machine.u = (void *)thread->parent;
|
||||||
|
machine.arch = arch;
|
||||||
|
machine.memory_read = df_eval_memory_read;
|
||||||
|
machine.reg_data = thread_unwind_regs_block;
|
||||||
|
machine.reg_size = reg_size;
|
||||||
|
machine.module_base = &module_base;
|
||||||
|
machine.tls_base = &tls_base;
|
||||||
|
|
||||||
//- rjf: lex & parse
|
//- rjf: lex & parse
|
||||||
EVAL_TokenArray tokens = eval_token_array_from_text(arena, string);
|
EVAL_TokenArray tokens = eval_token_array_from_text(arena, string);
|
||||||
EVAL_ParseResult parse = eval_parse_expr_from_text_tokens(arena, parse_ctx, string, &tokens);
|
EVAL_ParseResult parse = eval_parse_expr_from_text_tokens(arena, parse_ctx, string, &tokens);
|
||||||
@@ -4092,23 +4188,10 @@ df_eval_from_string(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_
|
|||||||
bytecode = eval_bytecode_from_oplist(arena, &op_list);
|
bytecode = eval_bytecode_from_oplist(arena, &op_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: grab thread/module
|
|
||||||
DF_Entity *module = df_module_from_process_vaddr(process, thread_unwind_ip_vaddr);
|
|
||||||
|
|
||||||
//- rjf: evaluate
|
//- rjf: evaluate
|
||||||
EVAL_Result eval = {0};
|
EVAL_Result eval = {0};
|
||||||
if(bytecode.size != 0)
|
if(bytecode.size != 0)
|
||||||
{
|
{
|
||||||
U64 module_base = df_base_vaddr_from_module(module);
|
|
||||||
U64 tls_base = df_tls_base_vaddr_from_thread(thread);
|
|
||||||
EVAL_Machine machine = {0};
|
|
||||||
machine.u = (void *)thread->parent;
|
|
||||||
machine.arch = arch;
|
|
||||||
machine.memory_read = df_eval_memory_read;
|
|
||||||
machine.reg_data = thread_unwind_regs_block;
|
|
||||||
machine.reg_size = reg_size;
|
|
||||||
machine.module_base = &module_base;
|
|
||||||
machine.tls_base = &tls_base;
|
|
||||||
eval = eval_interpret(&machine, bytecode);
|
eval = eval_interpret(&machine, bytecode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4139,6 +4222,12 @@ df_eval_from_string(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_
|
|||||||
result.errors = errors;
|
result.errors = errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- rjf: apply dynamic type overrides
|
||||||
|
if(parse.expr != 0 && parse.expr->kind != EVAL_ExprKind_Cast)
|
||||||
|
{
|
||||||
|
result = df_dynamically_typed_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, result);
|
||||||
|
}
|
||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
return result;
|
return result;
|
||||||
@@ -4213,10 +4302,83 @@ df_value_mode_eval_from_eval(TG_Graph *graph, RADDBG_Parsed *rdbg, DF_CtrlCtx *c
|
|||||||
return eval;
|
return eval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal DF_Eval
|
||||||
|
df_dynamically_typed_eval_from_eval(TG_Graph *graph, RADDBG_Parsed *rdbg, DF_CtrlCtx *ctrl_ctx, DF_Eval eval)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
DF_Entity *thread = df_entity_from_handle(ctrl_ctx->thread);
|
||||||
|
Architecture arch = df_architecture_from_entity(thread);
|
||||||
|
DF_Entity *process = thread->parent;
|
||||||
|
U64 unwind_count = ctrl_ctx->unwind_count;
|
||||||
|
U64 thread_rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_count);
|
||||||
|
DF_Entity *module = df_module_from_process_vaddr(process, thread_rip_vaddr);
|
||||||
|
TG_Key type_key = eval.type_key;
|
||||||
|
TG_Kind type_kind = tg_kind_from_key(type_key);
|
||||||
|
if(type_kind == TG_Kind_Ptr)
|
||||||
|
{
|
||||||
|
TG_Key ptee_type_key = tg_direct_from_graph_raddbg_key(graph, rdbg, type_key);
|
||||||
|
TG_Kind ptee_type_kind = tg_kind_from_key(ptee_type_key);
|
||||||
|
if(ptee_type_kind == TG_Kind_Struct || ptee_type_kind == TG_Kind_Class)
|
||||||
|
{
|
||||||
|
TG_Type *ptee_type = tg_type_from_graph_raddbg_key(scratch.arena, graph, rdbg, ptee_type_key);
|
||||||
|
B32 has_vtable = 0;
|
||||||
|
for(U64 idx = 0; idx < ptee_type->count; idx += 1)
|
||||||
|
{
|
||||||
|
if(ptee_type->members[idx].kind == TG_MemberKind_VirtualMethod)
|
||||||
|
{
|
||||||
|
has_vtable = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(has_vtable)
|
||||||
|
{
|
||||||
|
U64 ptr_vaddr = eval.offset;
|
||||||
|
U64 addr_size = bit_size_from_arch(arch)/8;
|
||||||
|
String8 ptr_value_memory = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle,
|
||||||
|
r1u64(ptr_vaddr, ptr_vaddr+addr_size));
|
||||||
|
if(ptr_value_memory.size >= addr_size)
|
||||||
|
{
|
||||||
|
U64 class_base_vaddr = 0;
|
||||||
|
MemoryCopy(&class_base_vaddr, ptr_value_memory.str, addr_size);
|
||||||
|
String8 vtable_base_ptr_memory = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle,
|
||||||
|
r1u64(class_base_vaddr, class_base_vaddr+addr_size));
|
||||||
|
if(vtable_base_ptr_memory.size >= addr_size)
|
||||||
|
{
|
||||||
|
U64 vtable_vaddr = 0;
|
||||||
|
MemoryCopy(&vtable_vaddr, vtable_base_ptr_memory.str, addr_size);
|
||||||
|
U64 vtable_voff = df_voff_from_vaddr(module, vtable_vaddr);
|
||||||
|
U64 global_idx = raddbg_vmap_idx_from_voff(rdbg->global_vmap, rdbg->global_vmap_count, vtable_voff);
|
||||||
|
if(0 < global_idx && global_idx < rdbg->global_variable_count)
|
||||||
|
{
|
||||||
|
RADDBG_GlobalVariable *global_var = &rdbg->global_variables[global_idx];
|
||||||
|
if(global_var->link_flags & RADDBG_LinkFlag_TypeScoped &&
|
||||||
|
0 < global_var->container_idx && global_var->container_idx < rdbg->udt_count)
|
||||||
|
{
|
||||||
|
RADDBG_UDT *udt = &rdbg->udts[global_var->container_idx];
|
||||||
|
if(0 < udt->self_type_idx && udt->self_type_idx < rdbg->type_node_count)
|
||||||
|
{
|
||||||
|
RADDBG_TypeNode *type = &rdbg->type_nodes[udt->self_type_idx];
|
||||||
|
TG_Key derived_type_key = tg_key_ext(tg_kind_from_raddbg_type_kind(type->kind), (U64)udt->self_type_idx);
|
||||||
|
TG_Key ptr_to_derived_type_key = tg_cons_type_make(graph, TG_Kind_Ptr, derived_type_key, 0);
|
||||||
|
eval.type_key = ptr_to_derived_type_key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scratch_end(scratch);
|
||||||
|
return eval;
|
||||||
|
}
|
||||||
|
|
||||||
internal DF_Eval
|
internal DF_Eval
|
||||||
df_eval_from_eval_cfg_table(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_Eval eval, DF_CfgTable *cfg)
|
df_eval_from_eval_cfg_table(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_Eval eval, DF_CfgTable *cfg)
|
||||||
{
|
{
|
||||||
ProfBeginFunction();
|
ProfBeginFunction();
|
||||||
|
|
||||||
|
//- rjf: apply view rules
|
||||||
for(DF_CfgVal *val = cfg->first_val; val != 0 && val != &df_g_nil_cfg_val; val = val->linear_next)
|
for(DF_CfgVal *val = cfg->first_val; val != 0 && val != &df_g_nil_cfg_val; val = val->linear_next)
|
||||||
{
|
{
|
||||||
DF_CoreViewRuleSpec *spec = df_core_view_rule_spec_from_string(val->string);
|
DF_CoreViewRuleSpec *spec = df_core_view_rule_spec_from_string(val->string);
|
||||||
@@ -4894,6 +5056,7 @@ df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalVie
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- rjf: apply view rules & resolve eval
|
//- rjf: apply view rules & resolve eval
|
||||||
//
|
//
|
||||||
|
eval = df_dynamically_typed_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, eval);
|
||||||
eval = df_eval_from_eval_cfg_table(arena, scope, ctrl_ctx, parse_ctx, eval, cfg_table);
|
eval = df_eval_from_eval_cfg_table(arena, scope, ctrl_ctx, parse_ctx, eval, cfg_table);
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
@@ -4993,6 +5156,15 @@ df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalVie
|
|||||||
for(DF_CfgVal *val = cfg_table->first_val; val != 0 && val != &df_g_nil_cfg_val; val = val->linear_next)
|
for(DF_CfgVal *val = cfg_table->first_val; val != 0 && val != &df_g_nil_cfg_val; val = val->linear_next)
|
||||||
{
|
{
|
||||||
DF_CoreViewRuleSpec *spec = df_core_view_rule_spec_from_string(val->string);
|
DF_CoreViewRuleSpec *spec = df_core_view_rule_spec_from_string(val->string);
|
||||||
|
if(str8_match(spec->info.string, str8_lit("list"), 0) ||
|
||||||
|
str8_match(spec->info.string, str8_lit("omit"), 0) ||
|
||||||
|
str8_match(spec->info.string, str8_lit("only"), 0))
|
||||||
|
{
|
||||||
|
// TODO(rjf): "list" view rule needs to be formally moved into the visualization
|
||||||
|
// engine hooks when the system is mature enough to support it
|
||||||
|
// also "omit", "only"
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if(spec->info.flags & DF_CoreViewRuleSpecInfoFlag_VizBlockProd)
|
if(spec->info.flags & DF_CoreViewRuleSpecInfoFlag_VizBlockProd)
|
||||||
{
|
{
|
||||||
expand_rule = DF_EvalVizExpandRule_ViewRule;
|
expand_rule = DF_EvalVizExpandRule_ViewRule;
|
||||||
@@ -6244,6 +6416,14 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rjf: exception or unexpected trap -> push error
|
||||||
|
if(event->cause == CTRL_EventCause_InterruptedByException ||
|
||||||
|
event->cause == CTRL_EventCause_InterruptedByTrap)
|
||||||
|
{
|
||||||
|
DF_CmdParams params = df_cmd_params_zero();
|
||||||
|
df_cmd_list_push(arena, cmds, ¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Error));
|
||||||
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
//- rjf: entity creation/deletion
|
//- rjf: entity creation/deletion
|
||||||
|
|||||||
@@ -818,6 +818,7 @@ struct DF_EvalVizRow
|
|||||||
String8 expr;
|
String8 expr;
|
||||||
String8 display_value;
|
String8 display_value;
|
||||||
String8 edit_value;
|
String8 edit_value;
|
||||||
|
TG_KeyList inherited_type_key_chain;
|
||||||
|
|
||||||
// rjf: variable-size & hook info
|
// rjf: variable-size & hook info
|
||||||
U64 size_in_rows;
|
U64 size_in_rows;
|
||||||
@@ -1562,6 +1563,7 @@ internal EVAL_ParseCtx df_eval_parse_ctx_from_module_voff(DBGI_Scope *scope, DF_
|
|||||||
internal EVAL_ParseCtx df_eval_parse_ctx_from_src_loc(DBGI_Scope *scope, DF_Entity *file, TxtPt pt);
|
internal EVAL_ParseCtx df_eval_parse_ctx_from_src_loc(DBGI_Scope *scope, DF_Entity *file, TxtPt pt);
|
||||||
internal DF_Eval df_eval_from_string(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, String8 string);
|
internal DF_Eval df_eval_from_string(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, String8 string);
|
||||||
internal DF_Eval df_value_mode_eval_from_eval(TG_Graph *graph, RADDBG_Parsed *rdbg, DF_CtrlCtx *ctrl_ctx, DF_Eval eval);
|
internal DF_Eval df_value_mode_eval_from_eval(TG_Graph *graph, RADDBG_Parsed *rdbg, DF_CtrlCtx *ctrl_ctx, DF_Eval eval);
|
||||||
|
internal DF_Eval df_dynamically_typed_eval_from_eval(TG_Graph *graph, RADDBG_Parsed *rdbg, DF_CtrlCtx *ctrl_ctx, DF_Eval eval);
|
||||||
internal DF_Eval df_eval_from_eval_cfg_table(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_Eval eval, DF_CfgTable *cfg);
|
internal DF_Eval df_eval_from_eval_cfg_table(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_Eval eval, DF_CfgTable *cfg);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|||||||
+86
-26
@@ -4082,6 +4082,32 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D
|
|||||||
//- rjf: build hover eval
|
//- rjf: build hover eval
|
||||||
ProfScope("build hover eval")
|
ProfScope("build hover eval")
|
||||||
{
|
{
|
||||||
|
// find panel/view pair that the mouse is on and disable hover if that view is scrolling
|
||||||
|
if(hover_eval_is_open)
|
||||||
|
{
|
||||||
|
for(DF_Panel *panel = ws->root_panel; !df_panel_is_nil(panel); panel = df_panel_rec_df_pre(panel).next)
|
||||||
|
{
|
||||||
|
if(!df_panel_is_nil(panel->first))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DF_View *view = df_selected_view_from_panel(panel);
|
||||||
|
if (!df_view_is_nil(view))
|
||||||
|
{
|
||||||
|
Rng2F32 panel_rect = df_rect_from_panel(content_rect, ws->root_panel, panel);
|
||||||
|
if(contains_2f32(panel_rect, ws->ui->mouse))
|
||||||
|
{
|
||||||
|
if(abs_f32(view->scroll_pos.x.off) > 0.01f ||
|
||||||
|
abs_f32(view->scroll_pos.y.off) > 0.01f)
|
||||||
|
{
|
||||||
|
hover_eval_is_open = 0;
|
||||||
|
ws->hover_eval_first_frame_idx = df_frame_index();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(ws->hover_eval_string.size == 0)
|
if(ws->hover_eval_string.size == 0)
|
||||||
{
|
{
|
||||||
ws->hover_eval_num_visible_rows_t = 0;
|
ws->hover_eval_num_visible_rows_t = 0;
|
||||||
@@ -4172,7 +4198,7 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D
|
|||||||
}
|
}
|
||||||
UI_PrefWidth(ui_em(30.f, 1.f))
|
UI_PrefWidth(ui_em(30.f, 1.f))
|
||||||
{
|
{
|
||||||
UI_PrefWidth(ui_text_dim(10, 1.f)) df_code_label(1.f, 1, row->expr);
|
UI_PrefWidth(ui_text_dim(10, 1.f)) df_code_label(1.f, 1, df_rgba_from_theme_color(DF_ThemeColor_CodeDefault), row->expr);
|
||||||
ui_spacer(ui_em(1.5f, 1.f));
|
ui_spacer(ui_em(1.5f, 1.f));
|
||||||
if(row->flags & DF_EvalVizRowFlag_CanEditValue)
|
if(row->flags & DF_EvalVizRowFlag_CanEditValue)
|
||||||
{
|
{
|
||||||
@@ -4197,7 +4223,7 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
df_code_label(1.f, 1, row->display_value);
|
df_code_label(1.f, 1, df_rgba_from_theme_color(DF_ThemeColor_CodeDefault), row->display_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui_spacer(ui_em(0.75f, 1.f));
|
ui_spacer(ui_em(0.75f, 1.f));
|
||||||
@@ -5051,18 +5077,21 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D
|
|||||||
Vec4F32 tx_color = df_rgba_from_theme_color(DF_ThemeColor_FailureText);
|
Vec4F32 tx_color = df_rgba_from_theme_color(DF_ThemeColor_FailureText);
|
||||||
F32 alpha_factor = Max(ws->error_t, 0.2f);
|
F32 alpha_factor = Max(ws->error_t, 0.2f);
|
||||||
tx_color.w *= alpha_factor;
|
tx_color.w *= alpha_factor;
|
||||||
ui_set_next_text_color(tx_color);
|
String8 error_string = str8(ws->error_buffer, ws->error_string_size);
|
||||||
ui_set_next_pref_width(ui_children_sum(1));
|
if(error_string.size != 0)
|
||||||
UI_CornerRadius(4)
|
|
||||||
UI_Row
|
|
||||||
UI_PrefWidth(ui_text_dim(10, 1))
|
|
||||||
UI_TextAlignment(UI_TextAlign_Center)
|
|
||||||
{
|
{
|
||||||
String8 error_string = str8(ws->error_buffer, ws->error_string_size);
|
ui_set_next_text_color(tx_color);
|
||||||
UI_Font(df_font_from_slot(DF_FontSlot_Icons))
|
ui_set_next_pref_width(ui_children_sum(1));
|
||||||
UI_FontSize(df_font_size_from_slot(ws, DF_FontSlot_Icons))
|
UI_CornerRadius(4)
|
||||||
ui_label(df_g_icon_kind_text_table[DF_IconKind_WarningBig]);
|
UI_Row
|
||||||
ui_label(error_string);
|
UI_PrefWidth(ui_text_dim(10, 1))
|
||||||
|
UI_TextAlignment(UI_TextAlign_Center)
|
||||||
|
{
|
||||||
|
UI_Font(df_font_from_slot(DF_FontSlot_Icons))
|
||||||
|
UI_FontSize(df_font_size_from_slot(ws, DF_FontSlot_Icons))
|
||||||
|
ui_label(df_g_icon_kind_text_table[DF_IconKind_WarningBig]);
|
||||||
|
ui_label(error_string);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6812,7 +6841,7 @@ df_single_line_eval_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rjf: arrow
|
// rjf: arrow
|
||||||
if(did_ptr_value && direct_type_has_content && (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules))
|
if(did_ptr_value && (direct_type_has_content || symbol_name.size != 0) && (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules))
|
||||||
{
|
{
|
||||||
String8 arrow = str8_lit(" -> ");
|
String8 arrow = str8_lit(" -> ");
|
||||||
str8_list_push(arena, &list, arrow);
|
str8_list_push(arena, &list, arrow);
|
||||||
@@ -6832,7 +6861,7 @@ df_single_line_eval_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rjf: special-case: symbols
|
// rjf: special-case: symbols
|
||||||
else if(direct_type_has_content && (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules) && symbol_name.size != 0)
|
else if((flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules) && symbol_name.size != 0)
|
||||||
{
|
{
|
||||||
str8_list_push(arena, &list, symbol_name);
|
str8_list_push(arena, &list, symbol_name);
|
||||||
space_taken += f_dim_from_tag_size_string(font, font_size, symbol_name).x;
|
space_taken += f_dim_from_tag_size_string(font, font_size, symbol_name).x;
|
||||||
@@ -7192,6 +7221,7 @@ df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DBGI_Scope *scop
|
|||||||
|
|
||||||
// rjf: apply view rules to eval
|
// rjf: apply view rules to eval
|
||||||
{
|
{
|
||||||
|
member_eval = df_dynamically_typed_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, member_eval);
|
||||||
member_eval = df_eval_from_eval_cfg_table(arena, scope, ctrl_ctx, parse_ctx, member_eval, &view_rule_table);
|
member_eval = df_eval_from_eval_cfg_table(arena, scope, ctrl_ctx, parse_ctx, member_eval, &view_rule_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7204,6 +7234,7 @@ df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DBGI_Scope *scop
|
|||||||
row->expr = push_str8_copy(arena, member->name);
|
row->expr = push_str8_copy(arena, member->name);
|
||||||
row->display_value = str8_list_join(arena, &display_strings, 0);
|
row->display_value = str8_list_join(arena, &display_strings, 0);
|
||||||
row->edit_value = str8_list_join(arena, &edit_strings, 0);
|
row->edit_value = str8_list_join(arena, &edit_strings, 0);
|
||||||
|
row->inherited_type_key_chain = tg_key_list_copy(arena, &member->inheritance_key_chain);
|
||||||
row->value_ui_rule_node = value_ui_rule_node;
|
row->value_ui_rule_node = value_ui_rule_node;
|
||||||
row->value_ui_rule_spec = value_ui_rule_spec;
|
row->value_ui_rule_spec = value_ui_rule_spec;
|
||||||
row->expand_ui_rule_node = expand_ui_rule_node;
|
row->expand_ui_rule_node = expand_ui_rule_node;
|
||||||
@@ -7271,6 +7302,7 @@ df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DBGI_Scope *scop
|
|||||||
|
|
||||||
// rjf: apply view rules to eval
|
// rjf: apply view rules to eval
|
||||||
{
|
{
|
||||||
|
elem_eval = df_dynamically_typed_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, elem_eval);
|
||||||
elem_eval = df_eval_from_eval_cfg_table(arena, scope, ctrl_ctx, parse_ctx, elem_eval, &view_rule_table);
|
elem_eval = df_eval_from_eval_cfg_table(arena, scope, ctrl_ctx, parse_ctx, elem_eval, &view_rule_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7350,6 +7382,7 @@ df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DBGI_Scope *scop
|
|||||||
df_cfg_table_push_unparsed_string(scratch.arena, &view_rule_table, view_rule_string, DF_CfgSrc_User);
|
df_cfg_table_push_unparsed_string(scratch.arena, &view_rule_table, view_rule_string, DF_CfgSrc_User);
|
||||||
|
|
||||||
// rjf: apply view rules to eval
|
// rjf: apply view rules to eval
|
||||||
|
link_eval = df_dynamically_typed_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, link_eval);
|
||||||
link_eval = df_eval_from_eval_cfg_table(arena, scope, ctrl_ctx, parse_ctx, link_eval, &view_rule_table);
|
link_eval = df_eval_from_eval_cfg_table(arena, scope, ctrl_ctx, parse_ctx, link_eval, &view_rule_table);
|
||||||
TG_Kind link_type_kind = tg_kind_from_key(link_eval.type_key);
|
TG_Kind link_type_kind = tg_kind_from_key(link_eval.type_key);
|
||||||
|
|
||||||
@@ -8643,14 +8676,14 @@ df_entity_tooltips(DF_Entity *entity)
|
|||||||
stop_condition = str8_lit("true");
|
stop_condition = str8_lit("true");
|
||||||
}
|
}
|
||||||
UI_PrefWidth(ui_em(12.f, 1.f)) UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText)) ui_labelf("Stop Condition: ");
|
UI_PrefWidth(ui_em(12.f, 1.f)) UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText)) ui_labelf("Stop Condition: ");
|
||||||
UI_PrefWidth(ui_text_dim(10, 1)) UI_Font(df_font_from_slot(DF_FontSlot_Code)) df_code_label(1.f, 1, stop_condition);
|
UI_PrefWidth(ui_text_dim(10, 1)) UI_Font(df_font_from_slot(DF_FontSlot_Code)) df_code_label(1.f, 1, df_rgba_from_theme_color(DF_ThemeColor_CodeDefault), stop_condition);
|
||||||
}
|
}
|
||||||
UI_PrefWidth(ui_children_sum(1)) UI_Row
|
UI_PrefWidth(ui_children_sum(1)) UI_Row
|
||||||
{
|
{
|
||||||
U64 hit_count = entity->u64;
|
U64 hit_count = entity->u64;
|
||||||
String8 hit_count_text = str8_from_u64(scratch.arena, hit_count, 10, 0, 0);
|
String8 hit_count_text = str8_from_u64(scratch.arena, hit_count, 10, 0, 0);
|
||||||
UI_PrefWidth(ui_em(12.f, 1.f)) UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText)) ui_labelf("Hit Count: ");
|
UI_PrefWidth(ui_em(12.f, 1.f)) UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText)) ui_labelf("Hit Count: ");
|
||||||
UI_PrefWidth(ui_text_dim(10, 1)) UI_Font(df_font_from_slot(DF_FontSlot_Code)) df_code_label(1.f, 1, hit_count_text);
|
UI_PrefWidth(ui_text_dim(10, 1)) UI_Font(df_font_from_slot(DF_FontSlot_Code)) df_code_label(1.f, 1, df_rgba_from_theme_color(DF_ThemeColor_CodeDefault), hit_count_text);
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
case DF_EntityKind_WatchPin: UI_Font(df_font_from_slot(DF_FontSlot_Code))
|
case DF_EntityKind_WatchPin: UI_Font(df_font_from_slot(DF_FontSlot_Code))
|
||||||
@@ -8661,7 +8694,7 @@ df_entity_tooltips(DF_Entity *entity)
|
|||||||
ui_set_next_text_color(color);
|
ui_set_next_text_color(color);
|
||||||
}
|
}
|
||||||
String8 display_string = df_display_string_from_entity(scratch.arena, entity);
|
String8 display_string = df_display_string_from_entity(scratch.arena, entity);
|
||||||
UI_PrefWidth(ui_text_dim(10, 1)) df_code_label(1.f, 1, display_string);
|
UI_PrefWidth(ui_text_dim(10, 1)) df_code_label(1.f, 1, df_rgba_from_theme_color(DF_ThemeColor_CodeDefault), display_string);
|
||||||
}break;
|
}break;
|
||||||
}
|
}
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
@@ -9551,8 +9584,8 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
|
|||||||
ws->entity_ctx_menu_entity = df_handle_from_entity(pin);
|
ws->entity_ctx_menu_entity = df_handle_from_entity(pin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
df_code_label(0.8f, 1, pin_expr);
|
df_code_label(0.8f, 1, df_rgba_from_theme_color(DF_ThemeColor_CodeDefault), pin_expr);
|
||||||
df_code_label(0.6f, 1, eval_string);
|
df_code_label(0.6f, 1, df_rgba_from_theme_color(DF_ThemeColor_CodeDefault), eval_string);
|
||||||
}
|
}
|
||||||
UI_Signal pin_sig = ui_signal_from_box(pin_box);
|
UI_Signal pin_sig = ui_signal_from_box(pin_box);
|
||||||
if(ui_key_match(pin_box_key, ui_hot_key()))
|
if(ui_key_match(pin_box_key, ui_hot_key()))
|
||||||
@@ -10463,7 +10496,7 @@ df_help_label(String8 string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal D_FancyStringList
|
internal D_FancyStringList
|
||||||
df_fancy_string_list_from_code_string(Arena *arena, F32 alpha, B32 indirection_size_change, String8 string)
|
df_fancy_string_list_from_code_string(Arena *arena, F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string)
|
||||||
{
|
{
|
||||||
Temp scratch = scratch_begin(&arena, 1);
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
D_FancyStringList fancy_strings = {0};
|
D_FancyStringList fancy_strings = {0};
|
||||||
@@ -10492,6 +10525,17 @@ df_fancy_string_list_from_code_string(Arena *arena, F32 alpha, B32 indirection_s
|
|||||||
};
|
};
|
||||||
d_fancy_string_list_push(arena, &fancy_strings, &fancy_string);
|
d_fancy_string_list_push(arena, &fancy_strings, &fancy_string);
|
||||||
}break;
|
}break;
|
||||||
|
case TXTI_TokenKind_Identifier:
|
||||||
|
{
|
||||||
|
D_FancyString fancy_string =
|
||||||
|
{
|
||||||
|
ui_top_font(),
|
||||||
|
token_string,
|
||||||
|
base_color,
|
||||||
|
ui_top_font_size() * (1.f - !!indirection_size_change*(indirection_counter/10.f)),
|
||||||
|
};
|
||||||
|
d_fancy_string_list_push(arena, &fancy_strings, &fancy_string);
|
||||||
|
}break;
|
||||||
case TXTI_TokenKind_Numeric:
|
case TXTI_TokenKind_Numeric:
|
||||||
{
|
{
|
||||||
Vec4F32 token_color_rgba_alt = token_color_rgba;
|
Vec4F32 token_color_rgba_alt = token_color_rgba;
|
||||||
@@ -10603,10 +10647,10 @@ df_fancy_string_list_from_code_string(Arena *arena, F32 alpha, B32 indirection_s
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
df_code_label(F32 alpha, B32 indirection_size_change, String8 string)
|
df_code_label(F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string)
|
||||||
{
|
{
|
||||||
Temp scratch = scratch_begin(0, 0);
|
Temp scratch = scratch_begin(0, 0);
|
||||||
D_FancyStringList fancy_strings = df_fancy_string_list_from_code_string(scratch.arena, alpha, indirection_size_change, string);
|
D_FancyStringList fancy_strings = df_fancy_string_list_from_code_string(scratch.arena, alpha, indirection_size_change, base_color, string);
|
||||||
UI_Box *box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero());
|
UI_Box *box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero());
|
||||||
ui_box_equip_display_fancy_strings(box, &fancy_strings);
|
ui_box_equip_display_fancy_strings(box, &fancy_strings);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
@@ -10812,11 +10856,11 @@ df_line_edit(DF_LineEditFlags flags, S32 depth, TxtPt *cursor, TxtPt *mark, U8 *
|
|||||||
if(!(flags & DF_LineEditFlag_PreferDisplayString) && pre_edit_value.size != 0)
|
if(!(flags & DF_LineEditFlag_PreferDisplayString) && pre_edit_value.size != 0)
|
||||||
{
|
{
|
||||||
display_string = pre_edit_value;
|
display_string = pre_edit_value;
|
||||||
df_code_label(1.f, 1, display_string);
|
df_code_label(1.f, 1, ui_top_text_color(), display_string);
|
||||||
}
|
}
|
||||||
else if(flags & DF_LineEditFlag_DisplayStringIsCode)
|
else if(flags & DF_LineEditFlag_DisplayStringIsCode)
|
||||||
{
|
{
|
||||||
df_code_label(1.f, 1, display_string);
|
df_code_label(1.f, 1, ui_top_text_color(), display_string);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -10845,7 +10889,7 @@ df_line_edit(DF_LineEditFlags flags, S32 depth, TxtPt *cursor, TxtPt *mark, U8 *
|
|||||||
F32 total_editstr_width = total_text_width - !!(flags & (DF_LineEditFlag_Expander|DF_LineEditFlag_ExpanderSpace|DF_LineEditFlag_ExpanderPlaceholder)) * expander_size_px;
|
F32 total_editstr_width = total_text_width - !!(flags & (DF_LineEditFlag_Expander|DF_LineEditFlag_ExpanderSpace|DF_LineEditFlag_ExpanderPlaceholder)) * expander_size_px;
|
||||||
ui_set_next_pref_width(ui_px(total_editstr_width+ui_top_font_size()*2, 0.f));
|
ui_set_next_pref_width(ui_px(total_editstr_width+ui_top_font_size()*2, 0.f));
|
||||||
UI_Box *editstr_box = ui_build_box_from_stringf(UI_BoxFlag_DrawText|UI_BoxFlag_DisableTextTrunc, "###editstr");
|
UI_Box *editstr_box = ui_build_box_from_stringf(UI_BoxFlag_DrawText|UI_BoxFlag_DisableTextTrunc, "###editstr");
|
||||||
D_FancyStringList code_fancy_strings = df_fancy_string_list_from_code_string(scratch.arena, 1.f, 0, edit_string);
|
D_FancyStringList code_fancy_strings = df_fancy_string_list_from_code_string(scratch.arena, 1.f, 0, ui_top_text_color(), edit_string);
|
||||||
ui_box_equip_display_fancy_strings(editstr_box, &code_fancy_strings);
|
ui_box_equip_display_fancy_strings(editstr_box, &code_fancy_strings);
|
||||||
UI_LineEditDrawData *draw_data = push_array(ui_build_arena(), UI_LineEditDrawData, 1);
|
UI_LineEditDrawData *draw_data = push_array(ui_build_arena(), UI_LineEditDrawData, 1);
|
||||||
draw_data->edited_string = push_str8_copy(ui_build_arena(), edit_string);
|
draw_data->edited_string = push_str8_copy(ui_build_arena(), edit_string);
|
||||||
@@ -11054,6 +11098,22 @@ df_gfx_begin_frame(Arena *arena, DF_CmdList *cmds)
|
|||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
|
//- rjf: errors
|
||||||
|
case DF_CoreCmdKind_Error:
|
||||||
|
{
|
||||||
|
DF_Window *window = df_window_from_handle(params.window);
|
||||||
|
if(window == 0)
|
||||||
|
{
|
||||||
|
for(DF_Window *w = df_gfx_state->first_window; w != 0; w = w->next)
|
||||||
|
{
|
||||||
|
DF_CmdParams p = df_cmd_params_from_window(w);
|
||||||
|
p.string = push_str8_copy(arena, params.string);
|
||||||
|
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_String);
|
||||||
|
df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
|
||||||
//- rjf: windows
|
//- rjf: windows
|
||||||
case DF_CoreCmdKind_OpenWindow:
|
case DF_CoreCmdKind_OpenWindow:
|
||||||
{
|
{
|
||||||
|
|||||||
+2
-2
@@ -1031,8 +1031,8 @@ internal B32 df_do_dasm_controls(DASM_Handle handle, U64 line_count_per_page, Tx
|
|||||||
|
|
||||||
internal UI_Signal df_error_label(String8 string);
|
internal UI_Signal df_error_label(String8 string);
|
||||||
internal B32 df_help_label(String8 string);
|
internal B32 df_help_label(String8 string);
|
||||||
internal D_FancyStringList df_fancy_string_list_from_code_string(Arena *arena, F32 alpha, B32 indirection_size_change, String8 string);
|
internal D_FancyStringList df_fancy_string_list_from_code_string(Arena *arena, F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string);
|
||||||
internal void df_code_label(F32 alpha, B32 indirection_size_change, String8 string);
|
internal void df_code_label(F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: UI Widgets: Line Edit
|
//~ rjf: UI Widgets: Line Edit
|
||||||
|
|||||||
+46
-19
@@ -1051,22 +1051,49 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW
|
|||||||
// rjf: build
|
// rjf: build
|
||||||
UI_Signal sig = {0};
|
UI_Signal sig = {0};
|
||||||
B32 next_expanded = row_expanded;
|
B32 next_expanded = row_expanded;
|
||||||
UI_TableCell UI_Font(code_font)
|
UI_TableCell UI_FocusHot(cell_selected) UI_FocusActive(cell_selected && ewv->input_editing)
|
||||||
UI_TextColor(row->depth > 0 ? df_rgba_from_theme_color(DF_ThemeColor_WeakText) : ui_top_text_color())
|
|
||||||
UI_FocusHot(cell_selected) UI_FocusActive(cell_selected && ewv->input_editing)
|
|
||||||
{
|
{
|
||||||
B32 expr_editing_active = ui_is_focus_active();
|
B32 expr_editing_active = ui_is_focus_active();
|
||||||
sig = df_line_editf((DF_LineEditFlag_CodeContents|
|
B32 is_inherited = (row->inherited_type_key_chain.count != 0);
|
||||||
DF_LineEditFlag_NoBackground|
|
UI_Font(code_font) UI_TextColor(row->depth > 0 ? df_rgba_from_theme_color(DF_ThemeColor_WeakText) : ui_top_text_color())
|
||||||
DF_LineEditFlag_DisableEdit*(!can_edit_expr)|
|
{
|
||||||
DF_LineEditFlag_Expander*!!(row->flags & DF_EvalVizRowFlag_CanExpand)|
|
if(is_inherited)
|
||||||
DF_LineEditFlag_ExpanderPlaceholder*(row->depth==0)|
|
{
|
||||||
DF_LineEditFlag_ExpanderSpace*(row->depth!=0)),
|
Vec4F32 inherited_bg_color = df_rgba_from_theme_color(DF_ThemeColor_Highlight1);
|
||||||
row->depth,
|
inherited_bg_color.w *= 0.2f;
|
||||||
&ewv->input_cursor, &ewv->input_mark, ewv->input_buffer, sizeof(ewv->input_buffer), &ewv->input_size, &next_expanded,
|
ui_set_next_background_color(inherited_bg_color);
|
||||||
row->expr,
|
}
|
||||||
"###row_%I64x", row_hash);
|
sig = df_line_editf((DF_LineEditFlag_CodeContents|
|
||||||
|
DF_LineEditFlag_NoBackground*(!is_inherited)|
|
||||||
|
DF_LineEditFlag_DisableEdit*(!can_edit_expr)|
|
||||||
|
DF_LineEditFlag_Expander*!!(row->flags & DF_EvalVizRowFlag_CanExpand)|
|
||||||
|
DF_LineEditFlag_ExpanderPlaceholder*(row->depth==0)|
|
||||||
|
DF_LineEditFlag_ExpanderSpace*(row->depth!=0)),
|
||||||
|
row->depth,
|
||||||
|
&ewv->input_cursor, &ewv->input_mark, ewv->input_buffer, sizeof(ewv->input_buffer), &ewv->input_size, &next_expanded,
|
||||||
|
row->expr,
|
||||||
|
"###row_%I64x", row_hash);
|
||||||
|
}
|
||||||
edit_commit = edit_commit || sig.commit;
|
edit_commit = edit_commit || sig.commit;
|
||||||
|
if(sig.hovering && is_inherited) UI_Tooltip
|
||||||
|
{
|
||||||
|
String8List inheritance_chain_type_names = {0};
|
||||||
|
for(TG_KeyNode *n = row->inherited_type_key_chain.first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
String8 inherited_type_name = tg_string_from_key(scratch.arena, parse_ctx.type_graph, parse_ctx.rdbg, n->v);
|
||||||
|
inherited_type_name = str8_skip_chop_whitespace(inherited_type_name);
|
||||||
|
str8_list_push(scratch.arena, &inheritance_chain_type_names, inherited_type_name);
|
||||||
|
}
|
||||||
|
StringJoin join = {0};
|
||||||
|
join.sep = str8_lit("::");
|
||||||
|
String8 inheritance_type = str8_list_join(scratch.arena, &inheritance_chain_type_names, &join);
|
||||||
|
ui_set_next_pref_width(ui_children_sum(1));
|
||||||
|
UI_Row
|
||||||
|
{
|
||||||
|
ui_labelf("Inherited from ");
|
||||||
|
UI_Font(df_font_from_slot(DF_FontSlot_Code)) df_code_label(1.f, 1.f, df_rgba_from_theme_color(DF_ThemeColor_CodeType), inheritance_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
if(sig.hovering && DEV_eval_watch_key_tooltips) UI_Tooltip UI_Font(df_font_from_slot(DF_FontSlot_Code))
|
if(sig.hovering && DEV_eval_watch_key_tooltips) UI_Tooltip UI_Font(df_font_from_slot(DF_FontSlot_Code))
|
||||||
{
|
{
|
||||||
ui_labelf("Parent Key: %I64x, %I64x, %I64x", row->parent_key.uniquifier, row->parent_key.parent_hash, row->parent_key.child_num);
|
ui_labelf("Parent Key: %I64x, %I64x, %I64x", row->parent_key.uniquifier, row->parent_key.parent_hash, row->parent_key.child_num);
|
||||||
@@ -1217,7 +1244,7 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW
|
|||||||
UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clip|UI_BoxFlag_Clickable, "###val_%I64x", row_hash);
|
UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clip|UI_BoxFlag_Clickable, "###val_%I64x", row_hash);
|
||||||
UI_Parent(box)
|
UI_Parent(box)
|
||||||
{
|
{
|
||||||
df_code_label(1.f, 1, row->display_value);
|
df_code_label(1.f, 1, df_rgba_from_theme_color(DF_ThemeColor_CodeDefault), row->display_value);
|
||||||
}
|
}
|
||||||
sig = ui_signal_from_box(box);
|
sig = ui_signal_from_box(box);
|
||||||
}
|
}
|
||||||
@@ -1261,7 +1288,7 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW
|
|||||||
UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clip|UI_BoxFlag_Clickable, "###type_%I64x", row_hash);
|
UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clip|UI_BoxFlag_Clickable, "###type_%I64x", row_hash);
|
||||||
if(!tg_key_match(key, tg_key_zero())) UI_Parent(box)
|
if(!tg_key_match(key, tg_key_zero())) UI_Parent(box)
|
||||||
{
|
{
|
||||||
df_code_label(1.f, 1, string);
|
df_code_label(1.f, 1, df_rgba_from_theme_color(DF_ThemeColor_CodeType), string);
|
||||||
}
|
}
|
||||||
UI_Signal sig = ui_signal_from_box(box);
|
UI_Signal sig = ui_signal_from_box(box);
|
||||||
if(sig.pressed)
|
if(sig.pressed)
|
||||||
@@ -7928,7 +7955,7 @@ DF_VIEW_UI_FUNCTION_DEF(Memory)
|
|||||||
}
|
}
|
||||||
if(a->type_string.size != 0)
|
if(a->type_string.size != 0)
|
||||||
{
|
{
|
||||||
df_code_label(1.f, 1, a->type_string);
|
df_code_label(1.f, 1, df_rgba_from_theme_color(DF_ThemeColor_CodeType), a->type_string);
|
||||||
}
|
}
|
||||||
UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText)) ui_label(str8_from_memory_size(scratch.arena, dim_1u64(a->vaddr_range)));
|
UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText)) ui_label(str8_from_memory_size(scratch.arena, dim_1u64(a->vaddr_range)));
|
||||||
if(a->next != 0)
|
if(a->next != 0)
|
||||||
@@ -8017,7 +8044,7 @@ DF_VIEW_UI_FUNCTION_DEF(Memory)
|
|||||||
UI_PrefHeight(ui_px(row_height_px, 0.f))
|
UI_PrefHeight(ui_px(row_height_px, 0.f))
|
||||||
{
|
{
|
||||||
B32 cursor_in_range = (viz_range_bytes.min <= mv->cursor && mv->cursor+8 <= viz_range_bytes.max);
|
B32 cursor_in_range = (viz_range_bytes.min <= mv->cursor && mv->cursor+8 <= viz_range_bytes.max);
|
||||||
ui_labelf("%016X", mv->cursor);
|
ui_labelf("%016I64X", mv->cursor);
|
||||||
if(cursor_in_range)
|
if(cursor_in_range)
|
||||||
{
|
{
|
||||||
U64 as_u8 = 0;
|
U64 as_u8 = 0;
|
||||||
@@ -8032,7 +8059,7 @@ DF_VIEW_UI_FUNCTION_DEF(Memory)
|
|||||||
ui_labelf("%02X (%I64u)", as_u8, as_u8);
|
ui_labelf("%02X (%I64u)", as_u8, as_u8);
|
||||||
ui_labelf("%04X (%I64u)", as_u16, as_u16);
|
ui_labelf("%04X (%I64u)", as_u16, as_u16);
|
||||||
ui_labelf("%08X (%I64u)", as_u32, as_u32);
|
ui_labelf("%08X (%I64u)", as_u32, as_u32);
|
||||||
ui_labelf("%016X (%I64u)", as_u64, as_u64);
|
ui_labelf("%016I64X (%I64u)", as_u64, as_u64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8197,7 +8224,7 @@ DF_VIEW_UI_FUNCTION_DEF(Breakpoints)
|
|||||||
UI_Parent(box)
|
UI_Parent(box)
|
||||||
{
|
{
|
||||||
String8 hit_count_string = str8_from_u64(scratch.arena, entity->u64, 10, 0, 0);
|
String8 hit_count_string = str8_from_u64(scratch.arena, entity->u64, 10, 0, 0);
|
||||||
UI_Font(df_font_from_slot(DF_FontSlot_Code)) df_code_label(1.f, 1, hit_count_string);
|
UI_Font(df_font_from_slot(DF_FontSlot_Code)) df_code_label(1.f, 1, df_rgba_from_theme_color(DF_ThemeColor_CodeDefault), hit_count_string);
|
||||||
}
|
}
|
||||||
UI_Signal sig = ui_signal_from_box(box);
|
UI_Signal sig = ui_signal_from_box(box);
|
||||||
if(sig.pressed)
|
if(sig.pressed)
|
||||||
|
|||||||
@@ -942,14 +942,14 @@ eval_irtree_and_type_from_expr(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdb
|
|||||||
|
|
||||||
if (l_good && r_good){
|
if (l_good && r_good){
|
||||||
Temp scratch = scratch_begin(&arena, 1);
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
TG_Type *check_type = tg_type_from_graph_raddbg_key(scratch.arena, graph, rdbg, check_type_key);
|
TG_MemberArray check_type_members = tg_data_members_from_graph_raddbg_key(scratch.arena, graph, rdbg, check_type_key);
|
||||||
|
|
||||||
// lookup member
|
// lookup member
|
||||||
String8 member_name = exprr->name;
|
String8 member_name = exprr->name;
|
||||||
TG_Member *match = 0;
|
TG_Member *match = 0;
|
||||||
for(U64 member_idx = 0; member_idx < check_type->count; member_idx += 1)
|
for(U64 member_idx = 0; member_idx < check_type_members.count; member_idx += 1)
|
||||||
{
|
{
|
||||||
TG_Member *member = &check_type->members[member_idx];
|
TG_Member *member = &check_type_members.v[member_idx];
|
||||||
if(str8_match(member->name, member_name, 0))
|
if(str8_match(member->name, member_name, 0))
|
||||||
{
|
{
|
||||||
match = member;
|
match = member;
|
||||||
|
|||||||
@@ -778,6 +778,7 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8
|
|||||||
case EVAL_TokenKind_Identifier:
|
case EVAL_TokenKind_Identifier:
|
||||||
{
|
{
|
||||||
B32 mapped_identifier = 0;
|
B32 mapped_identifier = 0;
|
||||||
|
B32 identifier_type_is_possibly_dynamically_overridden = 0;
|
||||||
B32 identifier_looks_like_type_expr = 0;
|
B32 identifier_looks_like_type_expr = 0;
|
||||||
RADDBG_LocationKind loc_kind = RADDBG_LocationKind_NULL;
|
RADDBG_LocationKind loc_kind = RADDBG_LocationKind_NULL;
|
||||||
RADDBG_LocationRegister loc_reg = {0};
|
RADDBG_LocationRegister loc_reg = {0};
|
||||||
@@ -808,6 +809,7 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8
|
|||||||
ctx->rdbg->type_nodes != 0)
|
ctx->rdbg->type_nodes != 0)
|
||||||
{
|
{
|
||||||
mapped_identifier = 1;
|
mapped_identifier = 1;
|
||||||
|
identifier_type_is_possibly_dynamically_overridden = 1;
|
||||||
RADDBG_Local *local_var = &ctx->rdbg->locals[local_num-1];
|
RADDBG_Local *local_var = &ctx->rdbg->locals[local_num-1];
|
||||||
|
|
||||||
// rjf: grab location info
|
// rjf: grab location info
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int lib_loaded = 0;
|
||||||
|
HANDLE lib = {0};
|
||||||
|
FILETIME lib_last_filetime = {0};
|
||||||
|
int (*get_number)(void) = 0;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
//- rjf: hot-load dll
|
||||||
|
{
|
||||||
|
HANDLE file = CreateFileA("mule_hotload_module.dll", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
FILETIME modified = {0};
|
||||||
|
if(GetFileTime(file, 0, 0, &modified) &&
|
||||||
|
CompareFileTime(&lib_last_filetime, &modified) == -1)
|
||||||
|
{
|
||||||
|
for(int reloaded = 0; !reloaded;)
|
||||||
|
{
|
||||||
|
if(lib_loaded)
|
||||||
|
{
|
||||||
|
FreeLibrary(lib);
|
||||||
|
lib_loaded = 0;
|
||||||
|
}
|
||||||
|
BOOL copy_worked = CopyFile("mule_hotload_module.dll", "mule_hotload_module_temp.dll", 0);
|
||||||
|
lib = LoadLibraryA("mule_hotload_module_temp.dll");
|
||||||
|
if(lib != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
reloaded = 1;
|
||||||
|
lib_last_filetime = modified;
|
||||||
|
get_number = (int(*)(void))GetProcAddress(lib, "get_number");
|
||||||
|
lib_loaded = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseHandle(file);
|
||||||
|
}
|
||||||
|
int number = get_number();
|
||||||
|
printf("got a number: %i\n", number);
|
||||||
|
if(number == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Sleep(1000);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
__declspec(dllexport) int
|
||||||
|
get_number(void)
|
||||||
|
{
|
||||||
|
int sum = 0;
|
||||||
|
for(int i = 0; i < 100; i += 1)
|
||||||
|
{
|
||||||
|
sum += i;
|
||||||
|
sum += i;
|
||||||
|
sum += 1;
|
||||||
|
}
|
||||||
|
sum = 1000;
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
@@ -914,6 +914,18 @@ struct Template_Example3{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SingleInheritanceBase
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SingleInheritanceDerived : SingleInheritanceBase
|
||||||
|
{
|
||||||
|
int z;
|
||||||
|
int w;
|
||||||
|
};
|
||||||
|
|
||||||
struct Has_Members{
|
struct Has_Members{
|
||||||
int a;
|
int a;
|
||||||
int b;
|
int b;
|
||||||
@@ -1090,6 +1102,86 @@ struct Vinheritance_Child : Vinheritance_MidLeft, Vinheritance_MidRight{
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Minheritance_Base{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Minheritance_MidLeft : Minheritance_Base{
|
||||||
|
float left;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Minheritance_MidRight : Minheritance_Base{
|
||||||
|
float right;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Minheritance_Child : Minheritance_MidLeft, Minheritance_MidRight{
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Pure
|
||||||
|
{
|
||||||
|
virtual ~Pure() = default;
|
||||||
|
virtual void Foo() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PureChild : Pure
|
||||||
|
{
|
||||||
|
virtual ~PureChild() = default;
|
||||||
|
virtual void Foo() {a += 1;}
|
||||||
|
double a = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Base
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int z;
|
||||||
|
virtual ~Base() = default;
|
||||||
|
virtual void Foo() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Derived : Base
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
int g;
|
||||||
|
int b;
|
||||||
|
int a;
|
||||||
|
virtual ~Derived() = default;
|
||||||
|
virtual void Foo() {a += 1;}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DerivedA : Base
|
||||||
|
{
|
||||||
|
float a;
|
||||||
|
float b;
|
||||||
|
virtual void Foo() {a += 1;}
|
||||||
|
virtual ~DerivedA() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DerivedB : Base
|
||||||
|
{
|
||||||
|
double c;
|
||||||
|
double d;
|
||||||
|
virtual void Foo() {c += 1;}
|
||||||
|
virtual ~DerivedB() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NonVirtualBase
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NonVirtualDerived : NonVirtualBase
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
int g;
|
||||||
|
int b;
|
||||||
|
int a;
|
||||||
|
};
|
||||||
|
|
||||||
struct OverloadedMethods{
|
struct OverloadedMethods{
|
||||||
int x;
|
int x;
|
||||||
int cool_method(void){
|
int cool_method(void){
|
||||||
@@ -1245,6 +1337,12 @@ extended_type_coverage_eval_tests(void){
|
|||||||
Template_Example3<void *, float> temp3_vi((void *)&temp3_if, 1.f);
|
Template_Example3<void *, float> temp3_vi((void *)&temp3_if, 1.f);
|
||||||
Template_Example3<int, Template_Example2<int, float>> temp3_itif(123, temp_if);
|
Template_Example3<int, Template_Example2<int, float>> temp3_itif(123, temp_if);
|
||||||
|
|
||||||
|
SingleInheritanceDerived sid;
|
||||||
|
sid.x = 123;
|
||||||
|
sid.y = 456;
|
||||||
|
sid.z = 789;
|
||||||
|
sid.w = 999;
|
||||||
|
|
||||||
Pointer_To_Member pointer_to_member = {
|
Pointer_To_Member pointer_to_member = {
|
||||||
&Has_Members::a, &Has_Members::c, &Has_Members::bas,
|
&Has_Members::a, &Has_Members::c, &Has_Members::bas,
|
||||||
&Has_Members::x, &Has_Members::z, &Has_Members::bas_f,
|
&Has_Members::x, &Has_Members::z, &Has_Members::bas_f,
|
||||||
@@ -1279,6 +1377,46 @@ extended_type_coverage_eval_tests(void){
|
|||||||
vinheritance_child.x = -1;
|
vinheritance_child.x = -1;
|
||||||
vinheritance_child.y = -1;
|
vinheritance_child.y = -1;
|
||||||
|
|
||||||
|
Minheritance_Child minheritance_child;
|
||||||
|
minheritance_child.name = "foobar";
|
||||||
|
minheritance_child.left = 10.5f;
|
||||||
|
minheritance_child.right = 13.0f;
|
||||||
|
minheritance_child.Minheritance_MidLeft::x = -1;
|
||||||
|
minheritance_child.Minheritance_MidLeft::y = -1;
|
||||||
|
minheritance_child.Minheritance_MidRight::x = +1;
|
||||||
|
minheritance_child.Minheritance_MidRight::y = +1;
|
||||||
|
|
||||||
|
Pure *child = new PureChild();
|
||||||
|
child->Foo();
|
||||||
|
child->Foo();
|
||||||
|
child->Foo();
|
||||||
|
delete child;
|
||||||
|
|
||||||
|
Base *derived = new Derived();
|
||||||
|
derived->Foo();
|
||||||
|
derived->Foo();
|
||||||
|
derived->Foo();
|
||||||
|
delete derived;
|
||||||
|
|
||||||
|
NonVirtualBase *non_virtual_derived = new NonVirtualDerived();
|
||||||
|
non_virtual_derived->x += 1;
|
||||||
|
non_virtual_derived->x += 1;
|
||||||
|
non_virtual_derived->x += 1;
|
||||||
|
delete non_virtual_derived;
|
||||||
|
|
||||||
|
Base *base_array[1024] = {0};
|
||||||
|
for(int i = 0; i < sizeof(base_array)/sizeof(base_array[0]); i += 1)
|
||||||
|
{
|
||||||
|
if(i & 1 == 1)
|
||||||
|
{
|
||||||
|
base_array[i] = new DerivedA();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base_array[i] = new DerivedB();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
OverloadedMethods overloaded_methods;
|
OverloadedMethods overloaded_methods;
|
||||||
{
|
{
|
||||||
overloaded_methods.x = 0;
|
overloaded_methods.x = 0;
|
||||||
|
|||||||
+15
-18
@@ -6,19 +6,6 @@
|
|||||||
//
|
//
|
||||||
// [ ] ** Thread/process control bullet-proofing, including solo-step mode
|
// [ ] ** Thread/process control bullet-proofing, including solo-step mode
|
||||||
// [ ] ** ASAN targets
|
// [ ] ** ASAN targets
|
||||||
// [ ] ** while typing, "Alt" Windows menu things should not happen
|
|
||||||
//
|
|
||||||
// [ ] ** I can't seem to get the .raddbg files to update consistently, or
|
|
||||||
// something. I can't seem to reproduce it reliably, but sometimes when I
|
|
||||||
// rebuild, for example, it seems to keep using the old PDB data
|
|
||||||
// effectively - like it doesn't think it needs to update the raddbg file,
|
|
||||||
// or something? But if I manually delete the raddbg file and relaunch,
|
|
||||||
// then it will have the new debug info. It would be nice if there was
|
|
||||||
// some kind of way to interrogate this in the debugger so I can send a
|
|
||||||
// more constructive report, like some way to get a hash of the PDB that
|
|
||||||
// is thinks it has converted to the RAD format, and then a way I can hash
|
|
||||||
// the PDB on the drive, or something, so I can figure out if they are
|
|
||||||
// mismatching for sure?
|
|
||||||
//
|
//
|
||||||
// [ ] ** In solo-stepping mode, if I step over something like CreateFileA, it
|
// [ ] ** In solo-stepping mode, if I step over something like CreateFileA, it
|
||||||
// pseudo-hangs the debugger. I can't seem to do anything else, including
|
// pseudo-hangs the debugger. I can't seem to do anything else, including
|
||||||
@@ -30,10 +17,12 @@
|
|||||||
// progress bar in the disassembly window. I had to close and restart. Is
|
// progress bar in the disassembly window. I had to close and restart. Is
|
||||||
// console app debugging not working yet, perhaps?
|
// console app debugging not working yet, perhaps?
|
||||||
//
|
//
|
||||||
// [ ] Setting the code_font/main_font values to a font name doesn't work.
|
// [ ] register value committing in watch
|
||||||
// Should probably make note that you have to set it to a path to a TTF,
|
//
|
||||||
// since that's not normally how Windows fonts work.
|
// [ ] Setting the code_font/main_font values to a font name doesn't work.
|
||||||
|
// Should probably make note that you have to set it to a path to a TTF,
|
||||||
|
// since that's not normally how Windows fonts work.
|
||||||
|
//
|
||||||
// [ ] ** Converter performance & heuristics for asynchronously doing it early
|
// [ ] ** Converter performance & heuristics for asynchronously doing it early
|
||||||
//
|
//
|
||||||
// [ ] disasm animation & go-to-address
|
// [ ] disasm animation & go-to-address
|
||||||
@@ -44,6 +33,8 @@
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Hot, Medium Priority Tasks (Low-Hanging-Fruit Features, UI Jank, Cleanup)
|
//~ rjf: Hot, Medium Priority Tasks (Low-Hanging-Fruit Features, UI Jank, Cleanup)
|
||||||
//
|
//
|
||||||
|
// [ ] ** while typing, "Alt" Windows menu things should not happen
|
||||||
|
//
|
||||||
// [ ] I was a little confused about what a profile file was. I understood
|
// [ ] I was a little confused about what a profile file was. I understood
|
||||||
// what the user file was, but the profile file sounded like it should
|
// what the user file was, but the profile file sounded like it should
|
||||||
// perhaps be per-project, yet it sounded like it was meant to be somewhat
|
// perhaps be per-project, yet it sounded like it was meant to be somewhat
|
||||||
@@ -202,6 +193,12 @@
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Hot, Low Priority Tasks (UI Opinions, Less-Serious Jank, Preferences, Cleanup)
|
//~ rjf: Hot, Low Priority Tasks (UI Opinions, Less-Serious Jank, Preferences, Cleanup)
|
||||||
//
|
//
|
||||||
|
// [ ] ** Directory picking is kind of busted, as it goes through the same
|
||||||
|
// path as file picking, and this doesn't give the user a clean path to
|
||||||
|
// actually pick a folder, just navigate with them
|
||||||
|
//
|
||||||
|
// [ ] ** Hover-Eval-Popup-While-Scrolling is very annoying!
|
||||||
|
//
|
||||||
// [ ] ** In the call stack, I would like to be able to click quickly and move
|
// [ ] ** In the call stack, I would like to be able to click quickly and move
|
||||||
// around the stack. Right now, you can do that with the first and third
|
// around the stack. Right now, you can do that with the first and third
|
||||||
// column, but the second column drops down a context menu. Since right
|
// column, but the second column drops down a context menu. Since right
|
||||||
@@ -422,7 +419,7 @@
|
|||||||
|
|
||||||
#define RADDBG_VERSION_MAJOR 0
|
#define RADDBG_VERSION_MAJOR 0
|
||||||
#define RADDBG_VERSION_MINOR 9
|
#define RADDBG_VERSION_MINOR 9
|
||||||
#define RADDBG_VERSION_PATCH 3
|
#define RADDBG_VERSION_PATCH 4
|
||||||
#define RADDBG_VERSION_STRING_LITERAL Stringify(RADDBG_VERSION_MAJOR) "." Stringify(RADDBG_VERSION_MINOR) "." Stringify(RADDBG_VERSION_PATCH)
|
#define RADDBG_VERSION_STRING_LITERAL Stringify(RADDBG_VERSION_MAJOR) "." Stringify(RADDBG_VERSION_MINOR) "." Stringify(RADDBG_VERSION_PATCH)
|
||||||
#if defined(NDEBUG)
|
#if defined(NDEBUG)
|
||||||
# define RADDBG_TITLE_STRING_LITERAL "The RAD Debugger (" RADDBG_VERSION_STRING_LITERAL " ALPHA) - " __DATE__ ""
|
# define RADDBG_TITLE_STRING_LITERAL "The RAD Debugger (" RADDBG_VERSION_STRING_LITERAL " ALPHA) - " __DATE__ ""
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ cons_root_new(CONS_RootParams *params){
|
|||||||
result->scope_count += 1;
|
result->scope_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rjf: setup null UDT
|
||||||
|
{
|
||||||
|
cons__type_udt_from_any_type(result, result->nil_type);
|
||||||
|
}
|
||||||
|
|
||||||
// initialize maps
|
// initialize maps
|
||||||
{
|
{
|
||||||
#define BKTCOUNT(x) ((x)?(u64_up_to_pow2(x)):(128))
|
#define BKTCOUNT(x) ((x)?(u64_up_to_pow2(x)):(128))
|
||||||
|
|||||||
@@ -763,7 +763,13 @@ pdbconv_type_equip_members(PDBCONV_Ctx *ctx, CONS_Type *owner_type, CV_TypeId fi
|
|||||||
|
|
||||||
// discard cases - we don't currently do anything with these
|
// discard cases - we don't currently do anything with these
|
||||||
case CV_LeafKind_VFUNCTAB:
|
case CV_LeafKind_VFUNCTAB:
|
||||||
{}break;
|
{
|
||||||
|
// TODO(rjf): error if bad range
|
||||||
|
if(list_item_off + sizeof(CV_LeafVFuncTab) <= cap)
|
||||||
|
{
|
||||||
|
list_item_opl_off = list_item_off + sizeof(CV_LeafVFuncTab);
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
|
||||||
// unhandled or invalid cases
|
// unhandled or invalid cases
|
||||||
default:
|
default:
|
||||||
@@ -1310,6 +1316,7 @@ pdbconv_type_cons_leaf_record(PDBCONV_Ctx *ctx, CV_TypeId itype){
|
|||||||
case CV_LeafKind_STRUCTURE:
|
case CV_LeafKind_STRUCTURE:
|
||||||
{
|
{
|
||||||
ProfBegin("CV_LeafKind_CLASS/CV_LeafKind_STRUCTURE");
|
ProfBegin("CV_LeafKind_CLASS/CV_LeafKind_STRUCTURE");
|
||||||
|
|
||||||
// TODO(allen): error if bad range
|
// TODO(allen): error if bad range
|
||||||
if (sizeof(CV_LeafStruct) <= cap){
|
if (sizeof(CV_LeafStruct) <= cap){
|
||||||
CV_LeafStruct *lf_struct = (CV_LeafStruct*)first;
|
CV_LeafStruct *lf_struct = (CV_LeafStruct*)first;
|
||||||
|
|||||||
@@ -161,7 +161,19 @@ r_init(CmdLine *cmdln)
|
|||||||
feature_levels, ArrayCount(feature_levels),
|
feature_levels, ArrayCount(feature_levels),
|
||||||
D3D11_SDK_VERSION,
|
D3D11_SDK_VERSION,
|
||||||
&r_d3d11_state->base_device, 0, &r_d3d11_state->base_device_ctx);
|
&r_d3d11_state->base_device, 0, &r_d3d11_state->base_device_ctx);
|
||||||
if(!SUCCEEDED(error))
|
if(FAILED(error) && driver_type == D3D_DRIVER_TYPE_HARDWARE)
|
||||||
|
{
|
||||||
|
// try with WARP driver as backup solution in case HW device is not available
|
||||||
|
error = D3D11CreateDevice(0,
|
||||||
|
D3D_DRIVER_TYPE_WARP,
|
||||||
|
0,
|
||||||
|
creation_flags,
|
||||||
|
feature_levels, ArrayCount(feature_levels),
|
||||||
|
D3D11_SDK_VERSION,
|
||||||
|
&r_d3d11_state->base_device, 0, &r_d3d11_state->base_device_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(FAILED(error))
|
||||||
{
|
{
|
||||||
char buffer[256] = {0};
|
char buffer[256] = {0};
|
||||||
raddbg_snprintf(buffer, sizeof(buffer), "D3D11 device creation failure (%x). The process is terminating.", error);
|
raddbg_snprintf(buffer, sizeof(buffer), "D3D11 device creation failure (%x). The process is terminating.", error);
|
||||||
@@ -307,7 +319,7 @@ r_init(CmdLine *cmdln)
|
|||||||
&vshad_source_blob,
|
&vshad_source_blob,
|
||||||
&vshad_source_errors);
|
&vshad_source_errors);
|
||||||
String8 errors = {0};
|
String8 errors = {0};
|
||||||
if(vshad_source_errors)
|
if(FAILED(error))
|
||||||
{
|
{
|
||||||
errors = str8((U8 *)vshad_source_errors->GetBufferPointer(),
|
errors = str8((U8 *)vshad_source_errors->GetBufferPointer(),
|
||||||
(U64)vshad_source_errors->GetBufferSize());
|
(U64)vshad_source_errors->GetBufferSize());
|
||||||
@@ -328,6 +340,8 @@ r_init(CmdLine *cmdln)
|
|||||||
vshad_source_blob->GetBufferSize(),
|
vshad_source_blob->GetBufferSize(),
|
||||||
&ilay);
|
&ilay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vshad_source_blob->Release();
|
||||||
|
|
||||||
// rjf: store
|
// rjf: store
|
||||||
r_d3d11_state->vshads[kind] = vshad;
|
r_d3d11_state->vshads[kind] = vshad;
|
||||||
@@ -359,7 +373,7 @@ r_init(CmdLine *cmdln)
|
|||||||
&pshad_source_blob,
|
&pshad_source_blob,
|
||||||
&pshad_source_errors);
|
&pshad_source_errors);
|
||||||
String8 errors = {0};
|
String8 errors = {0};
|
||||||
if(pshad_source_errors)
|
if(FAILED(error))
|
||||||
{
|
{
|
||||||
errors = str8((U8 *)pshad_source_errors->GetBufferPointer(),
|
errors = str8((U8 *)pshad_source_errors->GetBufferPointer(),
|
||||||
(U64)pshad_source_errors->GetBufferSize());
|
(U64)pshad_source_errors->GetBufferSize());
|
||||||
@@ -370,6 +384,8 @@ r_init(CmdLine *cmdln)
|
|||||||
error = r_d3d11_state->device->CreatePixelShader(pshad_source_blob->GetBufferPointer(), pshad_source_blob->GetBufferSize(), 0, &pshad);
|
error = r_d3d11_state->device->CreatePixelShader(pshad_source_blob->GetBufferPointer(), pshad_source_blob->GetBufferSize(), 0, &pshad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pshad_source_blob->Release();
|
||||||
|
|
||||||
// rjf: store
|
// rjf: store
|
||||||
r_d3d11_state->pshads[kind] = pshad;
|
r_d3d11_state->pshads[kind] = pshad;
|
||||||
@@ -463,7 +479,14 @@ r_window_equip(OS_Handle handle)
|
|||||||
swapchain_desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
|
swapchain_desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
|
||||||
swapchain_desc.Flags = 0;
|
swapchain_desc.Flags = 0;
|
||||||
}
|
}
|
||||||
r_d3d11_state->dxgi_factory->CreateSwapChainForHwnd(r_d3d11_state->device, hwnd, &swapchain_desc, 0, 0, &window->swapchain);
|
HRESULT error = r_d3d11_state->dxgi_factory->CreateSwapChainForHwnd(r_d3d11_state->device, hwnd, &swapchain_desc, 0, 0, &window->swapchain);
|
||||||
|
if(FAILED(error))
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
raddbg_snprintf(buffer, sizeof(buffer), "DXGI swap chain creation failure (%x). The process is terminating.", error);
|
||||||
|
os_graphical_message(1, str8_lit("Fatal Error"), str8_cstring(buffer));
|
||||||
|
os_exit_process(1);
|
||||||
|
}
|
||||||
|
|
||||||
//- rjf: create framebuffer & view
|
//- rjf: create framebuffer & view
|
||||||
window->swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)(&window->framebuffer));
|
window->swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)(&window->framebuffer));
|
||||||
@@ -971,7 +994,14 @@ r_window_end_frame(OS_Handle window, R_Handle window_equip)
|
|||||||
////////////////////////////
|
////////////////////////////
|
||||||
//- rjf: present
|
//- rjf: present
|
||||||
//
|
//
|
||||||
wnd->swapchain->Present(1, 0);
|
HRESULT error = wnd->swapchain->Present(1, 0);
|
||||||
|
if(FAILED(error))
|
||||||
|
{
|
||||||
|
char buffer[256] = {0};
|
||||||
|
raddbg_snprintf(buffer, sizeof(buffer), "D3D11 present failure (%x). The process is terminating.", error);
|
||||||
|
os_graphical_message(1, str8_lit("Fatal Error"), str8_cstring(buffer));
|
||||||
|
os_exit_process(1);
|
||||||
|
}
|
||||||
d_ctx->ClearState();
|
d_ctx->ClearState();
|
||||||
}
|
}
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::fstream temp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+9
-2
@@ -1123,7 +1123,7 @@ txti_mut_thread_entry_point(void *p)
|
|||||||
U8 *append_data_buffer = push_array_no_zero(buffer->data_arena, U8, msg->string.size);
|
U8 *append_data_buffer = push_array_no_zero(buffer->data_arena, U8, msg->string.size);
|
||||||
MemoryCopy(append_data_buffer, msg->string.str, msg->string.size);
|
MemoryCopy(append_data_buffer, msg->string.str, msg->string.size);
|
||||||
buffer->data.size += msg->string.size;
|
buffer->data.size += msg->string.size;
|
||||||
if(buffer->data.str == 0)
|
if(buffer->data.str == 0 && msg->string.size != 0)
|
||||||
{
|
{
|
||||||
buffer->data.str = append_data_buffer;
|
buffer->data.str = append_data_buffer;
|
||||||
}
|
}
|
||||||
@@ -1133,7 +1133,14 @@ txti_mut_thread_entry_point(void *p)
|
|||||||
case TXTI_MsgKind_Reload: ProfScope("reload")
|
case TXTI_MsgKind_Reload: ProfScope("reload")
|
||||||
{
|
{
|
||||||
arena_clear(buffer->data_arena);
|
arena_clear(buffer->data_arena);
|
||||||
buffer->data = push_str8_copy(buffer->data_arena, file_contents);
|
if(file_contents.size != 0)
|
||||||
|
{
|
||||||
|
buffer->data = push_str8_copy(buffer->data_arena, file_contents);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MemoryZeroStruct(&buffer->data);
|
||||||
|
}
|
||||||
}break;
|
}break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+93
-21
@@ -15,6 +15,41 @@ tg_hash_from_string(U64 seed, String8 string)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal int
|
||||||
|
tg_qsort_compare_members_offset(TG_Member *a, TG_Member *b)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
if(a->off < b->off)
|
||||||
|
{
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
else if(a->off > b->off)
|
||||||
|
{
|
||||||
|
result = +1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
tg_key_list_push(Arena *arena, TG_KeyList *list, TG_Key key)
|
||||||
|
{
|
||||||
|
TG_KeyNode *n = push_array(arena, TG_KeyNode, 1);
|
||||||
|
n->v = key;
|
||||||
|
SLLQueuePush(list->first, list->last, n);
|
||||||
|
list->count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal TG_KeyList
|
||||||
|
tg_key_list_copy(Arena *arena, TG_KeyList *src)
|
||||||
|
{
|
||||||
|
TG_KeyList dst = {0};
|
||||||
|
for(TG_KeyNode *n = src->first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
tg_key_list_push(arena, &dst, n->v);
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: RADDBG <-> TG Enum Conversions
|
//~ rjf: RADDBG <-> TG Enum Conversions
|
||||||
|
|
||||||
@@ -742,7 +777,7 @@ tg_type_from_graph_raddbg_key(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg
|
|||||||
|
|
||||||
// rjf: commit members
|
// rjf: commit members
|
||||||
type->count = members.count;
|
type->count = members.count;
|
||||||
type->members = push_array_no_zero(arena, TG_Member, 1);
|
type->members = push_array_no_zero(arena, TG_Member, members.count);
|
||||||
U64 idx = 0;
|
U64 idx = 0;
|
||||||
for(TG_MemberNode *n = members.first; n != 0; n = n->next, idx += 1)
|
for(TG_MemberNode *n = members.first; n != 0; n = n->next, idx += 1)
|
||||||
{
|
{
|
||||||
@@ -912,36 +947,73 @@ tg_members_from_graph_raddbg_key(Arena *arena, TG_Graph *graph, RADDBG_Parsed *r
|
|||||||
internal TG_MemberArray
|
internal TG_MemberArray
|
||||||
tg_data_members_from_graph_raddbg_key(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg, TG_Key key)
|
tg_data_members_from_graph_raddbg_key(Arena *arena, TG_Graph *graph, RADDBG_Parsed *rdbg, TG_Key key)
|
||||||
{
|
{
|
||||||
TG_MemberArray result = {0};
|
|
||||||
Temp scratch = scratch_begin(&arena, 1);
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
TG_MemberList members_list = {0};
|
||||||
|
B32 members_need_offset_sort = 0;
|
||||||
{
|
{
|
||||||
TG_Type *type = tg_type_from_graph_raddbg_key(scratch.arena, graph, rdbg, key);
|
TG_Type *root_type = tg_type_from_graph_raddbg_key(scratch.arena, graph, rdbg, key);
|
||||||
if(type->members != 0)
|
typedef struct Task Task;
|
||||||
|
struct Task
|
||||||
{
|
{
|
||||||
U64 data_member_count = 0;
|
Task *next;
|
||||||
for(U64 member_idx = 0; member_idx < type->count; member_idx += 1)
|
U64 base_off;
|
||||||
|
TG_KeyList inheritance_chain;
|
||||||
|
TG_Key type_key;
|
||||||
|
TG_Type *type;
|
||||||
|
};
|
||||||
|
Task start_task = {0, 0, {0}, key, root_type};
|
||||||
|
Task *first_task = &start_task;
|
||||||
|
Task *last_task = &start_task;
|
||||||
|
for(Task *task = first_task; task != 0; task = task->next)
|
||||||
|
{
|
||||||
|
TG_Type *type = task->type;
|
||||||
|
if(type->members != 0)
|
||||||
{
|
{
|
||||||
if(type->members[member_idx].kind == TG_MemberKind_DataField)
|
for(U64 member_idx = 0; member_idx < type->count; member_idx += 1)
|
||||||
{
|
{
|
||||||
data_member_count += 1;
|
if(type->members[member_idx].kind == TG_MemberKind_DataField)
|
||||||
}
|
{
|
||||||
}
|
TG_MemberNode *n = push_array(scratch.arena, TG_MemberNode, 1);
|
||||||
result.count = data_member_count;
|
MemoryCopyStruct(&n->v, &type->members[member_idx]);
|
||||||
result.v = push_array_no_zero(arena, TG_Member, result.count);
|
n->v.off += task->base_off;
|
||||||
U64 idx = 0;
|
n->v.inheritance_key_chain = task->inheritance_chain;
|
||||||
for(U64 member_idx = 0; member_idx < type->count; member_idx += 1)
|
SLLQueuePush(members_list.first, members_list.last, n);
|
||||||
{
|
members_list.count += 1;
|
||||||
if(type->members[member_idx].kind == TG_MemberKind_DataField)
|
}
|
||||||
{
|
else if(type->members[member_idx].kind == TG_MemberKind_Base)
|
||||||
MemoryCopyStruct(&result.v[idx], &type->members[member_idx]);
|
{
|
||||||
result.v[idx].name = push_str8_copy(arena, result.v[idx].name);
|
Task *t = push_array(scratch.arena, Task, 1);
|
||||||
idx += 1;
|
t->base_off = type->members[member_idx].off + task->base_off;
|
||||||
|
t->inheritance_chain = tg_key_list_copy(scratch.arena, &task->inheritance_chain);
|
||||||
|
tg_key_list_push(scratch.arena, &t->inheritance_chain, type->members[member_idx].type_key);
|
||||||
|
t->type_key = type->members[member_idx].type_key;
|
||||||
|
t->type = tg_type_from_graph_raddbg_key(scratch.arena, graph, rdbg, type->members[member_idx].type_key);
|
||||||
|
SLLQueuePush(first_task, last_task, t);
|
||||||
|
members_need_offset_sort = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TG_MemberArray members = {0};
|
||||||
|
{
|
||||||
|
members.count = members_list.count;
|
||||||
|
members.v = push_array(arena, TG_Member, members.count);
|
||||||
|
U64 idx = 0;
|
||||||
|
for(TG_MemberNode *n = members_list.first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
MemoryCopyStruct(&members.v[idx], &n->v);
|
||||||
|
members.v[idx].name = push_str8_copy(arena, members.v[idx].name);
|
||||||
|
members.v[idx].inheritance_key_chain = tg_key_list_copy(arena, &members.v[idx].inheritance_key_chain);
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(members_need_offset_sort)
|
||||||
|
{
|
||||||
|
qsort(members.v, members.count, sizeof(TG_Member), (int (*)(const void *, const void *))tg_qsort_compare_members_offset);
|
||||||
|
}
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
return result;
|
return members;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
|
|||||||
@@ -31,6 +31,21 @@ struct TG_Key
|
|||||||
U64 u64[1]; // ext -> unique id; cons -> idx; reg -> code
|
U64 u64[1]; // ext -> unique id; cons -> idx; reg -> code
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct TG_KeyNode TG_KeyNode;
|
||||||
|
struct TG_KeyNode
|
||||||
|
{
|
||||||
|
TG_KeyNode *next;
|
||||||
|
TG_Key v;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct TG_KeyList TG_KeyList;
|
||||||
|
struct TG_KeyList
|
||||||
|
{
|
||||||
|
TG_KeyNode *first;
|
||||||
|
TG_KeyNode *last;
|
||||||
|
U64 count;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Graph Types
|
//~ rjf: Graph Types
|
||||||
|
|
||||||
@@ -102,6 +117,7 @@ struct TG_Member
|
|||||||
TG_Key type_key;
|
TG_Key type_key;
|
||||||
String8 name;
|
String8 name;
|
||||||
U64 off;
|
U64 off;
|
||||||
|
TG_KeyList inheritance_key_chain;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct TG_MemberNode TG_MemberNode;
|
typedef struct TG_MemberNode TG_MemberNode;
|
||||||
@@ -179,6 +195,9 @@ thread_static Arena *tg_build_arena = 0;
|
|||||||
//~ rjf: Basic Helpers
|
//~ rjf: Basic Helpers
|
||||||
|
|
||||||
internal U64 tg_hash_from_string(U64 seed, String8 string);
|
internal U64 tg_hash_from_string(U64 seed, String8 string);
|
||||||
|
internal int tg_qsort_compare_members_offset(TG_Member *a, TG_Member *b);
|
||||||
|
internal void tg_key_list_push(Arena *arena, TG_KeyList *list, TG_Key key);
|
||||||
|
internal TG_KeyList tg_key_list_copy(Arena *arena, TG_KeyList *src);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: RADDBG <-> TG Enum Conversions
|
//~ rjf: RADDBG <-> TG Enum Conversions
|
||||||
|
|||||||
Reference in New Issue
Block a user