Merge tag 'v0.9.10-alpha' into odin

This commit is contained in:
2024-05-26 11:12:40 -04:00
67 changed files with 4493 additions and 3598 deletions
+34 -55
View File
@@ -20,26 +20,20 @@ You can download pre-built binaries for the debugger
[here](https://github.com/EpicGames/raddebugger/releases).
The RAD Debugger project aims to simplify the debugger by simplifying and
unifying the underlying debug info format. In that pursuit we've built
the RADDBGI debug info format, which is what the debugger parses and uses. To
work with existing toolchains, we convert PDB (and eventually PE/ELF files
with embedded DWARF) into the RADDBGI format on-demand. This conversion process
is currently an unoptimized reference version. Nevertheless it's still quite
fast for smaller PDB files (in many cases faster than many other programs
simply deserialize the PDBs). It is much slower for much larger projects at the
moment, but we expect this will vastly improve overtime.
unifying the underlying debug info format. In that pursuit we've built the RAD
Debug Info (RDI) format, which is what the debugger parses and uses. To work
with existing toolchains, we convert PDB (and eventually PE/ELF files with
embedded DWARF) into the RDI format on-demand.
The RADDBGI format is currently specified in code, in the files within the
`src/lib_raddbgi_format` folder. The other relevant folders for working with
the format are:
The RDI format is currently specified in code, in the files within the
`src/lib_rdi_format` folder. The other relevant folders for working with the
format are:
- `lib_raddbgi_make`: The "RAD Debug Info Make" library, for making RADDBGI
debug info.
- `raddbgi_from_pdb`: Our PDB-to-RADDBGI converter. Can be used as a helper
codebase layer, or built as an executable with a command line interface
frontend.
- `raddbgi_from_dwarf`: Our in-progress DWARF-to-RADDBGI converter.
- `raddbgi_dump`: Our RADDBGI textual dumping utility.
- `lib_rdi_make`: The "RAD Debug Info Make" library, for making RDI debug info.
- `rdi_from_pdb`: Our PDB-to-RDI converter. Can be used as a helper codebase
layer, or built as an executable with a command line interface frontend.
- `rdi_from_dwarf`: Our in-progress DWARF-to-RDI converter.
- `rdi_dump`: Our RDI textual dumping utility.
## Development Setup Instructions
@@ -126,18 +120,6 @@ there are still cases where the debugger has not been tested, and so there are
still issues. So, we feel that the top priority is eliminating these issues,
such that the debugging experience is rock solid.
Additionally, the debug info conversion process is not fast (nor wide) enough
to support extremely large projects. This is for two reasons: (a) the
PDB-to-RADDBGI converter is an unoptimized reference implementation, and (b)
the debugger learns of new modules (and thus which PDBs to load) in a
serially-dependent way (this is necessarily the case for correct debugging
results). We expect that the conversion process' performance can be massively
improved, and also that some heuristics can be used to begin converting PDBs
to RADDBGIs before the debugger knows those PDBs are needed, thus ensuring the
associated RADDBGI files are ready instantaneously when the associated modules
are finally loaded by the debugger. Improving this situation is a major part of
this phase, as it will make the debugger much more usable for large projects.
### Local x64 Linux Debugging Phase
The next priority for the project is to take the rock solid x64 Windows
@@ -152,11 +134,10 @@ The major parts of this phase are:
- Porting the `src/demon` layer to implement the Demon local process control
abstraction API.
- Porting the `src/unwind` layer to support x64 ELF unwinding (currently, there
is only an x64 PE unwinding implementation).
- Creating a DWARF-to-RADDBGI converter (in the same way that we've built a
PDB-to-RADDBGI converter). A partial implementation of this is in
`src/raddbgi_from_dwarf`.
- Implementing an x64 ELF Linux unwinder in the `src/ctrl` layer.
- Creating a DWARF-to-RDI converter (in the same way that we've built a
PDB-to-RDI converter). A partial implementation of this is in
`src/rdi_from_dwarf`.
- Porting the `src/render` layer to implement all of the rendering features the
frontend needs on a Linux-compatible API (the backend used on Windows is D3D11).
- Porting the `src/font_provider` layer to a Linux-compatible font
@@ -218,7 +199,7 @@ so in other words, layers are arranged into a directed acyclic graph.
A few layers are built to be used completely independently from the rest of the
codebase, as libraries in other codebases and projects. As such, these layers do
not depend on any other layers in the codebase. The folders which contain these
layers are prefixed with `lib_`, like `lib_raddbgi_format`.
layers are prefixed with `lib_`, like `lib_rdi_format`.
A list of the layers in the codebase and their associated namespaces is below:
- `base` (no namespace): Universal, codebase-wide constructs. Strings, math,
@@ -235,11 +216,11 @@ A list of the layers in the codebase and their associated namespaces is below:
- `dasm` (`DASM_`): An asynchronous disassembly decoder and cache. Users ask for
disassembly for a particular virtual address range in a process, and threads
implemented in this layer decode and cache the disassembly for that range.
- `dbgi` (`DBGI_`): An asynchronous debug info loader and cache. Loads debug
info stored in the RADDBGI format. Users ask for debug info for a particular
executable, and on separate threads, this layer loads the associated debug
info file. If necessary, it will launch a separate conversion process to
convert original debug info into the RADDBGI format.
- `dbgi` (`DI_`): An asynchronous debug info loader and cache. Loads debug info
stored in the RDI format. Users ask for debug info for a particular path, and
on separate threads, this layer loads the associated debug info file. If
necessary, it will launch a separate conversion process to convert original
debug info into the RDI format.
- `demon` (`DEMON_`): An abstraction layer for local-machine, low-level process
control. The abstraction is used to provide a common interface for process
control on target platforms. Used to implement part of `ctrl`.
@@ -274,13 +255,13 @@ A list of the layers in the codebase and their associated namespaces is below:
- `lib_raddbg_markup` (`RADDBG_`): Standalone library for marking up user
programs to work with various features in the `raddbg` debugger. Does not
depend on `base`, and can be independently relocated to other codebases.
- `lib_raddbgi_make` (`RDIM_`): Standalone library for constructing RADDBGI
debug info data. Does not depend on `base`, and can be independently relocated
- `lib_rdi_make` (`RDIM_`): Standalone library for constructing RDI debug info
data. Does not depend on `base`, and can be independently relocated
to other codebases.
- `lib_raddbgi_format` (`RDI_`): Standalone library which defines the core
RADDBGI types and helper functions for reading and writing the RADDBGI debug
info file format. Does not depend on `base`, and can be independently
relocated to other codebases.
- `lib_rdi_format` (`RDI_`): Standalone library which defines the core RDI types
and helper functions for reading and writing the RDI debug info file format.
Does not depend on `base`, and can be independently relocated to other
codebases.
- `metagen` (`MG_`): A metaprogram which is used to generate primarily code and
data tables. Consumes Metadesk files, stored with the extension `.mdesk`, and
generates C code which is then included by hand-written C code. Currently, it
@@ -315,11 +296,11 @@ A list of the layers in the codebase and their associated namespaces is below:
- `raddbg` (no namespace): The layer which ties everything together for the main
graphical debugger. Not much "meat", just drives `df`, implements command line
options, and so on.
- `raddbgi_from_pdb` (`P2R_`): Our implementation of PDB-to-RADDBGI conversion.
- `raddbgi_from_dwarf` (`D2R_`): Our in-progress implementation of
DWARF-to-RADDBGI conversion.
- `raddbgi_dump` (`RADDBGIDUMP_`): A dumper utility program for dumping
textualizations of RADDBGI debug info files.
- `rdi_from_pdb` (`P2R_`): Our implementation of PDB-to-RDI conversion.
- `rdi_from_dwarf` (`D2R_`): Our in-progress implementation of DWARF-to-RDI
conversion.
- `rdi_dump` (no namespace): A dumper utility program for dumping
textualizations of RDI debug info files.
- `regs` (`REGS_`): Types, helper functions, and metadata for registers on
supported architectures. Used in reading/writing registers in `demon`, or in
looking up register metadata.
@@ -338,11 +319,9 @@ A list of the layers in the codebase and their associated namespaces is below:
Used by the debugger to visualize source code files. Users ask for text lines,
tokens, and metadata, and it is prepared on background threads.
- `type_graph` (`TG_`): Code for analyzing and navigating type structures from
RADDBGI debug info files, with the additional capability of constructing
RDI debug info files, with the additional capability of constructing
synthetic types *not* found in debug info. Used in `eval` and for various
visualization features.
- `ui` (`UI_`): Machinery for building graphical user interfaces. Provides a
core immediate mode hierarchical user interface data structure building
API, and has helper layers for building some higher-level widgets.
- `unwind` (`UNW_`): Code for generating unwind information from threads, for
supported operating systems and architectures.
+21 -12
View File
@@ -15,7 +15,7 @@ cd /D "%~dp0"
:: `build raddbg clang`
:: `build raddbg release`
:: `build raddbg asan telemetry`
:: `build raddbgi_from_pdb`
:: `build rdi_from_pdb`
::
:: For a full list of possible build targets and their build command lines,
:: search for @build_targets in this file.
@@ -54,12 +54,14 @@ set clang_out= -o
:: --- Per-Build Settings -----------------------------------------------------
set link_dll=-DLL
if "%msvc%"=="1" set only_compile=/c
if "%clang%"=="1" set only_compile=-c
if "%msvc%"=="1" set EHsc=/EHsc
if "%clang%"=="1" set EHsc=
if "%msvc%"=="1" set rc=rc.exe
if "%clang%"=="1" set rc=llvm-rc.exe
if "%msvc%"=="1" set only_compile=/c
if "%clang%"=="1" set only_compile=-c
if "%msvc%"=="1" set EHsc=/EHsc
if "%clang%"=="1" set EHsc=
if "%msvc%"=="1" set no_aslr=/DYNAMICBASE:NO
if "%clang%"=="1" set no_aslr=
if "%msvc%"=="1" set rc=rc.exe
if "%clang%"=="1" set rc=llvm-rc.exe
:: --- Choose Compile/Link Lines ----------------------------------------------
if "%msvc%"=="1" set compile_debug=%cl_debug%
@@ -97,16 +99,23 @@ if not "%no_meta%"=="1" (
:: --- Build Everything (@build_targets) --------------------------------------
pushd build
if "%raddbg%"=="1" %compile% %gfx% ..\src\raddbg\raddbg_main.cpp %compile_link% %out%raddbg.exe || exit /b 1
if "%raddbgi_from_pdb%"=="1" %compile% ..\src\raddbgi_from_pdb\raddbgi_from_pdb_main.c %compile_link% %out%raddbgi_from_pdb.exe || exit /b 1
if "%raddbgi_from_dwarf%"=="1" %compile% ..\src\raddbgi_from_dwarf\raddbgi_from_dwarf.c %compile_link% %out%raddbgi_from_dwarf.exe || exit /b 1
if "%raddbgi_dump%"=="1" %compile% ..\src\raddbgi_dump\raddbgi_dump_main.c %compile_link% %out%raddbgi_dump.exe || exit /b 1
if "%raddbgi_breakpad_from_pdb%"=="1" %compile% ..\src\raddbgi_breakpad_from_pdb\raddbgi_breakpad_from_pdb_main.c %compile_link% %out%raddbgi_breakpad_from_pdb.exe || exit /b 1
if "%rdi_from_pdb%"=="1" %compile% ..\src\rdi_from_pdb\rdi_from_pdb_main.c %compile_link% %out%rdi_from_pdb.exe || exit /b 1
if "%rdi_from_dwarf%"=="1" %compile% ..\src\rdi_from_dwarf\rdi_from_dwarf.c %compile_link% %out%rdi_from_dwarf.exe || exit /b 1
if "%rdi_dump%"=="1" %compile% ..\src\rdi_dump\rdi_dump_main.c %compile_link% %out%rdi_dump.exe || exit /b 1
if "%rdi_breakpad_from_pdb%"=="1" %compile% ..\src\rdi_breakpad_from_pdb\rdi_breakpad_from_pdb_main.c %compile_link% %out%rdi_breakpad_from_pdb.exe || exit /b 1
if "%ryan_scratch%"=="1" %compile% ..\src\scratch\ryan_scratch.c %compile_link% %out%ryan_scratch.exe || exit /b 1
if "%cpp_tests%"=="1" %compile% ..\src\scratch\i_hate_c_plus_plus.cpp %compile_link% %out%cpp_tests.exe || exit /b 1
if "%look_at_raddbg%"=="1" %compile% ..\src\scratch\look_at_raddbg.c %compile_link% %out%look_at_raddbg.exe || exit /b 1
if "%mule_main%"=="1" del vc*.pdb mule*.pdb && %compile_release% %only_compile% ..\src\mule\mule_inline.cpp && %compile_release% %only_compile% ..\src\mule\mule_o2.cpp && %compile_debug% %EHsc% ..\src\mule\mule_main.cpp ..\src\mule\mule_c.c mule_inline.obj mule_o2.obj %compile_link% %out%mule_main.exe || exit /b 1
if "%mule_main%"=="1" del vc*.pdb mule*.pdb && %compile_release% %only_compile% ..\src\mule\mule_inline.cpp && %compile_release% %only_compile% ..\src\mule\mule_o2.cpp && %compile_debug% %EHsc% ..\src\mule\mule_main.cpp ..\src\mule\mule_c.c mule_inline.obj mule_o2.obj %compile_link% %no_aslr% %out%mule_main.exe || exit /b 1
if "%mule_module%"=="1" %compile% ..\src\mule\mule_module.cpp %compile_link% %link_dll% %out%mule_module.dll || exit /b 1
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 || exit /b 1
if "%mule_peb_trample%"=="1" (
if exist mule_peb_trample.exe move mule_peb_trample.exe mule_peb_trample_old_%random%.exe
if exist mule_peb_trample_new.pdb move mule_peb_trample_new.pdb mule_peb_trample_old_%random%.pdb
if exist mule_peb_trample_new.rdi move mule_peb_trample_new.rdi mule_peb_trample_old_%random%.rdi
%compile% ..\src\mule\mule_peb_trample.c %compile_link% %out%mule_peb_trample_new.exe || exit /b 1
move mule_peb_trample_new.exe mule_peb_trample.exe
)
popd
:: --- Unset ------------------------------------------------------------------
+7 -7
View File
@@ -56,7 +56,7 @@ commands =
},
.rjf_f2 =
{
.win = "build raddbgi_from_pdb telemetry release",
.win = "build mule_peb_trample",
.linux = "",
.out = "*compilation*",
.footer_panel = true,
@@ -74,7 +74,7 @@ commands =
},
.rjf_f4 =
{
.win = "build raddbgi_from_pdb release telemetry && pushd build && raddbgi_from_pdb.exe --exe:UnrealEditorFortnite.exe --pdb:UnrealEditorFortnite.pdb --out:UnrealEditorFortnite.raddbgi --capture && popd",
.win = "build rdi_from_pdb release telemetry && pushd build && rdi_from_pdb.exe --exe:UnrealEditorFortnite.exe --pdb:UnrealEditorFortnite.pdb --out:UnrealEditorFortnite.rdi --capture && popd",
.linux = "",
.out = "*compilation*",
.footer_panel = true,
@@ -83,7 +83,7 @@ commands =
},
.rjf_f5 =
{
.win = "pushd build && raddbgi_from_pdb.exe --exe:raddbg.exe --pdb:raddbg.pdb --out:raddbg.raddbg --capture && popd",
.win = "pushd build && rdi_from_pdb.exe --exe:raddbg.exe --pdb:raddbg.pdb --out:raddbg.rdi --capture && popd",
.linux = "",
.out = "*compilation*",
.footer_panel = true,
@@ -108,18 +108,18 @@ commands =
.save_dirty_files = true,
.cursor_at_end = false,
},
.build_raddbgi_from_pdb =
.build_rdi_from_pdb =
{
.win = "build raddbgi_from_pdb",
.win = "build rdi_from_pdb",
.linux = "",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
},
.build_raddbgi_dump =
.build_rdi_dump =
{
.win = "build raddbgi_dump",
.win = "build rdi_dump",
.linux = "",
.out = "*compilation*",
.footer_panel = true,
+3 -1
View File
@@ -92,6 +92,7 @@ cmd_line_from_string_list(Arena *arena, String8List command_line)
// NOTE(rjf): Parse command line.
B32 after_passthrough_option = 0;
B32 first_passthrough = 1;
for(String8Node *node = command_line.first->next, *next = 0; node != 0; node = next)
{
next = node->next;
@@ -175,10 +176,11 @@ cmd_line_from_string_list(Arena *arena, String8List command_line)
// NOTE(rjf): Default path, treat as a passthrough config option to be
// handled by tool-specific code.
else if(!str8_match(node->string, str8_lit("--"), 0))
else if(!str8_match(node->string, str8_lit("--"), 0) || !first_passthrough)
{
str8_list_push(arena, &parsed.inputs, node->string);
after_passthrough_option = 1;
first_passthrough = 0;
}
}
+22 -19
View File
@@ -18,59 +18,62 @@ main_thread_base_entry_point(void (*entry_point)(CmdLine *cmdline), char **argum
{
ProfBeginCapture(arguments[0]);
}
#if defined(OS_CORE_H)
#if defined(OS_CORE_H) && !defined(OS_INIT_MANUAL)
os_init();
#endif
#if defined(TASK_SYSTEM_H)
#if defined(TASK_SYSTEM_H) && !defined(TS_INIT_MANUAL)
ts_init();
#endif
#if defined(HASH_STORE_H)
#if defined(HASH_STORE_H) && !defined(HS_INIT_MANUAL)
hs_init();
#endif
#if defined(FILE_STREAM_H)
#if defined(FILE_STREAM_H) && !defined(FS_INIT_MANUAL)
fs_init();
#endif
#if defined(TEXT_CACHE_H)
#if defined(TEXT_CACHE_H) && !defined(TXT_INIT_MANUAL)
txt_init();
#endif
#if defined(DASM_CACHE_H)
#if defined(DASM_CACHE_H) && !defined(DASM_INIT_MANUAL)
dasm_init();
#endif
#if defined(DBGI_H)
dbgi_init();
#if defined(DI_H) && !defined(DI_INIT_MANUAL)
di_init();
#endif
#if defined(TXTI_H)
#if defined(FUZZY_SEARCH_H) && !defined(FZY_INIT_MANUAL)
fzy_init();
#endif
#if defined(TXTI_H) && !defined(TXTI_INIT_MANUAL)
txti_init();
#endif
#if defined(DEMON_CORE_H)
#if defined(DEMON_CORE_H) && !defined(DMN_INIT_MANUAL)
dmn_init();
#endif
#if defined(CTRL_CORE_H)
#if defined(CTRL_CORE_H) && !defined(CTRL_INIT_MANUAL)
ctrl_init();
#endif
#if defined(OS_GRAPHICAL_H)
#if defined(OS_GRAPHICAL_H) && !defined(OS_GFX_INIT_MANUAL)
os_graphical_init();
#endif
#if defined(FONT_PROVIDER_H)
#if defined(FONT_PROVIDER_H) && !defined(FP_INIT_MANUAL)
fp_init();
#endif
#if defined(RENDER_CORE_H)
#if defined(RENDER_CORE_H) && !defined(R_INIT_MANUAL)
r_init(&cmdline);
#endif
#if defined(TEXTURE_CACHE_H)
#if defined(TEXTURE_CACHE_H) && !defined(TEX_INIT_MANUAL)
tex_init();
#endif
#if defined(GEO_CACHE_H)
#if defined(GEO_CACHE_H) && !defined(GEO_INIT_MANUAL)
geo_init();
#endif
#if defined(FONT_CACHE_H)
#if defined(FONT_CACHE_H) && !defined(F_INIT_MANUAL)
f_init();
#endif
#if defined(DF_CORE_H)
#if defined(DF_CORE_H) && !defined(DF_INIT_MANUAL)
DF_StateDeltaHistory *hist = df_state_delta_history_alloc();
df_core_init(&cmdline, hist);
#endif
#if defined(DF_GFX_H)
#if defined(DF_GFX_H) && !defined(DF_GFX_INIT_MANUAL)
df_gfx_init(update_and_render, df_state_delta_history());
#endif
entry_point(&cmdline);
+1549 -134
View File
File diff suppressed because it is too large Load Diff
+107 -7
View File
@@ -49,6 +49,7 @@ typedef enum CTRL_EntityKind
CTRL_EntityKind_Thread,
CTRL_EntityKind_Module,
CTRL_EntityKind_EntryPoint,
CTRL_EntityKind_DebugInfoPath,
CTRL_EntityKind_COUNT
}
CTRL_EntityKind;
@@ -67,6 +68,7 @@ struct CTRL_Entity
DMN_Handle handle;
U64 id;
Rng1U64 vaddr_range;
U64 timestamp;
String8 string;
};
@@ -107,22 +109,45 @@ struct CTRL_EntityStore
////////////////////////////////
//~ rjf: Unwind Types
typedef U32 CTRL_UnwindFlags;
enum
{
CTRL_UnwindFlag_Error = (1<<0),
CTRL_UnwindFlag_Stale = (1<<1),
};
typedef struct CTRL_UnwindStepResult CTRL_UnwindStepResult;
struct CTRL_UnwindStepResult
{
CTRL_UnwindFlags flags;
};
typedef struct CTRL_UnwindFrame CTRL_UnwindFrame;
struct CTRL_UnwindFrame
{
CTRL_UnwindFrame *next;
CTRL_UnwindFrame *prev;
U64 rip;
void *regs;
};
typedef struct CTRL_UnwindFrameNode CTRL_UnwindFrameNode;
struct CTRL_UnwindFrameNode
{
CTRL_UnwindFrameNode *next;
CTRL_UnwindFrameNode *prev;
CTRL_UnwindFrame v;
};
typedef struct CTRL_UnwindFrameArray CTRL_UnwindFrameArray;
struct CTRL_UnwindFrameArray
{
CTRL_UnwindFrame *v;
U64 count;
};
typedef struct CTRL_Unwind CTRL_Unwind;
struct CTRL_Unwind
{
CTRL_UnwindFrame *first;
CTRL_UnwindFrame *last;
U64 count;
B32 error;
CTRL_UnwindFrameArray frames;
CTRL_UnwindFlags flags;
};
////////////////////////////////
@@ -224,6 +249,7 @@ typedef enum CTRL_MsgKind
CTRL_MsgKind_Run,
CTRL_MsgKind_SingleStep,
CTRL_MsgKind_SetUserEntryPoints,
CTRL_MsgKind_SetModuleDebugInfoPath,
CTRL_MsgKind_COUNT,
}
CTRL_MsgKind;
@@ -292,6 +318,9 @@ typedef enum CTRL_EventKind
CTRL_EventKind_EndThread,
CTRL_EventKind_EndModule,
//- rjf: debug info changes
CTRL_EventKind_ModuleDebugInfoPathChange,
//- rjf: debug strings
CTRL_EventKind_DebugString,
CTRL_EventKind_ThreadName,
@@ -348,6 +377,7 @@ struct CTRL_Event
U64 rip_vaddr;
U64 stack_base;
U64 tls_root;
U64 timestamp;
U32 exception_code;
String8 string;
};
@@ -474,6 +504,47 @@ struct CTRL_ThreadRegCache
CTRL_ThreadRegCacheStripe *stripes;
};
////////////////////////////////
//~ rjf: Module Image Info Cache Types
typedef struct CTRL_ModuleImageInfoCacheNode CTRL_ModuleImageInfoCacheNode;
struct CTRL_ModuleImageInfoCacheNode
{
CTRL_ModuleImageInfoCacheNode *next;
CTRL_ModuleImageInfoCacheNode *prev;
CTRL_MachineID machine_id;
DMN_Handle module;
Arena *arena;
PE_IntelPdata *pdatas;
U64 pdatas_count;
U64 entry_point_voff;
Rng1U64 tls_vaddr_range;
String8 initial_debug_info_path;
};
typedef struct CTRL_ModuleImageInfoCacheSlot CTRL_ModuleImageInfoCacheSlot;
struct CTRL_ModuleImageInfoCacheSlot
{
CTRL_ModuleImageInfoCacheNode *first;
CTRL_ModuleImageInfoCacheNode *last;
};
typedef struct CTRL_ModuleImageInfoCacheStripe CTRL_ModuleImageInfoCacheStripe;
struct CTRL_ModuleImageInfoCacheStripe
{
Arena *arena;
OS_Handle rw_mutex;
};
typedef struct CTRL_ModuleImageInfoCache CTRL_ModuleImageInfoCache;
struct CTRL_ModuleImageInfoCache
{
U64 slots_count;
CTRL_ModuleImageInfoCacheSlot *slots;
U64 stripes_count;
CTRL_ModuleImageInfoCacheStripe *stripes;
};
////////////////////////////////
//~ rjf: Wakeup Hook Function Types
@@ -496,6 +567,7 @@ struct CTRL_State
// rjf: caches
CTRL_ProcessMemoryCache process_memory_cache;
CTRL_ThreadRegCache thread_reg_cache;
CTRL_ModuleImageInfoCache module_image_info_cache;
// rjf: user -> ctrl msg ring buffer
U64 u2c_ring_size;
@@ -615,6 +687,7 @@ internal CTRL_EntityStore *ctrl_entity_store_alloc(void);
internal void ctrl_entity_store_release(CTRL_EntityStore *store);
//- rjf: string allocation/deletion
internal U64 ctrl_name_bucket_idx_from_string_size(U64 size);
internal String8 ctrl_entity_string_alloc(CTRL_EntityStore *store, String8 string);
internal void ctrl_entity_string_release(CTRL_EntityStore *store, String8 string);
@@ -627,6 +700,7 @@ internal void ctrl_entity_equip_string(CTRL_EntityStore *store, CTRL_Entity *ent
//- rjf: entity store lookups
internal CTRL_Entity *ctrl_entity_from_machine_id_handle(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle handle);
internal CTRL_Entity *ctrl_entity_child_from_kind(CTRL_Entity *parent, CTRL_EntityKind kind);
//- rjf: applying events to entity caches
internal void ctrl_entity_store_apply_events(CTRL_EntityStore *store, CTRL_EventList *list);
@@ -654,6 +728,8 @@ internal U128 ctrl_hash_store_key_from_process_vaddr_range(CTRL_MachineID machin
//- rjf: process memory cache reading helpers
internal CTRL_ProcessMemorySlice ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 range, U64 endt_us);
internal CTRL_ProcessMemorySlice ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_MachineID machine_id, DMN_Handle process, U64 vaddr, U64 limit, U64 element_size, U64 endt_us);
internal B32 ctrl_read_cached_process_memory(CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 range, B32 *is_stale_out, void *out, U64 endt_us);
#define ctrl_read_cached_process_memory_struct(machine_id, process, vaddr, is_stale_out, ptr, endt_us) ctrl_read_cached_process_memory((machine_id), (process), r1u64((vaddr), (vaddr)+(sizeof(*(ptr)))), (is_stale_out), (ptr), (endt_us))
//- rjf: process memory writing
internal B32 ctrl_process_write(CTRL_MachineID machine_id, DMN_Handle process, Rng1U64 range, void *src);
@@ -669,9 +745,29 @@ internal U64 ctrl_query_cached_rip_from_thread(CTRL_EntityStore *store, CTRL_Mac
//- rjf: thread register writing
internal B32 ctrl_thread_write_reg_block(CTRL_MachineID machine_id, DMN_Handle thread, void *block);
////////////////////////////////
//~ rjf: Module Image Info Functions
//- rjf: cache lookups
internal PE_IntelPdata *ctrl_intel_pdata_from_module_voff(Arena *arena, CTRL_MachineID machine_id, DMN_Handle module_handle, U64 voff);
internal U64 ctrl_entry_point_voff_from_module(CTRL_MachineID machine_id, DMN_Handle module_handle);
internal Rng1U64 ctrl_tls_vaddr_range_from_module(CTRL_MachineID machine_id, DMN_Handle module_handle);
internal String8 ctrl_initial_debug_info_path_from_module(Arena *arena, CTRL_MachineID machine_id, DMN_Handle module_handle);
////////////////////////////////
//~ rjf: Unwinding Functions
//- rjf: unwind deep copier
internal CTRL_Unwind ctrl_unwind_deep_copy(Arena *arena, Architecture arch, CTRL_Unwind *src);
//- rjf: [x64]
internal REGS_Reg64 *ctrl_unwind_reg_from_pe_gpr_reg__pe_x64(REGS_RegBlockX64 *regs, PE_UnwindGprRegX64 gpr_reg);
internal CTRL_UnwindStepResult ctrl_unwind_step__pe_x64(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle process_handle, DMN_Handle module, REGS_RegBlockX64 *regs, U64 endt_us);
//- rjf: abstracted unwind step
internal CTRL_UnwindStepResult ctrl_unwind_step(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle process_handle, DMN_Handle module, Architecture arch, void *reg_block, U64 endt_us);
//- rjf: abstracted full unwind
internal CTRL_Unwind ctrl_unwind_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle thread, U64 endt_us);
////////////////////////////////
@@ -709,6 +805,10 @@ internal void ctrl_thread__entry_point(void *p);
internal void ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_MachineID machine_id, DMN_Handle process, DMN_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
internal void ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_MachineID machine_id, DMN_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
//- rjf: module lifetime open/close work
internal void ctrl_thread__module_open(CTRL_MachineID machine_id, DMN_Handle process, DMN_Handle module, Rng1U64 vaddr_range, String8 path, U64 exe_timestamp);
internal void ctrl_thread__module_close(CTRL_MachineID machine_id, DMN_Handle module, String8 path);
//- rjf: attached process running/event gathering
internal DMN_Event *ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, DMN_RunCtrls *run_ctrls, CTRL_Spoof *spoof);
+30 -21
View File
@@ -24,7 +24,7 @@ dasm_params_match(DASM_Params *a, DASM_Params *b)
a->style_flags == b->style_flags &&
a->syntax == b->syntax &&
a->base_vaddr == b->base_vaddr &&
str8_match(a->exe_path, b->exe_path, 0));
di_key_match(&a->dbgi_key, &b->dbgi_key));
return result;
}
@@ -189,7 +189,7 @@ dasm_scope_touch_node__stripe_r_guarded(DASM_Scope *scope, DASM_Node *node)
ins_atomic_u64_eval_assign(&node->last_user_clock_idx_touched, dasm_user_clock_idx());
touch->hash = node->hash;
MemoryCopyStruct(&touch->params, &node->params);
touch->params.exe_path = push_str8_copy(dasm_tctx->arena, touch->params.exe_path);
touch->params.dbgi_key = di_key_copy(dasm_tctx->arena, &touch->params.dbgi_key);
SLLStackPush(scope->top_touch, touch);
}
@@ -236,6 +236,14 @@ dasm_info_from_hash_params(DASM_Scope *scope, U128 hash, DASM_Params *params)
}
if(node == 0)
{
log_infof("[dasm] cache miss, creating node...\n");
log_infof(" hash: [0x%I64x 0x%I64x]\n", hash.u64[0], hash.u64[1]);
log_infof(" vaddr: 0x%I64x\n", params->vaddr);
log_infof(" arch: %S\n", string_from_architecture(params->arch));
log_infof(" style_flags: 0x%x\n", params->style_flags);
log_infof(" syntax: %i\n", params->syntax);
log_infof(" base_vaddr: 0x%I64x\n", params->base_vaddr);
log_infof(" dbgi_key: [%S 0x%I64x]\n", params->dbgi_key.path, params->dbgi_key.min_timestamp);
node = stripe->free_node;
if(node)
{
@@ -250,7 +258,7 @@ dasm_info_from_hash_params(DASM_Scope *scope, U128 hash, DASM_Params *params)
node->hash = hash;
MemoryCopyStruct(&node->params, params);
// TODO(rjf): need to make this releasable - currently all exe_paths just leak
node->params.exe_path = push_str8_copy(stripe->arena, node->params.exe_path);
node->params.dbgi_key = di_key_copy(stripe->arena, &node->params.dbgi_key);
node_is_new = 1;
}
}
@@ -294,7 +302,7 @@ dasm_u2p_enqueue_req(U128 hash, DASM_Params *params, U64 endt_us)
{
U64 unconsumed_size = dasm_shared->u2p_ring_write_pos - dasm_shared->u2p_ring_read_pos;
U64 available_size = dasm_shared->u2p_ring_size - unconsumed_size;
if(available_size >= sizeof(hash)+sizeof(U64)+sizeof(Architecture)+sizeof(DASM_StyleFlags)+sizeof(DASM_Syntax)+sizeof(U64)+sizeof(U64)+params->exe_path.size)
if(available_size >= sizeof(hash)+sizeof(U64)+sizeof(Architecture)+sizeof(DASM_StyleFlags)+sizeof(DASM_Syntax)+sizeof(U64)+sizeof(U64)+params->dbgi_key.path.size+sizeof(U64))
{
good = 1;
dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, &hash);
@@ -303,8 +311,9 @@ dasm_u2p_enqueue_req(U128 hash, DASM_Params *params, U64 endt_us)
dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, &params->style_flags);
dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, &params->syntax);
dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, &params->base_vaddr);
dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, &params->exe_path.size);
dasm_shared->u2p_ring_write_pos += ring_write(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, params->exe_path.str, params->exe_path.size);
dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, &params->dbgi_key.path.size);
dasm_shared->u2p_ring_write_pos += ring_write(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, params->dbgi_key.path.str, params->dbgi_key.path.size);
dasm_shared->u2p_ring_write_pos += ring_write_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_write_pos, &params->dbgi_key.min_timestamp);
dasm_shared->u2p_ring_write_pos += 7;
dasm_shared->u2p_ring_write_pos -= dasm_shared->u2p_ring_write_pos%8;
break;
@@ -328,7 +337,7 @@ dasm_u2p_dequeue_req(Arena *arena, U128 *hash_out, DASM_Params *params_out)
OS_MutexScope(dasm_shared->u2p_ring_mutex) for(;;)
{
U64 unconsumed_size = dasm_shared->u2p_ring_write_pos - dasm_shared->u2p_ring_read_pos;
if(unconsumed_size >= sizeof(*hash_out)+sizeof(U64)+sizeof(Architecture)+sizeof(DASM_StyleFlags)+sizeof(DASM_Syntax)+sizeof(U64)+sizeof(U64))
if(unconsumed_size >= sizeof(*hash_out)+sizeof(U64)+sizeof(Architecture)+sizeof(DASM_StyleFlags)+sizeof(DASM_Syntax)+sizeof(U64)+sizeof(U64)+sizeof(U64))
{
dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, hash_out);
dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, &params_out->vaddr);
@@ -336,9 +345,10 @@ dasm_u2p_dequeue_req(Arena *arena, U128 *hash_out, DASM_Params *params_out)
dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, &params_out->style_flags);
dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, &params_out->syntax);
dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, &params_out->base_vaddr);
dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, &params_out->exe_path.size);
params_out->exe_path.str = push_array(arena, U8, params_out->exe_path.size);
dasm_shared->u2p_ring_read_pos += ring_read(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, params_out->exe_path.str, params_out->exe_path.size);
dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, &params_out->dbgi_key.path.size);
params_out->dbgi_key.path.str = push_array(arena, U8, params_out->dbgi_key.path.size);
dasm_shared->u2p_ring_read_pos += ring_read(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, params_out->dbgi_key.path.str, params_out->dbgi_key.path.size);
dasm_shared->u2p_ring_read_pos += ring_read_struct(dasm_shared->u2p_ring_base, dasm_shared->u2p_ring_size, dasm_shared->u2p_ring_read_pos, &params_out->dbgi_key.min_timestamp);
dasm_shared->u2p_ring_read_pos += 7;
dasm_shared->u2p_ring_read_pos -= dasm_shared->u2p_ring_read_pos%8;
break;
@@ -362,7 +372,7 @@ dasm_parse_thread__entry_point(void *p)
dasm_u2p_dequeue_req(scratch.arena, &hash, &params);
U64 change_gen = fs_change_gen();
HS_Scope *hs_scope = hs_scope_open();
DBGI_Scope *dbgi_scope = dbgi_scope_open();
DI_Scope *di_scope = di_scope_open();
TXT_Scope *txt_scope = txt_scope_open();
//- rjf: unpack hash
@@ -386,12 +396,11 @@ dasm_parse_thread__entry_point(void *p)
}
//- rjf: get dbg info
DBGI_Parse *dbgi = &dbgi_parse_nil;
if(got_task && params.exe_path.size != 0)
RDI_Parsed *rdi = &di_rdi_parsed_nil;
if(got_task && params.dbgi_key.path.size != 0)
{
dbgi = dbgi_parse_from_exe_path(dbgi_scope, params.exe_path, max_U64);
rdi = di_rdi_from_key(di_scope, &params.dbgi_key, max_U64);
}
RDI_Parsed *rdi = &dbgi->rdi;
//- rjf: hash -> data
String8 data = {0};
@@ -442,7 +451,7 @@ dasm_parse_thread__entry_point(void *p)
// rjf: push strings derived from voff -> line info
if(params.style_flags & (DASM_StyleFlag_SourceFilesNames|DASM_StyleFlag_SourceLines))
{
if(dbgi != &dbgi_parse_nil)
if(rdi != &di_rdi_parsed_nil)
{
U64 voff = (params.vaddr+off) - params.base_vaddr;
U32 unit_idx = rdi_vmap_idx_from_voff(rdi->unit_vmap, rdi->unit_vmap_count, voff);
@@ -517,7 +526,7 @@ dasm_parse_thread__entry_point(void *p)
String8 addr_part = {0};
if(params.style_flags & DASM_StyleFlag_Addresses)
{
addr_part = push_str8f(scratch.arena, "%s%016I64X ", dbgi != &dbgi_parse_nil ? " " : "", params.vaddr+off);
addr_part = push_str8f(scratch.arena, "%s%016I64X ", rdi != &di_rdi_parsed_nil ? " " : "", params.vaddr+off);
}
String8 code_bytes_part = {0};
if(params.style_flags & DASM_StyleFlag_CodeBytes)
@@ -539,7 +548,7 @@ dasm_parse_thread__entry_point(void *p)
code_bytes_part = str8_list_join(scratch.arena, &code_bytes_strings, 0);
}
String8 symbol_part = {0};
if(jump_dst_vaddr != 0 && dbgi != &dbgi_parse_nil && params.style_flags & DASM_StyleFlag_SymbolNames)
if(jump_dst_vaddr != 0 && rdi != &di_rdi_parsed_nil && params.style_flags & DASM_StyleFlag_SymbolNames)
{
RDI_U32 scope_idx = rdi_vmap_idx_from_voff(rdi->scope_vmap, rdi->scope_vmap_count, jump_dst_vaddr-params.base_vaddr);
if(scope_idx != 0)
@@ -590,7 +599,7 @@ dasm_parse_thread__entry_point(void *p)
(U64)params.arch,
(U64)params.style_flags,
(U64)params.syntax,
(U64)dbgi,
(U64)rdi,
0x4d534144,
};
text_key = hs_hash_from_data(str8((U8 *)hash_data, sizeof(hash_data)));
@@ -614,7 +623,7 @@ dasm_parse_thread__entry_point(void *p)
{
n->info_arena = info_arena;
MemoryCopyStruct(&n->info, &info);
if(dbgi != &dbgi_parse_nil && params.style_flags & (DASM_StyleFlag_SourceLines|DASM_StyleFlag_SourceFilesNames))
if(rdi != &di_rdi_parsed_nil && params.style_flags & (DASM_StyleFlag_SourceLines|DASM_StyleFlag_SourceFilesNames))
{
n->change_gen = change_gen;
}
@@ -630,7 +639,7 @@ dasm_parse_thread__entry_point(void *p)
}
txt_scope_close(txt_scope);
dbgi_scope_close(dbgi_scope);
di_scope_close(di_scope);
hs_scope_close(hs_scope);
scratch_end(scratch);
}
+1 -1
View File
@@ -36,7 +36,7 @@ struct DASM_Params
DASM_StyleFlags style_flags;
DASM_Syntax syntax;
U64 base_vaddr;
String8 exe_path;
DI_Key dbgi_key;
};
////////////////////////////////
+590 -1078
View File
File diff suppressed because it is too large Load Diff
+194 -337
View File
@@ -1,294 +1,170 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef DBGI_H
#define DBGI_H
#ifndef DI_H
#define DI_H
////////////////////////////////
//~ rjf: Info Bundle Types
//~ rjf: Cache Key Type
typedef struct DBGI_Parse DBGI_Parse;
struct DBGI_Parse
typedef struct DI_Key DI_Key;
struct DI_Key
{
U64 gen;
Arena *arena;
void *exe_base;
FileProperties exe_props;
String8 dbg_path;
void *dbg_base;
FileProperties dbg_props;
PE_BinInfo pe;
RDI_Parsed rdi;
String8 path;
U64 min_timestamp;
};
////////////////////////////////
//~ rjf: Exe -> Debug Forced Override Cache Types
typedef struct DBGI_ForceNode DBGI_ForceNode;
struct DBGI_ForceNode
typedef struct DI_KeyNode DI_KeyNode;
struct DI_KeyNode
{
DBGI_ForceNode *next;
String8 exe_path;
U64 dbg_path_cap;
U64 dbg_path_size;
U8 *dbg_path_base;
DI_KeyNode *next;
DI_Key v;
};
typedef struct DBGI_ForceSlot DBGI_ForceSlot;
struct DBGI_ForceSlot
typedef struct DI_KeyList DI_KeyList;
struct DI_KeyList
{
DBGI_ForceNode *first;
DBGI_ForceNode *last;
};
typedef struct DBGI_ForceStripe DBGI_ForceStripe;
struct DBGI_ForceStripe
{
Arena *arena;
OS_Handle rw_mutex;
OS_Handle cv;
};
////////////////////////////////
//~ rjf: Binary Cache State Types
typedef U32 DBGI_BinaryFlags;
enum
{
DBGI_BinaryFlag_ParseInFlight = (1<<0),
};
typedef struct DBGI_Binary DBGI_Binary;
struct DBGI_Binary
{
// rjf: links & metadata
DBGI_Binary *next;
String8 exe_path;
U64 refcount;
U64 scope_touch_count;
U64 last_time_enqueued_for_parse_us;
DBGI_BinaryFlags flags;
U64 gen;
// rjf: exe handles
OS_Handle exe_file;
OS_Handle exe_file_map;
// rjf: debug handles
OS_Handle dbg_file;
OS_Handle dbg_file_map;
// rjf: analysis results
DBGI_Parse parse;
};
typedef struct DBGI_BinarySlot DBGI_BinarySlot;
struct DBGI_BinarySlot
{
DBGI_Binary *first;
DBGI_Binary *last;
};
typedef struct DBGI_BinaryStripe DBGI_BinaryStripe;
struct DBGI_BinaryStripe
{
Arena *arena;
OS_Handle rw_mutex;
OS_Handle cv;
};
////////////////////////////////
//~ rjf: Fuzzy Search Cache Types
typedef enum DBGI_FuzzySearchTarget
{
DBGI_FuzzySearchTarget_Procedures,
DBGI_FuzzySearchTarget_GlobalVariables,
DBGI_FuzzySearchTarget_ThreadVariables,
DBGI_FuzzySearchTarget_UDTs,
DBGI_FuzzySearchTarget_COUNT
}
DBGI_FuzzySearchTarget;
typedef struct DBGI_FuzzySearchItem DBGI_FuzzySearchItem;
struct DBGI_FuzzySearchItem
{
U64 idx;
U64 missed_size;
FuzzyMatchRangeList match_ranges;
};
typedef struct DBGI_FuzzySearchItemChunk DBGI_FuzzySearchItemChunk;
struct DBGI_FuzzySearchItemChunk
{
DBGI_FuzzySearchItemChunk *next;
DBGI_FuzzySearchItem *v;
U64 count;
U64 cap;
};
typedef struct DBGI_FuzzySearchItemChunkList DBGI_FuzzySearchItemChunkList;
struct DBGI_FuzzySearchItemChunkList
{
DBGI_FuzzySearchItemChunk *first;
DBGI_FuzzySearchItemChunk *last;
U64 chunk_count;
U64 total_count;
};
typedef struct DBGI_FuzzySearchItemArray DBGI_FuzzySearchItemArray;
struct DBGI_FuzzySearchItemArray
{
DBGI_FuzzySearchItem *v;
DI_KeyNode *first;
DI_KeyNode *last;
U64 count;
};
typedef struct DBGI_FuzzySearchBucket DBGI_FuzzySearchBucket;
struct DBGI_FuzzySearchBucket
typedef struct DI_KeyArray DI_KeyArray;
struct DI_KeyArray
{
Arena *arena;
String8 exe_path;
String8 query;
DBGI_FuzzySearchTarget target;
};
typedef struct DBGI_FuzzySearchNode DBGI_FuzzySearchNode;
struct DBGI_FuzzySearchNode
{
DBGI_FuzzySearchNode *next;
U128 key;
U64 scope_touch_count;
U64 last_time_submitted_us;
DBGI_FuzzySearchBucket buckets[3];
U64 gen;
U64 submit_gen;
DBGI_FuzzySearchItemArray gen_items;
};
typedef struct DBGI_FuzzySearchSlot DBGI_FuzzySearchSlot;
struct DBGI_FuzzySearchSlot
{
DBGI_FuzzySearchNode *first;
DBGI_FuzzySearchNode *last;
};
typedef struct DBGI_FuzzySearchStripe DBGI_FuzzySearchStripe;
struct DBGI_FuzzySearchStripe
{
Arena *arena;
OS_Handle rw_mutex;
OS_Handle cv;
};
typedef struct DBGI_FuzzySearchThread DBGI_FuzzySearchThread;
struct DBGI_FuzzySearchThread
{
OS_Handle thread;
OS_Handle u2f_ring_mutex;
OS_Handle u2f_ring_cv;
U64 u2f_ring_size;
U8 *u2f_ring_base;
U64 u2f_ring_write_pos;
U64 u2f_ring_read_pos;
};
////////////////////////////////
//~ rjf: Weak Access Scope Types
typedef struct DBGI_TouchedBinary DBGI_TouchedBinary;
struct DBGI_TouchedBinary
{
DBGI_TouchedBinary *next;
DBGI_Binary *binary;
};
typedef struct DBGI_TouchedFuzzySearch DBGI_TouchedFuzzySearch;
struct DBGI_TouchedFuzzySearch
{
DBGI_TouchedFuzzySearch *next;
DBGI_FuzzySearchNode *node;
};
typedef struct DBGI_Scope DBGI_Scope;
struct DBGI_Scope
{
DBGI_Scope *next;
DBGI_TouchedBinary *first_tb;
DBGI_TouchedBinary *last_tb;
DBGI_TouchedFuzzySearch *first_tfs;
DBGI_TouchedFuzzySearch *last_tfs;
};
typedef struct DBGI_ThreadCtx DBGI_ThreadCtx;
struct DBGI_ThreadCtx
{
Arena *arena;
DBGI_Scope *free_scope;
DBGI_TouchedBinary *free_tb;
DBGI_TouchedFuzzySearch *free_tfs;
DI_Key *v;
U64 count;
};
////////////////////////////////
//~ rjf: Event Types
typedef enum DBGI_EventKind
typedef enum DI_EventKind
{
DBGI_EventKind_Null,
DBGI_EventKind_ConversionStarted,
DBGI_EventKind_ConversionEnded,
DBGI_EventKind_ConversionFailureUnsupportedFormat,
DBGI_EventKind_COUNT
DI_EventKind_Null,
DI_EventKind_ConversionStarted,
DI_EventKind_ConversionEnded,
DI_EventKind_ConversionFailureUnsupportedFormat,
DI_EventKind_COUNT
}
DBGI_EventKind;
DI_EventKind;
typedef struct DBGI_Event DBGI_Event;
struct DBGI_Event
typedef struct DI_Event DI_Event;
struct DI_Event
{
DBGI_EventKind kind;
DI_EventKind kind;
String8 string;
};
typedef struct DBGI_EventNode DBGI_EventNode;
struct DBGI_EventNode
typedef struct DI_EventNode DI_EventNode;
struct DI_EventNode
{
DBGI_EventNode *next;
DBGI_Event v;
DI_EventNode *next;
DI_Event v;
};
typedef struct DBGI_EventList DBGI_EventList;
struct DBGI_EventList
typedef struct DI_EventList DI_EventList;
struct DI_EventList
{
DBGI_EventNode *first;
DBGI_EventNode *last;
DI_EventNode *first;
DI_EventNode *last;
U64 count;
};
////////////////////////////////
//~ rjf: Cross-Thread Shared State
//~ rjf: Cache Types
typedef struct DBGI_Shared DBGI_Shared;
struct DBGI_Shared
typedef struct DI_StringChunkNode DI_StringChunkNode;
struct DI_StringChunkNode
{
DI_StringChunkNode *next;
U64 size;
};
typedef struct DI_Node DI_Node;
struct DI_Node
{
// rjf: links
DI_Node *next;
DI_Node *prev;
// rjf: metadata
U64 ref_count;
U64 touch_count;
U64 is_working;
U64 last_time_requested_us;
// rjf: key
DI_Key key;
// rjf: file handles
OS_Handle file;
OS_Handle file_map;
void *file_base;
FileProperties file_props;
// rjf: parse artifacts
Arena *arena;
RDI_Parsed rdi;
B32 parse_done;
};
typedef struct DI_Slot DI_Slot;
struct DI_Slot
{
DI_Node *first;
DI_Node *last;
};
typedef struct DI_Stripe DI_Stripe;
struct DI_Stripe
{
Arena *arena;
DI_Node *free_node;
DI_StringChunkNode *free_string_chunks[8];
OS_Handle rw_mutex;
OS_Handle cv;
};
////////////////////////////////
//~ rjf: Scoped Access Types
typedef struct DI_Touch DI_Touch;
struct DI_Touch
{
DI_Touch *next;
DI_Node *node;
};
typedef struct DI_Scope DI_Scope;
struct DI_Scope
{
DI_Scope *next;
DI_Touch *first_touch;
DI_Touch *last_touch;
};
typedef struct DI_TCTX DI_TCTX;
struct DI_TCTX
{
Arena *arena;
DI_Scope *free_scope;
DI_Touch *free_touch;
};
////////////////////////////////
//~ rjf: Shared State Types
typedef struct DI_Shared DI_Shared;
struct DI_Shared
{
// rjf: arena
Arena *arena;
// rjf: forced override table
U64 force_slots_count;
U64 force_stripes_count;
DBGI_ForceSlot *force_slots;
DBGI_ForceStripe *force_stripes;
// rjf: binary table
U64 binary_slots_count;
U64 binary_stripes_count;
DBGI_BinarySlot *binary_slots;
DBGI_BinaryStripe *binary_stripes;
// rjf: fuzzy search cache table
U64 fuzzy_search_slots_count;
U64 fuzzy_search_stripes_count;
DBGI_FuzzySearchSlot *fuzzy_search_slots;
DBGI_FuzzySearchStripe *fuzzy_search_stripes;
// rjf: node cache
U64 slots_count;
DI_Slot *slots;
U64 stripes_count;
DI_Stripe *stripes;
// rjf: user -> parse ring
OS_Handle u2p_ring_mutex;
@@ -309,123 +185,104 @@ struct DBGI_Shared
// rjf: threads
U64 parse_thread_count;
OS_Handle *parse_threads;
U64 fuzzy_thread_count;
DBGI_FuzzySearchThread *fuzzy_threads;
};
////////////////////////////////
//~ rjf: Globals
global DBGI_Shared *dbgi_shared = 0;
thread_static DBGI_ThreadCtx *dbgi_tctx = 0;
global DBGI_Parse dbgi_parse_nil =
global DI_Shared *di_shared = 0;
thread_static DI_TCTX *di_tctx = 0;
global RDI_Parsed di_rdi_parsed_nil =
{
0,
0,
0,
{0},
{0},
0,
{0},
{0},
{
0,
0,
0,
0,
{0},
0,
0,
0,
0,
0,
0,
0,
&rdi_binary_section_nil, 1,
&rdi_file_path_node_nil, 1,
&rdi_source_file_nil, 1,
&rdi_unit_nil, 1,
&rdi_vmap_entry_nil, 1,
&rdi_type_node_nil, 1,
&rdi_udt_nil, 1,
&rdi_member_nil, 1,
&rdi_enum_member_nil, 1,
&rdi_global_variable_nil, 1,
&rdi_vmap_entry_nil, 1,
&rdi_thread_variable_nil, 1,
&rdi_procedure_nil, 1,
&rdi_scope_nil, 1,
&rdi_voff_nil, 1,
&rdi_vmap_entry_nil, 1,
&rdi_local_nil, 1,
&rdi_location_block_nil, 1,
0, 0,
0, 0,
},
0,
0,
0,
0,
0,
0,
&rdi_top_level_info_nil,
&rdi_binary_section_nil, 1,
&rdi_file_path_node_nil, 1,
&rdi_source_file_nil, 1,
&rdi_unit_nil, 1,
&rdi_vmap_entry_nil, 1,
&rdi_type_node_nil, 1,
&rdi_udt_nil, 1,
&rdi_member_nil, 1,
&rdi_enum_member_nil, 1,
&rdi_global_variable_nil, 1,
&rdi_vmap_entry_nil, 1,
&rdi_thread_variable_nil, 1,
&rdi_procedure_nil, 1,
&rdi_scope_nil, 1,
&rdi_voff_nil, 1,
&rdi_vmap_entry_nil, 1,
&rdi_local_nil, 1,
&rdi_location_block_nil, 1,
0, 0,
0, 0,
};
////////////////////////////////
//~ rjf: Basic Helpers
internal U64 di_hash_from_string(String8 string, StringMatchFlags match_flags);
internal U64 di_hash_from_key(DI_Key *k);
internal B32 di_key_match(DI_Key *a, DI_Key *b);
internal DI_Key di_key_copy(Arena *arena, DI_Key *src);
internal DI_Key di_normalized_key_from_key(Arena *arena, DI_Key *src);
internal void di_key_list_push(Arena *arena, DI_KeyList *list, DI_Key *key);
internal DI_KeyArray di_key_array_from_list(Arena *arena, DI_KeyList *list);
////////////////////////////////
//~ rjf: Main Layer Initialization
internal void dbgi_init(void);
////////////////////////////////
//~ rjf: Thread-Context Idempotent Initialization
internal void dbgi_ensure_tctx_inited(void);
////////////////////////////////
//~ rjf: Helpers
internal U64 dbgi_hash_from_string(String8 string, StringMatchFlags match_flags);
internal U64 dbgi_fuzzy_item_num_from_array_element_idx__linear_search(DBGI_FuzzySearchItemArray *array, U64 element_idx);
internal String8 dbgi_fuzzy_item_string_from_rdi_target_element_idx(RDI_Parsed *rdi, DBGI_FuzzySearchTarget target, U64 element_idx);
////////////////////////////////
//~ rjf: Forced Override Cache Functions
internal void dbgi_force_exe_path_dbg_path(String8 exe_path, String8 dbg_path);
internal String8 dbgi_forced_dbg_path_from_exe_path(Arena *arena, String8 exe_path);
internal void di_init(void);
////////////////////////////////
//~ rjf: Scope Functions
internal DBGI_Scope *dbgi_scope_open(void);
internal void dbgi_scope_close(DBGI_Scope *scope);
internal void dbgi_scope_touch_binary__stripe_mutex_r_guarded(DBGI_Scope *scope, DBGI_Binary *binary);
internal void dbgi_scope_touch_fuzzy_search__stripe_mutex_r_guarded(DBGI_Scope *scope, DBGI_FuzzySearchNode *node);
internal DI_Scope *di_scope_open(void);
internal void di_scope_close(DI_Scope *scope);
internal void di_scope_touch_node__stripe_mutex_r_guarded(DI_Scope *scope, DI_Node *node);
////////////////////////////////
//~ rjf: Binary Cache Functions
//~ rjf: Per-Slot Functions
internal void dbgi_binary_open(String8 exe_path);
internal void dbgi_binary_close(String8 exe_path);
internal DBGI_Parse *dbgi_parse_from_exe_path(DBGI_Scope *scope, String8 exe_path, U64 endt_us);
internal DI_Node *di_node_from_key_slot__stripe_mutex_r_guarded(DI_Slot *slot, DI_Key *key);
////////////////////////////////
//~ rjf: Fuzzy Search Cache Functions
//~ rjf: Per-Stripe Functions
internal DBGI_FuzzySearchItemArray dbgi_fuzzy_search_items_from_key_exe_query(DBGI_Scope *scope, U128 key, String8 exe_path, String8 query, DBGI_FuzzySearchTarget target, U64 endt_us, B32 *stale_out);
internal U64 di_string_bucket_idx_from_string_size(U64 size);
internal String8 di_string_alloc__stripe_mutex_w_guarded(DI_Stripe *stripe, String8 string);
internal void di_string_release__stripe_mutex_w_guarded(DI_Stripe *stripe, String8 string);
////////////////////////////////
//~ rjf: Key Opening/Closing
internal void di_open(DI_Key *key);
internal void di_close(DI_Key *key);
////////////////////////////////
//~ rjf: Cache Lookups
internal RDI_Parsed *di_rdi_from_key(DI_Scope *scope, DI_Key *key, U64 endt_us);
////////////////////////////////
//~ rjf: Parse Threads
internal B32 dbgi_u2p_enqueue_exe_path(String8 exe_path, U64 endt_us);
internal String8 dbgi_u2p_dequeue_exe_path(Arena *arena);
internal B32 di_u2p_enqueue_key(DI_Key *key, U64 endt_us);
internal void di_u2p_dequeue_key(Arena *arena, DI_Key *out_key);
internal void dbgi_p2u_push_event(DBGI_Event *event);
internal DBGI_EventList dbgi_p2u_pop_events(Arena *arena, U64 endt_us);
internal void di_p2u_push_event(DI_Event *event);
internal DI_EventList di_p2u_pop_events(Arena *arena, U64 endt_us);
internal void dbgi_parse_thread_entry_point(void *p);
internal void di_parse_thread__entry_point(void *p);
////////////////////////////////
//~ rjf: Fuzzy Searching Threads
internal B32 dbgi_u2f_enqueue_req(U128 key, U64 endt_us);
internal void dbgi_u2f_dequeue_req(Arena *arena, DBGI_FuzzySearchThread *thread, U128 *key_out);
internal int dbgi_qsort_compare_fuzzy_search_items(DBGI_FuzzySearchItem *a, DBGI_FuzzySearchItem *b);
internal void dbgi_fuzzy_thread__entry_point(void *p);
#endif //DBGI_H
#endif // DI_H
+238 -296
View File
File diff suppressed because it is too large Load Diff
+47 -52
View File
@@ -265,10 +265,10 @@ struct DF_Eval
////////////////////////////////
//~ rjf: View Rule Hook Types
#define DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_SIG(name) DF_Eval name(Arena *arena, DBGI_Scope *dbgi_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_Eval eval, struct DF_CfgVal *val)
#define DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_SIG(name) DF_Eval name(Arena *arena, DI_Scope *di_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_Eval eval, struct DF_CfgVal *val)
#define DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME(name) df_core_view_rule_eval_resolution__##name
#define DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_DEF(name) internal DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_SIG(DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME(name))
#define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_SIG(name) void name(Arena *arena, DBGI_Scope *dbgi_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, struct DF_EvalView *eval_view, DF_Eval eval, String8 string, struct DF_CfgTable *cfg_table, DF_ExpandKey parent_key, DF_ExpandKey key, S32 depth, struct DF_CfgNode *cfg, struct DF_EvalVizBlockList *out)
#define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_SIG(name) void name(Arena *arena, DI_Scope *di_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, struct DF_EvalView *eval_view, DF_Eval eval, String8 string, struct DF_CfgTable *cfg_table, DF_ExpandKey parent_key, DF_ExpandKey key, S32 depth, struct DF_CfgNode *cfg, struct DF_EvalVizBlockList *out)
#define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(name) df_core_view_rule_viz_block_prod__##name
#define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(name) internal DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_SIG(DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(name))
typedef DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_SIG(DF_CoreViewRuleEvalResolutionHookFunctionType);
@@ -521,7 +521,7 @@ struct DF_TextLineSrc2DasmInfo
{
Rng1U64 voff_range;
S64 remap_line;
DF_Entity *binary;
DI_Key dbgi_key;
};
typedef struct DF_TextLineSrc2DasmInfoNode DF_TextLineSrc2DasmInfoNode;
@@ -543,7 +543,7 @@ typedef struct DF_TextLineSrc2DasmInfoListArray DF_TextLineSrc2DasmInfoListArray
struct DF_TextLineSrc2DasmInfoListArray
{
DF_TextLineSrc2DasmInfoList *v;
DF_EntityList binaries;
DI_KeyList dbgi_keys;
U64 count;
};
@@ -552,7 +552,7 @@ struct DF_TextLineSrc2DasmInfoListArray
typedef struct DF_TextLineDasm2SrcInfo DF_TextLineDasm2SrcInfo;
struct DF_TextLineDasm2SrcInfo
{
DF_Entity *binary;
DI_Key dbgi_key;
DF_Entity *file;
TxtPt pt;
Rng1U64 voff_range;
@@ -708,8 +708,8 @@ struct DF_EvalVizBlock
// rjf: info about ranges that this block spans
Rng1U64 visual_idx_range;
Rng1U64 semantic_idx_range;
DBGI_FuzzySearchTarget dbgi_target;
DBGI_FuzzySearchItemArray backing_search_items;
FZY_Target fzy_target;
FZY_ItemArray fzy_backing_items;
// rjf: visualization config extensions
DF_CfgTable cfg_table;
@@ -946,29 +946,33 @@ struct DF_AutoViewRuleMapCache
DF_AutoViewRuleSlot *slots;
};
//- rjf: per-run unwind cache
//- rjf: per-thread unwind cache
typedef struct DF_RunUnwindCacheNode DF_RunUnwindCacheNode;
struct DF_RunUnwindCacheNode
typedef struct DF_UnwindCacheNode DF_UnwindCacheNode;
struct DF_UnwindCacheNode
{
DF_RunUnwindCacheNode *hash_next;
DF_UnwindCacheNode *next;
DF_UnwindCacheNode *prev;
U64 reggen;
U64 memgen;
Arena *arena;
DF_Handle thread;
CTRL_Unwind unwind;
};
typedef struct DF_RunUnwindCacheSlot DF_RunUnwindCacheSlot;
struct DF_RunUnwindCacheSlot
typedef struct DF_UnwindCacheSlot DF_UnwindCacheSlot;
struct DF_UnwindCacheSlot
{
DF_RunUnwindCacheNode *first;
DF_RunUnwindCacheNode *last;
DF_UnwindCacheNode *first;
DF_UnwindCacheNode *last;
};
typedef struct DF_RunUnwindCache DF_RunUnwindCache;
struct DF_RunUnwindCache
typedef struct DF_UnwindCache DF_UnwindCache;
struct DF_UnwindCache
{
Arena *arena;
U64 slots_count;
DF_RunUnwindCacheSlot *slots;
DF_UnwindCacheSlot *slots;
DF_UnwindCacheNode *free_node;
};
//- rjf: per-run tls-base-vaddr cache
@@ -1004,7 +1008,7 @@ typedef struct DF_RunLocalsCacheNode DF_RunLocalsCacheNode;
struct DF_RunLocalsCacheNode
{
DF_RunLocalsCacheNode *hash_next;
DF_Handle binary;
DI_Key dbgi_key;
U64 voff;
EVAL_String2NumMap *locals_map;
};
@@ -1146,10 +1150,7 @@ struct DF_State
DF_AutoViewRuleMapCache auto_view_rule_cache;
// rjf: per-run caches
U64 unwind_cache_reggen_idx;
U64 unwind_cache_memgen_idx;
DF_RunUnwindCache unwind_caches[2];
U64 unwind_cache_gen;
DF_UnwindCache unwind_cache;
U64 tls_base_cache_reggen_idx;
U64 tls_base_cache_memgen_idx;
DF_RunTLSBaseCache tls_base_caches[2];
@@ -1459,6 +1460,7 @@ internal void df_entity_equip_color_rgba(DF_Entity *entity, Vec4F32 rgba);
internal void df_entity_equip_color_hsva(DF_Entity *entity, Vec4F32 hsva);
internal void df_entity_equip_death_timer(DF_Entity *entity, F32 seconds_til_death);
internal void df_entity_equip_cfg_src(DF_Entity *entity, DF_CfgSrc cfg_src);
internal void df_entity_equip_timestamp(DF_Entity *entity, U64 timestamp);
//- rjf: control layer correllation equipment
internal void df_entity_equip_ctrl_machine_id(DF_Entity *entity, CTRL_MachineID machine_id);
@@ -1507,11 +1509,6 @@ internal DF_CmdSpecList df_push_cmd_spec_list(Arena *arena);
internal void df_register_core_view_rule_specs(DF_CoreViewRuleSpecInfoArray specs);
internal DF_CoreViewRuleSpec *df_core_view_rule_spec_from_string(String8 string);
////////////////////////////////
//~ rjf: Debug Info Mapping
internal String8 df_debug_info_path_from_module(Arena *arena, DF_Entity *module);
////////////////////////////////
//~ rjf: Stepping "Trap Net" Builders
@@ -1522,9 +1519,9 @@ internal CTRL_TrapList df_trap_net_from_thread__step_into_line(Arena *arena, DF_
////////////////////////////////
//~ rjf: Modules & Debug Info Mappings
//- rjf: module <=> binary file
internal DF_Entity *df_binary_file_from_module(DF_Entity *module);
internal DF_EntityList df_modules_from_binary_file(Arena *arena, DF_Entity *binary_info);
//- rjf: module <=> debug info keys
internal DI_Key df_dbgi_key_from_module(DF_Entity *module);
internal DF_EntityList df_modules_from_dbgi_key(Arena *arena, DI_Key *dbgi_key);
//- rjf: voff <=> vaddr
internal U64 df_base_vaddr_from_module(DF_Entity *module);
@@ -1536,33 +1533,29 @@ internal Rng1U64 df_vaddr_range_from_voff_range(DF_Entity *module, Rng1U64 voff_
////////////////////////////////
//~ rjf: Debug Info Lookups
//- rjf: binary file -> dbgi parse
internal DBGI_Parse *df_dbgi_parse_from_binary_file(DBGI_Scope *scope, DF_Entity *binary);
//- rjf: voff|vaddr -> symbol lookups
internal String8 df_symbol_name_from_binary_voff(Arena *arena, DF_Entity *binary, U64 voff);
internal String8 df_symbol_name_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff);
internal String8 df_symbol_name_from_process_vaddr(Arena *arena, DF_Entity *process, U64 vaddr);
//- rjf: src -> voff lookups
internal DF_TextLineSrc2DasmInfoListArray df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entity *file, Rng1S64 line_num_range);
//- rjf: voff -> src lookups
internal DF_TextLineDasm2SrcInfo df_text_line_dasm2src_info_from_binary_voff(DF_Entity *binary, U64 voff);
internal DF_TextLineDasm2SrcInfo df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff);
//- rjf: symbol -> voff lookups
internal U64 df_voff_from_binary_symbol_name(DF_Entity *binary, String8 symbol_name);
internal U64 df_type_num_from_binary_name(DF_Entity *binary, String8 name);
internal U64 df_voff_from_dbgi_key_symbol_name(DI_Key *dbgi_key, String8 symbol_name);
internal U64 df_type_num_from_dbgi_key_name(DI_Key *dbgi_key, String8 name);
////////////////////////////////
//~ rjf: Process/Thread Info Lookups
//~ rjf: Process/Thread/Module Info Lookups
//- rjf: thread info extraction helpers
internal DF_Entity *df_module_from_process_vaddr(DF_Entity *process, U64 vaddr);
internal DF_Entity *df_module_from_thread(DF_Entity *thread);
internal U64 df_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64 rip_vaddr);
internal Architecture df_architecture_from_entity(DF_Entity *entity);
internal EVAL_String2NumMap *df_push_locals_map_from_binary_voff(Arena *arena, DBGI_Scope *scope, DF_Entity *binary, U64 voff);
internal EVAL_String2NumMap *df_push_member_map_from_binary_voff(Arena *arena, DBGI_Scope *scope, DF_Entity *binary, U64 voff);
internal EVAL_String2NumMap *df_push_locals_map_from_dbgi_key_voff(Arena *arena, DI_Scope *scope, DI_Key *dbgi_key, U64 voff);
internal EVAL_String2NumMap *df_push_member_map_from_dbgi_key_voff(Arena *arena, DI_Scope *scope, DI_Key *dbgi_key, U64 voff);
internal B32 df_set_thread_rip(DF_Entity *thread, U64 vaddr);
internal DF_Entity *df_module_from_thread_candidates(DF_Entity *thread, DF_EntityList *candidates);
@@ -1587,12 +1580,12 @@ internal CTRL_Event df_ctrl_last_stop_event(void);
//~ rjf: Evaluation
internal B32 df_eval_memory_read(void *u, void *out, U64 addr, U64 size);
internal EVAL_ParseCtx df_eval_parse_ctx_from_process_vaddr(DBGI_Scope *scope, DF_Entity *process, U64 vaddr);
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, EVAL_String2ExprMap *macro_map, String8 string);
internal EVAL_ParseCtx df_eval_parse_ctx_from_process_vaddr(DI_Scope *scope, DF_Entity *process, U64 vaddr);
internal EVAL_ParseCtx df_eval_parse_ctx_from_src_loc(DI_Scope *scope, DF_Entity *file, TxtPt pt);
internal DF_Eval df_eval_from_string(Arena *arena, DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, String8 string);
internal DF_Eval df_value_mode_eval_from_eval(TG_Graph *graph, RDI_Parsed *rdi, DF_CtrlCtx *ctrl_ctx, DF_Eval eval);
internal DF_Eval df_dynamically_typed_eval_from_eval(TG_Graph *graph, RDI_Parsed *rdi, 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, EVAL_String2ExprMap *macro_map, DF_Eval eval, DF_CfgTable *cfg);
internal DF_Eval df_eval_from_eval_cfg_table(Arena *arena, DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_Eval eval, DF_CfgTable *cfg);
////////////////////////////////
//~ rjf: Evaluation Views
@@ -1630,8 +1623,8 @@ internal DF_EvalLinkBaseArray df_eval_link_base_array_from_chunk_list(Arena *are
internal DF_EvalVizBlock *df_eval_viz_block_begin(Arena *arena, DF_EvalVizBlockKind kind, DF_ExpandKey parent_key, DF_ExpandKey key, S32 depth);
internal DF_EvalVizBlock *df_eval_viz_block_split_and_continue(Arena *arena, DF_EvalVizBlockList *list, DF_EvalVizBlock *split_block, U64 split_idx);
internal void df_eval_viz_block_end(DF_EvalVizBlockList *list, DF_EvalVizBlock *block);
internal void df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalView *view, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_ExpandKey parent_key, DF_ExpandKey key, String8 string, DF_Eval eval, TG_Member *opt_member, DF_CfgTable *cfg_table, S32 depth, DF_EvalVizBlockList *list_out);
internal DF_EvalVizBlockList df_eval_viz_block_list_from_eval_view_expr_keys(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_EvalView *eval_view, String8 expr, DF_ExpandKey parent_key, DF_ExpandKey key);
internal void df_append_viz_blocks_for_parent__rec(Arena *arena, DI_Scope *scope, DF_EvalView *view, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_ExpandKey parent_key, DF_ExpandKey key, String8 string, DF_Eval eval, TG_Member *opt_member, DF_CfgTable *cfg_table, S32 depth, DF_EvalVizBlockList *list_out);
internal DF_EvalVizBlockList df_eval_viz_block_list_from_eval_view_expr_keys(Arena *arena, DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_EvalView *eval_view, String8 expr, DF_ExpandKey parent_key, DF_ExpandKey key);
internal void df_eval_viz_block_list_concat__in_place(DF_EvalVizBlockList *dst, DF_EvalVizBlockList *to_push);
//- rjf: viz block list <-> table coordinates
@@ -1684,7 +1677,9 @@ internal String8 df_info_summary_from_string(Architecture arch, String8 string);
//- rjf: entity kind cache
internal DF_EntityList df_query_cached_entity_list_with_kind(DF_EntityKind kind);
internal DF_EntityList df_push_active_binary_list(Arena *arena);
//- rjf: active entity based queries
internal DI_KeyList df_push_active_dbgi_key_list(Arena *arena);
internal DF_EntityList df_push_active_target_list(Arena *arena);
//- rjf: per-run caches
@@ -1692,8 +1687,8 @@ internal CTRL_Unwind df_query_cached_unwind_from_thread(DF_Entity *thread);
internal U64 df_query_cached_rip_from_thread(DF_Entity *thread);
internal U64 df_query_cached_rip_from_thread_unwind(DF_Entity *thread, U64 unwind_count);
internal U64 df_query_cached_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64 rip_vaddr);
internal EVAL_String2NumMap *df_query_cached_locals_map_from_binary_voff(DF_Entity *binary, U64 voff);
internal EVAL_String2NumMap *df_query_cached_member_map_from_binary_voff(DF_Entity *binary, U64 voff);
internal EVAL_String2NumMap *df_query_cached_locals_map_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff);
internal EVAL_String2NumMap *df_query_cached_member_map_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff);
//- rjf: top-level command dispatch
internal void df_push_cmd__root(DF_CmdParams *params, DF_CmdSpec *spec);
+2 -6
View File
@@ -26,14 +26,10 @@ DF_EntityKindTable:
//- rjf: filesystem modeling
{File file 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" FileOutline "File" }
{OverrideFileLink override_file_link 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 "Label" FileOutline "Override File Link" }
{PendingFileChange pending_file_change 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" FileOutline "Pending File Change" }
//- rjf: auto view rules
{AutoViewRule auto_view_rule 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 "Label" Binoculars "Auto View Rule" }
//- rjf: diagnostics log
{DiagLog diag_log 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" FileOutline "Diagnostics Log" }
//- rjf: text attachments
{FlashMarker flash_marker 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Null "Flash Marker" }
@@ -59,8 +55,8 @@ DF_EntityKindTable:
{Process process 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Threads "Process" }
{Thread thread 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Thread "Thread" }
{Module module 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Module "Module" }
{DebugInfoOverride debug_info_override 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 "Label" Null "Debug Info Override" }
{PendingThreadName pending_thread_name 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Threads "Pending Thread Name" }
{DebugInfoPath debug_info_path 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Module "Debug Info Path" }
//- rjf: parser task entities
{ConversionTask conversion_task 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 "Label" Null "Conversion Task" }
@@ -337,7 +333,7 @@ DF_CoreCmdTable:// | | |
{DuplicateEntity 1 Null Nil 0 0 0 0 0 0 Null "duplicate_entity" "Duplicate Entity" "Duplicates an entity." "" }
//- rjf: breakpoints
{TextBreakpoint 1 Null Nil 0 0 0 0 0 0 CircleFilled "text_breakpoint" "Text Breakpoint" "Places or removes a breakpoint on the specified line of source code." "" }
{TextBreakpoint 1 FilePath Nil 0 0 0 0 0 0 CircleFilled "text_breakpoint" "Text Breakpoint" "Places or removes a breakpoint on the specified line of source code." "" }
{AddressBreakpoint 0 VirtualAddr Nil 0 0 0 0 1 1 CircleFilled "address_breakpoint" "Address Breakpoint" "Places or removes a breakpoint on the specified address." "" }
{FunctionBreakpoint 0 String Nil 0 0 0 0 1 1 CircleFilled "function_breakpoint" "Function Breakpoint" "Places or removes a breakpoint on the first address(es) of the specified function." "" }
{ToggleBreakpointAtCursor 0 Null Nil 0 0 0 0 0 0 CircleFilled "toggle_breakpoint_cursor" "Toggle Breakpoint At Cursor" "Places or removes a breakpoint on the line on which the active cursor sits." "" }
+9 -19
View File
@@ -29,16 +29,14 @@ Rng1U64 df_g_cmd_param_slot_range_table[21] =
{OffsetOf(DF_CmdParams, dir2), OffsetOf(DF_CmdParams, dir2) + sizeof(Dir2)},
};
DF_IconKind df_g_entity_kind_icon_kind_table[27] =
DF_IconKind df_g_entity_kind_icon_kind_table[25] =
{
DF_IconKind_Null,
DF_IconKind_Null,
DF_IconKind_Machine,
DF_IconKind_FileOutline,
DF_IconKind_FileOutline,
DF_IconKind_FileOutline,
DF_IconKind_Binoculars,
DF_IconKind_FileOutline,
DF_IconKind_Null,
DF_IconKind_Pin,
DF_IconKind_CircleFilled,
@@ -53,23 +51,21 @@ DF_IconKind_Null,
DF_IconKind_Threads,
DF_IconKind_Thread,
DF_IconKind_Module,
DF_IconKind_Null,
DF_IconKind_Threads,
DF_IconKind_Module,
DF_IconKind_Null,
DF_IconKind_Null,
DF_IconKind_Null,
};
String8 df_g_entity_kind_display_string_table[27] =
String8 df_g_entity_kind_display_string_table[25] =
{
str8_lit_comp("Nil"),
str8_lit_comp("Root"),
str8_lit_comp("Machine"),
str8_lit_comp("File"),
str8_lit_comp("Override File Link"),
str8_lit_comp("Pending File Change"),
str8_lit_comp("Auto View Rule"),
str8_lit_comp("Diagnostics Log"),
str8_lit_comp("Flash Marker"),
str8_lit_comp("Watch Pin"),
str8_lit_comp("Breakpoint"),
@@ -84,14 +80,14 @@ str8_lit_comp("Destination"),
str8_lit_comp("Process"),
str8_lit_comp("Thread"),
str8_lit_comp("Module"),
str8_lit_comp("Debug Info Override"),
str8_lit_comp("Pending Thread Name"),
str8_lit_comp("Debug Info Path"),
str8_lit_comp("Conversion Task"),
str8_lit_comp("Conversion Failure"),
str8_lit_comp("EndedProcess"),
};
String8 df_g_entity_kind_name_label_table[27] =
String8 df_g_entity_kind_name_label_table[25] =
{
str8_lit_comp("Label"),
str8_lit_comp("Label"),
@@ -100,8 +96,6 @@ str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Label"),
str8_lit_comp("Expression"),
str8_lit_comp("Label"),
str8_lit_comp("Expression"),
@@ -122,17 +116,15 @@ str8_lit_comp("Label"),
str8_lit_comp("Label"),
};
DF_EntityKindFlags df_g_entity_kind_flags_table[27] =
DF_EntityKindFlags df_g_entity_kind_flags_table[25] =
{
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(1*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 1*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 1*DF_EntityKindFlag_NameIsCode | 1*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 1*DF_EntityKindFlag_LeafMutationProfileConfig | 1*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 1*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 1*DF_EntityKindFlag_LeafMutationProfileConfig | 1*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 1*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 1*DF_EntityKindFlag_NameIsCode | 1*DF_EntityKindFlag_UserDefinedLifetime),
@@ -146,14 +138,14 @@ DF_EntityKindFlags df_g_entity_kind_flags_table[27] =
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 1*DF_EntityKindFlag_LeafMutationSoftHalt | 1*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 1*DF_EntityKindFlag_TreeMutationSoftHalt | 1*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
(0*DF_EntityKindFlag_LeafMutationUserConfig | 0*DF_EntityKindFlag_LeafMutationProfileConfig | 0*DF_EntityKindFlag_LeafMutationSoftHalt | 0*DF_EntityKindFlag_LeafMutationDebugInfoMap | 0*DF_EntityKindFlag_TreeMutationUserConfig | 0*DF_EntityKindFlag_TreeMutationProfileConfig | 0*DF_EntityKindFlag_TreeMutationSoftHalt | 0*DF_EntityKindFlag_TreeMutationDebugInfoMap | 0*DF_EntityKindFlag_NameIsCode | 0*DF_EntityKindFlag_UserDefinedLifetime),
};
DF_EntityOpFlags df_g_entity_kind_op_flags_table[27] =
DF_EntityOpFlags df_g_entity_kind_op_flags_table[25] =
{
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
@@ -162,8 +154,6 @@ DF_EntityOpFlags df_g_entity_kind_op_flags_table[27] =
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
(1*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (1*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (1*DF_EntityOpFlag_Duplicate),
(1*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (1*DF_EntityOpFlag_Rename) | (1*DF_EntityOpFlag_Enable) | (1*DF_EntityOpFlag_Condition) | (1*DF_EntityOpFlag_Duplicate),
(0*DF_EntityOpFlag_Delete) | (0*DF_EntityOpFlag_Freeze) | (0*DF_EntityOpFlag_Edit) | (0*DF_EntityOpFlag_Rename) | (0*DF_EntityOpFlag_Enable) | (0*DF_EntityOpFlag_Condition) | (0*DF_EntityOpFlag_Duplicate),
@@ -377,7 +367,7 @@ DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[214] =
{ str8_lit_comp("name_entity"), str8_lit_comp("Equips an entity with a name."), str8_lit_comp(""), str8_lit_comp("Name Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("edit_entity"), str8_lit_comp("Opens the editor for an entity."), str8_lit_comp(""), str8_lit_comp("Edit Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("duplicate_entity"), str8_lit_comp("Duplicates an entity."), str8_lit_comp(""), str8_lit_comp("Duplicate Entity"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null},
{ str8_lit_comp("text_breakpoint"), str8_lit_comp("Places or removes a breakpoint on the specified line of source code."), str8_lit_comp(""), str8_lit_comp("Text Breakpoint"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_CircleFilled},
{ str8_lit_comp("text_breakpoint"), str8_lit_comp("Places or removes a breakpoint on the specified line of source code."), str8_lit_comp(""), str8_lit_comp("Text Breakpoint"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_FilePath, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_CircleFilled},
{ str8_lit_comp("address_breakpoint"), str8_lit_comp("Places or removes a breakpoint on the specified address."), str8_lit_comp(""), str8_lit_comp("Address Breakpoint"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_VirtualAddr, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_CircleFilled},
{ str8_lit_comp("function_breakpoint"), str8_lit_comp("Places or removes a breakpoint on the first address(es) of the specified function."), str8_lit_comp(""), str8_lit_comp("Function Breakpoint"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_String, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*1)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_CircleFilled},
{ str8_lit_comp("toggle_breakpoint_cursor"), str8_lit_comp("Places or removes a breakpoint on the line on which the active cursor sits."), str8_lit_comp(""), str8_lit_comp("Toggle Breakpoint At Cursor"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_CircleFilled},
+6 -8
View File
@@ -22,9 +22,7 @@ DF_EntityKind_Root,
DF_EntityKind_Machine,
DF_EntityKind_File,
DF_EntityKind_OverrideFileLink,
DF_EntityKind_PendingFileChange,
DF_EntityKind_AutoViewRule,
DF_EntityKind_DiagLog,
DF_EntityKind_FlashMarker,
DF_EntityKind_WatchPin,
DF_EntityKind_Breakpoint,
@@ -39,8 +37,8 @@ DF_EntityKind_Dest,
DF_EntityKind_Process,
DF_EntityKind_Thread,
DF_EntityKind_Module,
DF_EntityKind_DebugInfoOverride,
DF_EntityKind_PendingThreadName,
DF_EntityKind_DebugInfoPath,
DF_EntityKind_ConversionTask,
DF_EntityKind_ConversionFail,
DF_EntityKind_EndedProcess,
@@ -1535,11 +1533,11 @@ struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] =
};
C_LINKAGE_BEGIN
extern Rng1U64 df_g_cmd_param_slot_range_table[22];
extern DF_IconKind df_g_entity_kind_icon_kind_table[27];
extern String8 df_g_entity_kind_display_string_table[27];
extern String8 df_g_entity_kind_name_label_table[27];
extern DF_EntityKindFlags df_g_entity_kind_flags_table[27];
extern DF_EntityOpFlags df_g_entity_kind_op_flags_table[27];
extern DF_IconKind df_g_entity_kind_icon_kind_table[25];
extern String8 df_g_entity_kind_display_string_table[25];
extern String8 df_g_entity_kind_name_label_table[25];
extern DF_EntityKindFlags df_g_entity_kind_flags_table[25];
extern DF_EntityOpFlags df_g_entity_kind_op_flags_table[25];
extern String8 df_g_cfg_src_string_table[4];
extern DF_CoreCmdKind df_g_cfg_src_load_cmd_kind_table[4];
extern DF_CoreCmdKind df_g_cfg_src_write_cmd_kind_table[4];
+115 -97
View File
@@ -583,17 +583,18 @@ df_queue_drag_drop(void)
}
internal void
df_set_hovered_line_info(DF_Entity *binary, U64 voff)
df_set_hovered_line_info(DI_Key *dbgi_key, U64 voff)
{
df_gfx_state->hover_line_binary = df_handle_from_entity(binary);
arena_clear(df_gfx_state->hover_line_arena);
df_gfx_state->hover_line_dbgi_key = di_key_copy(df_gfx_state->hover_line_arena, dbgi_key);
df_gfx_state->hover_line_voff = voff;
df_gfx_state->hover_line_set_this_frame = 1;
}
internal DF_Entity *
df_get_hovered_line_info_binary(void)
internal DI_Key
df_get_hovered_line_info_dbgi_key(void)
{
return df_entity_from_handle(df_gfx_state->hover_line_binary);
return df_gfx_state->hover_line_dbgi_key;
}
internal U64
@@ -1038,7 +1039,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
//////////////////////////////
//- rjf: unpack context
//
B32 window_is_focused = os_window_is_focused(ws->os);
B32 window_is_focused = os_window_is_focused(ws->os) || ws->window_temporarily_focused_ipc;
B32 confirm_open = df_gfx_state->confirm_active;
B32 query_is_open = !df_view_is_nil(ws->query_view_stack_top);
B32 hover_eval_is_open = (!confirm_open &&
@@ -1049,6 +1050,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
{
ws->menu_bar_key_held = 0;
}
ws->window_temporarily_focused_ipc = 0;
ui_select_state(ws->ui);
//////////////////////////////
@@ -2488,7 +2490,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
//- rjf: thread finding
case DF_CoreCmdKind_FindThread:
{
DBGI_Scope *scope = dbgi_scope_open();
DI_Scope *scope = di_scope_open();
DF_Entity *thread = df_entity_from_handle(params.entity);
U64 unwind_count = params.index;
if(thread->kind == DF_EntityKind_Thread)
@@ -2499,19 +2501,19 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
// rjf: extract thread/rip info
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
DF_Entity *binary = df_binary_file_from_module(module);
DI_Key dbgi_key = df_dbgi_key_from_module(module);
RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0);
U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr);
DBGI_Parse *dbgi = df_dbgi_parse_from_binary_file(scope, binary);
DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_binary_voff(binary, rip_voff);
DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff);
// rjf: snap to resolved line
B32 missing_rip = (rip_vaddr == 0);
B32 binary_missing = (binary->flags & DF_EntityFlag_IsMissing);
B32 dbg_info_pending = !binary_missing && dbgi == &dbgi_parse_nil;
B32 dbgi_missing = (dbgi_key.min_timestamp == 0 || dbgi_key.path.size == 0);
B32 dbgi_pending = !dbgi_missing && rdi == &di_rdi_parsed_nil;
B32 has_line_info = (line_info.voff_range.max != line_info.voff_range.min);
B32 has_module = !df_entity_is_nil(module);
B32 has_dbg_info = has_module && !binary_missing;
if(!dbg_info_pending && (has_line_info || has_module))
B32 has_dbg_info = has_module && !dbgi_missing;
if(!dbgi_pending && (has_line_info || has_module))
{
DF_CmdParams params = df_cmd_params_from_window(ws);
if(has_line_info)
@@ -2527,17 +2529,33 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
params.index = unwind_count;
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_Entity);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_VirtualOff);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_VirtualAddr);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_Index);
df_cmd_list_push(arena, cmds, &params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation));
}
// rjf: snap to resolved address w/o line info
if(!missing_rip && !dbgi_pending && !has_line_info && !has_module)
{
DF_CmdParams params = df_cmd_params_from_window(ws);
params.entity = df_handle_from_entity(thread);
params.voff = rip_voff;
params.vaddr = rip_vaddr;
params.index = unwind_count;
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_Entity);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_VirtualOff);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_VirtualAddr);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_Index);
df_cmd_list_push(arena, cmds, &params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation));
}
// rjf: retry on stopped, pending debug info
if(!df_ctrl_targets_running() && (dbg_info_pending || missing_rip))
if(!df_ctrl_targets_running() && (dbgi_pending || missing_rip))
{
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindThread));
}
}
dbgi_scope_close(scope);
di_scope_close(scope);
}break;
case DF_CoreCmdKind_FindSelectedThread:
{
@@ -2561,17 +2579,17 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
// rjf: try to resolve name as a symbol
U64 voff = 0;
DF_Entity *voff_binary = &df_g_nil_entity;
DI_Key voff_dbgi_key = {0};
if(name_resolved == 0)
{
DF_EntityList binaries = df_push_active_binary_list(scratch.arena);
for(DF_EntityNode *n = binaries.first; n != 0; n = n->next)
DI_KeyList keys = df_push_active_dbgi_key_list(scratch.arena);
for(DI_KeyNode *n = keys.first; n != 0; n = n->next)
{
U64 binary_voff = df_voff_from_binary_symbol_name(n->entity, name);
U64 binary_voff = df_voff_from_dbgi_key_symbol_name(&n->v, name);
if(binary_voff != 0)
{
voff = binary_voff;
voff_binary = n->entity;
voff_dbgi_key = n->v;
name_resolved = 1;
break;
}
@@ -2680,19 +2698,25 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
// rjf: name resolved to voff * dbg info
if(name_resolved != 0 && voff != 0)
{
DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_binary_voff(voff_binary, voff);
DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&voff_dbgi_key, voff);
DF_CmdParams p = params;
{
p.file_path = df_full_path_from_entity(scratch.arena, dasm2src_info.file);
p.text_point = dasm2src_info.pt;
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_FilePath);
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_TextPoint);
if(!df_entity_is_nil(voff_binary))
if(voff_dbgi_key.path.size != 0)
{
p.entity = df_handle_from_entity(voff_binary);
p.voff = dasm2src_info.voff_range.min;
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity);
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_VirtualOff);
DF_EntityList modules = df_modules_from_dbgi_key(scratch.arena, &voff_dbgi_key);
DF_Entity *module = df_first_entity_from_list(&modules);
DF_Entity *process = df_entity_ancestor_from_kind(module, DF_EntityKind_Process);
if(!df_entity_is_nil(process))
{
p.entity = df_handle_from_entity(process);
p.vaddr = module->vaddr_rng.min + dasm2src_info.voff_range.min;
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity);
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_VirtualAddr);
}
}
}
df_cmd_list_push(arena, cmds, &p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation));
@@ -2911,7 +2935,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
{
for(DF_TextLineSrc2DasmInfoNode *n = src2dasm.v[src2dasm_idx].first; n != 0; n = n->next)
{
DF_EntityList modules = df_modules_from_binary_file(scratch.arena, n->v.binary);
DF_EntityList modules = df_modules_from_dbgi_key(scratch.arena, &n->v.dbgi_key);
DF_Entity *module = df_module_from_thread_candidates(thread, &modules);
vaddr = df_vaddr_from_voff(module, n->v.voff_range.min);
goto end_lookup;
@@ -3299,7 +3323,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
//
Rng2F32 window_rect = os_client_rect_from_window(ws->os);
Vec2F32 window_rect_dim = dim_2f32(window_rect);
Rng2F32 top_bar_rect = r2f32p(window_rect.x0, window_rect.y0, window_rect.x0+window_rect_dim.x, window_rect.y0+ui_top_pref_height().value);
Rng2F32 top_bar_rect = r2f32p(window_rect.x0, window_rect.y0, window_rect.x0+window_rect_dim.x+1, window_rect.y0+ui_top_pref_height().value);
Rng2F32 bottom_bar_rect = r2f32p(window_rect.x0, window_rect_dim.y - ui_top_pref_height().value, window_rect.x0+window_rect_dim.x, window_rect.y0+window_rect_dim.y);
Rng2F32 content_rect = r2f32p(window_rect.x0, top_bar_rect.y1, window_rect.x0+window_rect_dim.x, bottom_bar_rect.y0);
F32 window_edge_px = os_dpi_from_window(ws->os)*0.035f;
@@ -3411,26 +3435,10 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
case DF_EntityKind_Module:
{
DF_Entity *bin_file = df_binary_file_from_module(entity);
if(ui_clicked(df_icon_buttonf(DF_IconKind_Module, 0, "Inspect Binary File Memory")))
{
DF_CmdParams params = df_cmd_params_from_panel(ws, panel);
params.entity = df_handle_from_entity(bin_file);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_Entity);
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_PendingEntity));
ui_ctx_menu_close();
}
if(ui_clicked(df_icon_buttonf(DF_IconKind_Module, 0, "View Binary File Disassembly")))
{
DF_CmdParams params = df_cmd_params_from_panel(ws, panel);
params.entity = df_handle_from_entity(bin_file);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_Entity);
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_PendingEntity));
ui_ctx_menu_close();
}
}break;
case DF_EntityKind_Process:
{
#if 0
if(ui_clicked(df_icon_buttonf(DF_IconKind_FileOutline, 0, "Open Process Log")))
{
DF_Entity *log = df_log_from_entity(entity);
@@ -3440,9 +3448,11 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Code));
ui_ctx_menu_close();
}
#endif
}break;
case DF_EntityKind_Thread:
{
#if 0
if(ui_clicked(df_icon_buttonf(DF_IconKind_FileOutline, 0, "Open Thread Log")))
{
DF_Entity *log = df_log_from_entity(entity);
@@ -3452,6 +3462,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Code));
ui_ctx_menu_close();
}
#endif
}break;
}
}
@@ -3924,13 +3935,13 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
DF_Entity *process = df_entity_ancestor_from_kind(entity, DF_EntityKind_Process);
CTRL_Unwind unwind = df_query_cached_unwind_from_thread(entity);
String8List lines = {0};
for(CTRL_UnwindFrame *frame = unwind.first; frame != 0; frame = frame->next)
for(U64 frame_idx = 0; frame_idx < unwind.frames.count; frame_idx += 1)
{
U64 rip_vaddr = frame->rip;
U64 rip_vaddr = regs_rip_from_arch_block(entity->arch, unwind.frames.v[frame_idx].regs);
DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
DF_Entity *binary = df_binary_file_from_module(module);
DI_Key dbgi_key = df_dbgi_key_from_module(module);
U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr);
String8 symbol = df_symbol_name_from_binary_voff(scratch.arena, binary, rip_voff);
String8 symbol = df_symbol_name_from_dbgi_key_voff(scratch.arena, &dbgi_key, rip_voff);
if(symbol.size != 0)
{
str8_list_pushf(scratch.arena, &lines, "0x%I64x: %S", rip_vaddr, symbol);
@@ -4255,7 +4266,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
DF_Entity *module = df_module_from_process_vaddr(process, thread_rip_vaddr);
U64 thread_rip_voff = df_voff_from_vaddr(module, thread_rip_vaddr);
DF_Entity *binary = df_binary_file_from_module(module);
DI_Key dbgi_key = df_dbgi_key_from_module(module);
//- rjf: gather lister items
DF_AutoCompListerItemChunkList item_list = {0};
@@ -4263,7 +4274,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
//- rjf: gather locals
if(ws->autocomp_lister_params.flags & DF_AutoCompListerFlag_Locals)
{
EVAL_String2NumMap *locals_map = df_query_cached_locals_map_from_binary_voff(binary, thread_rip_voff);
EVAL_String2NumMap *locals_map = df_query_cached_locals_map_from_dbgi_key_voff(&dbgi_key, thread_rip_voff);
for(EVAL_String2NumMapNode *n = locals_map->first; n != 0; n = n->order_next)
{
DF_AutoCompListerItem item = {0};
@@ -5306,7 +5317,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
}
os_window_push_custom_title_bar_client_area(ws->os, min_sig.box->rect);
os_window_push_custom_title_bar_client_area(ws->os, max_sig.box->rect);
os_window_push_custom_title_bar_client_area(ws->os, cls_sig.box->rect);
os_window_push_custom_title_bar_client_area(ws->os, pad_2f32(cls_sig.box->rect, 2.f));
}
}
}
@@ -5716,7 +5727,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
UI_FontSize(df_font_size_from_slot(ws, DF_FontSlot_Main))
{
Temp scratch = scratch_begin(&arena, 1);
DBGI_Scope *scope = dbgi_scope_open();
DI_Scope *scope = di_scope_open();
DF_CtrlCtx ctrl_ctx = ws->hover_eval_ctrl_ctx;
DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread);
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
@@ -5983,7 +5994,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds)
}
}
dbgi_scope_close(scope);
di_scope_close(scope);
scratch_end(scratch);
}
}
@@ -8311,7 +8322,7 @@ df_single_line_eval_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags
}
internal DF_EvalVizWindowedRowList
df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_EvalView *eval_view, U32 default_radix, F_Tag font, F32 font_size, Rng1S64 visible_range, DF_EvalVizBlockList *blocks)
df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_EvalView *eval_view, U32 default_radix, F_Tag font, F32 font_size, Rng1S64 visible_range, DF_EvalVizBlockList *blocks)
{
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
@@ -8697,12 +8708,12 @@ df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DBGI_Scope *scop
for(U64 idx = visible_idx_range.min; idx < visible_idx_range.max; idx += 1)
{
// rjf: unpack info about this row
String8 name = dbgi_fuzzy_item_string_from_rdi_target_element_idx(parse_ctx->rdi, block->dbgi_target, block->backing_search_items.v[idx].idx);
String8 name = fzy_item_string_from_rdi_target_element_idx(parse_ctx->rdi, block->fzy_target, block->fzy_backing_items.v[idx].idx);
// rjf: get keys for this row
DF_ExpandKey parent_key = block->parent_key;
DF_ExpandKey key = block->key;
key.child_num = block->backing_search_items.v[idx].idx;
key.child_num = block->fzy_backing_items.v[idx].idx;
// rjf: get eval for this row
DF_Eval eval = df_eval_from_string(arena, scope, ctrl_ctx, parse_ctx, macro_map, name);
@@ -9547,6 +9558,13 @@ df_stop_explanation_string_icon_from_ctrl_event(Arena *arena, CTRL_Event *event,
Temp scratch = scratch_begin(&arena, 1);
DF_Entity *thread = df_entity_from_ctrl_handle(event->machine_id, event->entity);
String8 thread_display_string = df_display_string_from_entity(scratch.arena, thread);
String8 process_thread_string = thread_display_string;
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
if(process->kind == DF_EntityKind_Process)
{
String8 process_display_string = df_display_string_from_entity(scratch.arena, process);
process_thread_string = push_str8f(scratch.arena, "%S: %S", process_display_string, thread_display_string);
}
switch(event->kind)
{
default:
@@ -9558,7 +9576,7 @@ df_stop_explanation_string_icon_from_ctrl_event(Arena *arena, CTRL_Event *event,
{
if(!df_entity_is_nil(thread))
{
explanation = push_str8f(arena, "%S completed step", thread_display_string);
explanation = push_str8f(arena, "%S completed step", process_thread_string);
}
else
{
@@ -9570,7 +9588,7 @@ df_stop_explanation_string_icon_from_ctrl_event(Arena *arena, CTRL_Event *event,
if(!df_entity_is_nil(thread))
{
icon = DF_IconKind_CircleFilled;
explanation = push_str8f(arena, "%S hit a breakpoint", thread_display_string);
explanation = push_str8f(arena, "%S hit a breakpoint", process_thread_string);
}
}break;
case CTRL_EventCause_InterruptedByException:
@@ -9583,30 +9601,30 @@ df_stop_explanation_string_icon_from_ctrl_event(Arena *arena, CTRL_Event *event,
default:
{
String8 exception_code_string = df_string_from_exception_code(event->exception_code);
explanation = push_str8f(arena, "Exception thrown by %S - 0x%x%s%S", thread_display_string, event->exception_code, exception_code_string.size > 0 ? ": " : "", exception_code_string);
explanation = push_str8f(arena, "Exception thrown by %S - 0x%x%s%S", process_thread_string, event->exception_code, exception_code_string.size > 0 ? ": " : "", exception_code_string);
}break;
case CTRL_ExceptionKind_CppThrow:
{
explanation = push_str8f(arena, "Exception thrown by %S - 0x%x: C++ exception", thread_display_string, event->exception_code);
explanation = push_str8f(arena, "Exception thrown by %S - 0x%x: C++ exception", process_thread_string, event->exception_code);
}break;
case CTRL_ExceptionKind_MemoryRead:
{
explanation = push_str8f(arena, "Exception thrown by %S - 0x%x: Access violation reading 0x%I64x",
thread_display_string,
process_thread_string,
event->exception_code,
event->vaddr_rng.min);
}break;
case CTRL_ExceptionKind_MemoryWrite:
{
explanation = push_str8f(arena, "Exception thrown by %S - 0x%x: Access violation writing 0x%I64x",
thread_display_string,
process_thread_string,
event->exception_code,
event->vaddr_rng.min);
}break;
case CTRL_ExceptionKind_MemoryExecute:
{
explanation = push_str8f(arena, "Exception thrown by %S - 0x%x: Access violation executing 0x%I64x",
thread_display_string,
process_thread_string,
event->exception_code,
event->vaddr_rng.min);
}break;
@@ -9621,7 +9639,7 @@ df_stop_explanation_string_icon_from_ctrl_event(Arena *arena, CTRL_Event *event,
case CTRL_EventCause_InterruptedByTrap:
{
icon = DF_IconKind_WarningBig;
explanation = push_str8f(arena, "%S interrupted by trap - 0x%x", thread_display_string, event->exception_code);
explanation = push_str8f(arena, "%S interrupted by trap - 0x%x", process_thread_string, event->exception_code);
}break;
case CTRL_EventCause_InterruptedByHalt:
{
@@ -9938,13 +9956,13 @@ df_entity_tooltips(DF_Entity *entity)
ui_spacer(ui_em(1.5f, 1.f));
DF_Entity *process = df_entity_ancestor_from_kind(entity, DF_EntityKind_Process);
CTRL_Unwind unwind = df_query_cached_unwind_from_thread(entity);
for(CTRL_UnwindFrame *frame = unwind.first; frame != 0; frame = frame->next)
for(U64 idx = 0; idx < unwind.frames.count; idx += 1)
{
U64 rip_vaddr = frame->rip;
U64 rip_vaddr = regs_rip_from_arch_block(entity->arch, unwind.frames.v[idx].regs);
DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
DF_Entity *binary = df_binary_file_from_module(module);
DI_Key dbgi_key = df_dbgi_key_from_module(module);
U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr);
String8 symbol = df_symbol_name_from_binary_voff(scratch.arena, binary, rip_voff);
String8 symbol = df_symbol_name_from_dbgi_key_voff(scratch.arena, &dbgi_key, rip_voff);
UI_PrefWidth(ui_children_sum(1)) UI_Row
{
UI_Font(df_font_from_slot(DF_FontSlot_Code)) UI_PrefWidth(ui_em(18.f, 1.f)) UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText)) ui_labelf("0x%I64x", rip_vaddr);
@@ -10059,13 +10077,12 @@ df_entity_desc_button(DF_Window *ws, DF_Entity *entity, FuzzyMatchRangeList *nam
ui_set_next_background_color(bg_color);
}
ui_set_next_hover_cursor(OS_Cursor_HandPoint);
UI_Key key = ui_key_from_stringf(ui_top_parent()->key, "entity_ref_button_%p", entity);
UI_Box *box = ui_build_box_from_key(UI_BoxFlag_Clickable|
UI_BoxFlag_DrawBorder|
UI_BoxFlag_DrawBackground|
UI_BoxFlag_DrawHotEffects|
UI_BoxFlag_DrawActiveEffects,
key);
UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable|
UI_BoxFlag_DrawBorder|
UI_BoxFlag_DrawBackground|
UI_BoxFlag_DrawHotEffects|
UI_BoxFlag_DrawActiveEffects,
"entity_ref_button_%p", entity);
//- rjf: build contents
UI_Parent(box) UI_PrefWidth(ui_text_dim(10, 0))
@@ -10133,13 +10150,14 @@ df_entity_desc_button(DF_Window *ws, DF_Entity *entity, FuzzyMatchRangeList *nam
U64 idx = 0;
U64 limit = 3;
ui_spacer(ui_em(1.f, 1.f));
for(CTRL_UnwindFrame *f = unwind.last; f != 0 && idx < limit; f = f->prev)
for(U64 num = unwind.frames.count; num > 0; num -= 1)
{
U64 rip_vaddr = f->rip;
CTRL_UnwindFrame *f = &unwind.frames.v[num-1];
U64 rip_vaddr = regs_rip_from_arch_block(entity->arch, f->regs);
DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr);
DF_Entity *binary = df_binary_file_from_module(module);
String8 procedure_name = df_symbol_name_from_binary_voff(scratch.arena, binary, rip_voff);
DI_Key dbgi_key = df_dbgi_key_from_module(module);
String8 procedure_name = df_symbol_name_from_dbgi_key_voff(scratch.arena, &dbgi_key, rip_voff);
if(procedure_name.size != 0)
{
FuzzyMatchRangeList fuzzy_matches = {0};
@@ -10582,7 +10600,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
U64 thread_rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_count);
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
DF_Entity *module = df_module_from_process_vaddr(process, thread_rip_vaddr);
DF_Entity *binary = df_binary_file_from_module(module);
DI_Key dbgi_key = df_dbgi_key_from_module(module);
U64 thread_rip_voff = df_voff_from_vaddr(module, thread_rip_vaddr);
// rjf: thread info => color
@@ -10649,7 +10667,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
n != 0;
n = n->next)
{
if(n->v.binary == binary)
if(di_key_match(&n->v.dbgi_key, &dbgi_key))
{
line_info = &n->v;
break;
@@ -10964,7 +10982,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
//
UI_Focus(UI_FocusKind_Off)
{
DBGI_Scope *scope = dbgi_scope_open();
DI_Scope *scope = di_scope_open();
U64 line_idx = 0;
for(S64 line_num = params->line_num_range.min;
line_num < params->line_num_range.max;
@@ -11029,7 +11047,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
}
}
}
dbgi_scope_close(scope);
di_scope_close(scope);
}
//////////////////////////////
@@ -11257,11 +11275,11 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
if(params->line_src2dasm[line_slice_idx].first != 0 &&
params->line_src2dasm[line_slice_idx].first->v.remap_line == mouse_pt.line)
{
df_set_hovered_line_info(params->line_src2dasm[line_slice_idx].first->v.binary, params->line_src2dasm[line_slice_idx].first->v.voff_range.min);
df_set_hovered_line_info(&params->line_src2dasm[line_slice_idx].first->v.dbgi_key, params->line_src2dasm[line_slice_idx].first->v.voff_range.min);
}
if(params->line_dasm2src[line_slice_idx].first != 0)
{
df_set_hovered_line_info(params->line_dasm2src[line_slice_idx].first->v.binary, params->line_dasm2src[line_slice_idx].first->v.voff_range.min);
df_set_hovered_line_info(&params->line_dasm2src[line_slice_idx].first->v.dbgi_key, params->line_dasm2src[line_slice_idx].first->v.voff_range.min);
}
}
@@ -11399,7 +11417,6 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
}
if(dasm2src_info != 0)
{
DF_Entity *binary = dasm2src_info->binary;
has_line_info = 1;
line_info_line_num = dasm2src_info->pt.line;
line_info_t = selected_thread_module->alive_t;
@@ -11426,7 +11443,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
//
UI_Parent(text_container_box) ProfScope("build line text") UI_Focus(UI_FocusKind_Off)
{
DF_Entity *hovered_line_binary = df_get_hovered_line_info_binary();
DI_Key hovered_line_dbgi_key = df_get_hovered_line_info_dbgi_key();
U64 hovered_line_voff = df_get_hovered_line_info_voff();
ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f));
UI_WidthFill
@@ -11501,12 +11518,12 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
if(token->kind == TXT_TokenKind_Identifier || token->kind == TXT_TokenKind_Keyword)
{
B32 mapped_special = 0;
for(DF_EntityNode *n = params->relevant_binaries.first; n != 0; n = n->next)
for(DI_KeyNode *n = params->relevant_dbgi_keys.first; n != 0; n = n->next)
{
DF_Entity *binary = n->entity;
DI_Key dbgi_key = n->v;
if(!mapped_special && token->kind == TXT_TokenKind_Identifier)
{
U64 voff = df_voff_from_binary_symbol_name(binary, token_string);
U64 voff = df_voff_from_dbgi_key_symbol_name(&dbgi_key, token_string);
if(voff != 0)
{
mapped_special = 1;
@@ -11516,7 +11533,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
}
if(!mapped_special && token->kind == TXT_TokenKind_Identifier)
{
U64 type_num = df_type_num_from_binary_name(binary, token_string);
U64 type_num = df_type_num_from_dbgi_key_name(&dbgi_key, token_string);
if(type_num != 0)
{
mapped_special = 1;
@@ -11708,7 +11725,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
for(DF_TextLineSrc2DasmInfoNode *n = src2dasm_list->first; n != 0; n = n->next)
{
if(n->v.remap_line == line_num &&
n->v.binary == hovered_line_binary &&
di_key_match(&n->v.dbgi_key, &hovered_line_dbgi_key) &&
n->v.voff_range.min <= hovered_line_voff && hovered_line_voff < n->v.voff_range.max)
{
matches = 1;
@@ -11721,8 +11738,8 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
// rjf: check dasm2src
if(dasm2src_list->first != 0)
{
DF_Entity *binary = dasm2src_list->first->v.binary;
if(binary == hovered_line_binary)
DI_Key dbgi_key = dasm2src_list->first->v.dbgi_key;
if(di_key_match(&dbgi_key, &dasm2src_list->first->v.dbgi_key))
{
for(DF_TextLineDasm2SrcInfoNode *n = dasm2src_list->first; n != 0; n = n->next)
{
@@ -12820,6 +12837,7 @@ df_gfx_init(OS_WindowRepaintFunctionType *window_repaint_entry_point, DF_StateDe
df_gfx_state->repaint_hook = window_repaint_entry_point;
df_gfx_state->cfg_main_font_path_arena = arena_alloc();
df_gfx_state->cfg_code_font_path_arena = arena_alloc();
df_gfx_state->hover_line_arena = arena_alloc();
df_clear_bindings();
// rjf: register gfx layer views
@@ -13829,7 +13847,7 @@ df_gfx_end_frame(void)
//- rjf: clear hover line info
if(df_gfx_state->hover_line_set_this_frame == 0)
{
df_gfx_state->hover_line_binary = df_handle_zero();
MemoryZeroStruct(&df_gfx_state->hover_line_dbgi_key);
df_gfx_state->hover_line_voff = 0;
}
+9 -7
View File
@@ -300,11 +300,11 @@ enum
#define DF_GFX_VIEW_RULE_LINE_STRINGIZE_FUNCTION_NAME(name) df_gfx_view_rule_line_stringize__##name
#define DF_GFX_VIEW_RULE_LINE_STRINGIZE_FUNCTION_DEF(name) internal DF_GFX_VIEW_RULE_LINE_STRINGIZE_FUNCTION_SIG(DF_GFX_VIEW_RULE_LINE_STRINGIZE_FUNCTION_NAME(name))
#define DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_SIG(name) void name(DF_ExpandKey key, DF_Eval eval, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, struct DF_CfgNode *cfg)
#define DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_SIG(name) void name(DF_ExpandKey key, DF_Eval eval, DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, struct DF_CfgNode *cfg)
#define DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_NAME(name) df_gfx_view_rule_row_ui__##name
#define DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_DEF(name) DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_SIG(DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_NAME(name))
#define DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_SIG(name) void name(struct DF_Window *ws, DF_ExpandKey key, DF_Eval eval, String8 string, DBGI_Scope *dbgi_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, struct DF_CfgNode *cfg, Vec2F32 dim)
#define DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_SIG(name) void name(struct DF_Window *ws, DF_ExpandKey key, DF_Eval eval, String8 string, DI_Scope *di_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, struct DF_CfgNode *cfg, Vec2F32 dim)
#define DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_NAME(name) df_gfx_view_rule_block_ui__##name
#define DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(name) DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_SIG(DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_NAME(name))
@@ -405,7 +405,7 @@ struct DF_CodeSliceParams
DF_EntityList *line_pins;
DF_TextLineDasm2SrcInfoList *line_dasm2src;
DF_TextLineSrc2DasmInfoList *line_src2dasm;
DF_EntityList relevant_binaries;
DI_KeyList relevant_dbgi_keys;
// rjf: visual parameters
F_Tag font;
@@ -513,6 +513,7 @@ struct DF_Window
UI_State *ui;
F32 code_font_size_delta;
F32 main_font_size_delta;
B32 window_temporarily_focused_ipc;
// rjf: view state delta history
DF_StateDeltaHistory *view_state_hist;
@@ -714,7 +715,8 @@ struct DF_GfxState
DF_DragDropState drag_drop_state;
// rjf: hover line info correllation state
DF_Handle hover_line_binary;
Arena *hover_line_arena;
DI_Key hover_line_dbgi_key;
U64 hover_line_voff;
B32 hover_line_set_this_frame;
@@ -871,8 +873,8 @@ internal B32 df_drag_drop(DF_DragDropPayload *out_payload);
internal void df_drag_kill(void);
internal void df_queue_drag_drop(void);
internal void df_set_hovered_line_info(DF_Entity *binary, U64 voff);
internal DF_Entity *df_get_hovered_line_info_binary(void);
internal void df_set_hovered_line_info(DI_Key *dbgi_key, U64 voff);
internal DI_Key df_get_hovered_line_info_dbgi_key(void);
internal U64 df_get_hovered_line_info_voff(void);
////////////////////////////////
@@ -930,7 +932,7 @@ internal void df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdLis
internal String8 df_eval_escaped_from_raw_string(Arena *arena, String8 raw);
internal String8List df_single_line_eval_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags flags, TG_Graph *graph, RDI_Parsed *rdi, DF_CtrlCtx *ctrl_ctx, U32 default_radix, F_Tag font, F32 font_size, F32 max_size, S32 depth, DF_Eval eval, TG_Member *opt_member, DF_CfgTable *cfg_table);
internal DF_EvalVizWindowedRowList df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_EvalView *eval_view, U32 default_radix, F_Tag font, F32 font_size, Rng1S64 visible_range, DF_EvalVizBlockList *blocks);
internal DF_EvalVizWindowedRowList df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_EvalView *eval_view, U32 default_radix, F_Tag font, F32 font_size, Rng1S64 visible_range, DF_EvalVizBlockList *blocks);
////////////////////////////////
//~ rjf: Hover Eval
+17 -18
View File
@@ -23,7 +23,7 @@ DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_DEF(array)
str8_list_push(scratch.arena, &array_size_expr_strs, child->string);
}
String8 array_size_expr = str8_list_join(scratch.arena, &array_size_expr_strs, 0);
DF_Eval array_size_eval = df_eval_from_string(arena, dbgi_scope, ctrl_ctx, parse_ctx, macro_map, array_size_expr);
DF_Eval array_size_eval = df_eval_from_string(arena, di_scope, ctrl_ctx, parse_ctx, macro_map, array_size_expr);
DF_Eval array_size_eval_value = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdi, ctrl_ctx, array_size_eval);
eval_error_list_concat_in_place(&eval.errors, &array_size_eval.errors);
array_size = array_size_eval_value.imm_u64;
@@ -1036,7 +1036,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(rgba)
//~ rjf: "text"
internal DF_TxtTopologyInfo
df_vr_txt_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg)
df_vr_txt_topology_info_from_cfg(DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg)
{
Temp scratch = scratch_begin(0, 0);
DF_TxtTopologyInfo result = zero_struct;
@@ -1094,7 +1094,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text)
//
DF_Entity *thread = df_entity_from_handle(ctrl_ctx->thread);
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
DF_TxtTopologyInfo top = df_vr_txt_topology_info_from_cfg(dbgi_scope, ctrl_ctx, parse_ctx, macro_map, cfg);
DF_TxtTopologyInfo top = df_vr_txt_topology_info_from_cfg(di_scope, ctrl_ctx, parse_ctx, macro_map, cfg);
DF_Eval value_eval = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdi, ctrl_ctx, eval);
U64 base_vaddr = value_eval.imm_u64 ? value_eval.imm_u64 : value_eval.offset;
Rng1U64 vaddr_range = r1u64(base_vaddr, base_vaddr + (top.size_cap ? top.size_cap : 2048));
@@ -1177,7 +1177,7 @@ DF_VIEW_UI_FUNCTION_DEF(text)
//~ rjf: "disasm"
internal DF_DisasmTopologyInfo
df_vr_disasm_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg)
df_vr_disasm_topology_info_from_cfg(DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg)
{
Temp scratch = scratch_begin(0, 0);
DF_DisasmTopologyInfo result = zero_struct;
@@ -1236,7 +1236,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(disasm)
state->last_open_frame_idx = df_frame_index();
{
//- rjf: unpack params
DF_DisasmTopologyInfo top = df_vr_disasm_topology_info_from_cfg(dbgi_scope, ctrl_ctx, parse_ctx, macro_map, cfg);
DF_DisasmTopologyInfo top = df_vr_disasm_topology_info_from_cfg(di_scope, ctrl_ctx, parse_ctx, macro_map, cfg);
//- rjf: resolve to address value & range
DF_Eval value_eval = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdi, ctrl_ctx, eval);
@@ -1259,7 +1259,6 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(disasm)
dasm_params.style_flags = DASM_StyleFlag_Addresses;
dasm_params.syntax = DASM_Syntax_Intel;
dasm_params.base_vaddr = 0;
dasm_params.exe_path = str8_zero();
}
DASM_Info dasm_info = dasm_info_from_key_params(dasm_scope, dasm_key, &dasm_params, &data_hash);
String8 dasm_text_data = {0};
@@ -1388,7 +1387,7 @@ df_bitmap_view_state__canvas_from_screen_rect(DF_BitmapViewState *bvs, Rng2F32 r
}
internal DF_BitmapTopologyInfo
df_vr_bitmap_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg)
df_vr_bitmap_topology_info_from_cfg(DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg)
{
Temp scratch = scratch_begin(0, 0);
DF_BitmapTopologyInfo info = {0};
@@ -1513,7 +1512,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(bitmap)
//
DF_Eval value_eval = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdi, ctrl_ctx, eval);
U64 base_vaddr = value_eval.imm_u64 ? value_eval.imm_u64 : value_eval.offset;
DF_BitmapTopologyInfo topology_info = df_vr_bitmap_topology_info_from_cfg(dbgi_scope, ctrl_ctx, parse_ctx, macro_map, cfg);
DF_BitmapTopologyInfo topology_info = df_vr_bitmap_topology_info_from_cfg(di_scope, ctrl_ctx, parse_ctx, macro_map, cfg);
U64 expected_size = topology_info.width*topology_info.height*r_tex2d_format_bytes_per_pixel_table[topology_info.fmt];
Rng1U64 vaddr_range = r1u64(base_vaddr, base_vaddr+expected_size);
@@ -1568,7 +1567,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(bitmap)
DF_VIEW_SETUP_FUNCTION_DEF(bitmap)
{
DF_BitmapViewState *bvs = df_view_user_state(view, DF_BitmapViewState);
DBGI_Scope *dbgi_scope = dbgi_scope_open();
DI_Scope *di_scope = di_scope_open();
DF_CfgNode *view_center_cfg = df_cfg_node_child_from_string(cfg_root, str8_lit("view_center"), StringMatchFlag_CaseInsensitive);
DF_CfgNode *zoom_cfg = df_cfg_node_child_from_string(cfg_root, str8_lit("zoom"), StringMatchFlag_CaseInsensitive);
DF_CfgNode *bitmap_cfg = df_cfg_node_child_from_string(cfg_root, str8_lit("bitmap"), StringMatchFlag_CaseInsensitive);
@@ -1576,16 +1575,16 @@ DF_VIEW_SETUP_FUNCTION_DEF(bitmap)
DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread);
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
U64 thread_unwind_rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, ctrl_ctx.unwind_count);
EVAL_ParseCtx parse_ctx = df_eval_parse_ctx_from_process_vaddr(dbgi_scope, process, thread_unwind_rip_vaddr);
EVAL_ParseCtx parse_ctx = df_eval_parse_ctx_from_process_vaddr(di_scope, process, thread_unwind_rip_vaddr);
bvs->view_center_pos.x = (F32)f64_from_str8(bitmap_cfg->first->string);
bvs->view_center_pos.y = (F32)f64_from_str8(bitmap_cfg->first->next->string);
bvs->zoom = (F32)f64_from_str8(zoom_cfg->first->string);
bvs->top = df_vr_bitmap_topology_info_from_cfg(dbgi_scope, &ctrl_ctx, &parse_ctx, &eval_string2expr_map_nil, bitmap_cfg);
bvs->top = df_vr_bitmap_topology_info_from_cfg(di_scope, &ctrl_ctx, &parse_ctx, &eval_string2expr_map_nil, bitmap_cfg);
if(bvs->zoom == 0)
{
bvs->zoom = 1.f;
}
dbgi_scope_close(dbgi_scope);
di_scope_close(di_scope);
}
DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(bitmap)
@@ -1636,7 +1635,7 @@ DF_VIEW_UI_FUNCTION_DEF(bitmap)
{
DF_BitmapViewState *bvs = df_view_user_state(view, DF_BitmapViewState);
Temp scratch = scratch_begin(0, 0);
DBGI_Scope *dbgi_scope = dbgi_scope_open();
DI_Scope *di_scope = di_scope_open();
HS_Scope *hs_scope = hs_scope_open();
TEX_Scope *tex_scope = tex_scope_open();
@@ -1647,13 +1646,13 @@ DF_VIEW_UI_FUNCTION_DEF(bitmap)
DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread);
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
U64 thread_unwind_rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, ctrl_ctx.unwind_count);
EVAL_ParseCtx parse_ctx = df_eval_parse_ctx_from_process_vaddr(dbgi_scope, process, thread_unwind_rip_vaddr);
EVAL_ParseCtx parse_ctx = df_eval_parse_ctx_from_process_vaddr(di_scope, process, thread_unwind_rip_vaddr);
//////////////////////////////
//- rjf: evaluate expression
//
String8 expr = str8(view->query_buffer, view->query_string_size);
DF_Eval eval = df_eval_from_string(scratch.arena, dbgi_scope, &ctrl_ctx, &parse_ctx, &eval_string2expr_map_nil, expr);
DF_Eval eval = df_eval_from_string(scratch.arena, di_scope, &ctrl_ctx, &parse_ctx, &eval_string2expr_map_nil, expr);
DF_Eval value_eval = df_value_mode_eval_from_eval(parse_ctx.type_graph, parse_ctx.rdi, &ctrl_ctx, eval);
U64 base_vaddr = value_eval.imm_u64 ? value_eval.imm_u64 : value_eval.offset;
U64 expected_size = bvs->top.width*bvs->top.height*r_tex2d_format_bytes_per_pixel_table[bvs->top.fmt];
@@ -1731,7 +1730,7 @@ DF_VIEW_UI_FUNCTION_DEF(bitmap)
hs_scope_close(hs_scope);
tex_scope_close(tex_scope);
dbgi_scope_close(dbgi_scope);
di_scope_close(di_scope);
scratch_end(scratch);
}
@@ -1739,7 +1738,7 @@ DF_VIEW_UI_FUNCTION_DEF(bitmap)
//~ rjf: "geo"
internal DF_GeoTopologyInfo
df_vr_geo_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg)
df_vr_geo_topology_info_from_cfg(DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg)
{
Temp scratch = scratch_begin(0, 0);
DF_GeoTopologyInfo result = {0};
@@ -1860,7 +1859,7 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(geo)
U64 base_vaddr = value_eval.imm_u64 ? value_eval.imm_u64 : value_eval.offset;
//- rjf: extract extra geo topology info from view rule
DF_GeoTopologyInfo top = df_vr_geo_topology_info_from_cfg(dbgi_scope, ctrl_ctx, parse_ctx, macro_map, cfg);
DF_GeoTopologyInfo top = df_vr_geo_topology_info_from_cfg(di_scope, ctrl_ctx, parse_ctx, macro_map, cfg);
Rng1U64 index_buffer_vaddr_range = r1u64(base_vaddr, base_vaddr+top.index_count*sizeof(U32));
Rng1U64 vertex_buffer_vaddr_range = top.vertices_vaddr_range;
+4 -4
View File
@@ -38,7 +38,7 @@ struct DF_VR_TextState
F32 loaded_t;
};
internal DF_TxtTopologyInfo df_vr_txt_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg);
internal DF_TxtTopologyInfo df_vr_txt_topology_info_from_cfg(DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg);
////////////////////////////////
//~ rjf: "disasm"
@@ -61,7 +61,7 @@ struct DF_VR_DisasmState
F32 loaded_t;
};
internal DF_DisasmTopologyInfo df_vr_disasm_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg);
internal DF_DisasmTopologyInfo df_vr_disasm_topology_info_from_cfg(DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg);
////////////////////////////////
//~ rjf: "bitmap"
@@ -104,7 +104,7 @@ internal Vec2F32 df_bitmap_view_state__screen_from_canvas_pos(DF_BitmapViewState
internal Rng2F32 df_bitmap_view_state__screen_from_canvas_rect(DF_BitmapViewState *bvs, Rng2F32 rect, Rng2F32 cvs);
internal Vec2F32 df_bitmap_view_state__canvas_from_screen_pos(DF_BitmapViewState *bvs, Rng2F32 rect, Vec2F32 scr);
internal Rng2F32 df_bitmap_view_state__canvas_from_screen_rect(DF_BitmapViewState *bvs, Rng2F32 rect, Rng2F32 scr);
internal DF_BitmapTopologyInfo df_vr_bitmap_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg);
internal DF_BitmapTopologyInfo df_vr_bitmap_topology_info_from_cfg(DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg);
////////////////////////////////
//~ rjf: "geo"
@@ -139,6 +139,6 @@ struct DF_VR_GeoBoxDrawData
F32 loaded_t;
};
internal DF_GeoTopologyInfo df_vr_geo_topology_info_from_cfg(DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg);
internal DF_GeoTopologyInfo df_vr_geo_topology_info_from_cfg(DI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_CfgNode *cfg);
#endif // DF_VIEW_RULES_H
+214 -216
View File
@@ -543,7 +543,7 @@ df_watch_view_text_edit_state_from_pt(DF_WatchViewState *wv, DF_WatchViewPoint p
//- rjf: windowed watch tree visualization (both single-line and multi-line)
internal DF_EvalVizBlockList
df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_View *view, DF_WatchViewState *ews)
df_eval_viz_block_list_from_watch_view_state(Arena *arena, DI_Scope *di_scope, FZY_Scope *fzy_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_View *view, DF_WatchViewState *ews)
{
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
@@ -551,7 +551,7 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF
DF_EvalViewKey eval_view_key = df_eval_view_key_from_eval_watch_view(ews);
DF_EvalView *eval_view = df_eval_view_from_key(eval_view_key);
String8 filter = str8(view->query_buffer, view->query_string_size);
DBGI_FuzzySearchTarget dbgi_target = DBGI_FuzzySearchTarget_UDTs;
FZY_Target fzy_target = FZY_Target_UDTs;
switch(ews->fill_kind)
{
////////////////////////////
@@ -568,7 +568,7 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF
{
DF_ExpandKey parent_key = df_parent_expand_key_from_eval_root(root);
DF_ExpandKey key = df_expand_key_from_eval_root(root);
DF_EvalVizBlockList root_blocks = df_eval_viz_block_list_from_eval_view_expr_keys(arena, scope, ctrl_ctx, parse_ctx, macro_map, eval_view, root_expr_string, parent_key, key);
DF_EvalVizBlockList root_blocks = df_eval_viz_block_list_from_eval_view_expr_keys(arena, di_scope, ctrl_ctx, parse_ctx, macro_map, eval_view, root_expr_string, parent_key, key);
df_eval_viz_block_list_concat__in_place(&blocks, &root_blocks);
}
}
@@ -594,7 +594,7 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF
{
DF_ExpandKey parent_key = df_expand_key_make(5381, 0);
DF_ExpandKey key = df_expand_key_make(df_hash_from_expand_key(parent_key), num);
DF_EvalVizBlockList root_blocks = df_eval_viz_block_list_from_eval_view_expr_keys(arena, scope, ctrl_ctx, parse_ctx, macro_map, eval_view, root_expr_string, parent_key, key);
DF_EvalVizBlockList root_blocks = df_eval_viz_block_list_from_eval_view_expr_keys(arena, di_scope, ctrl_ctx, parse_ctx, macro_map, eval_view, root_expr_string, parent_key, key);
df_eval_viz_block_list_concat__in_place(&blocks, &root_blocks);
}
}
@@ -606,7 +606,7 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF
{
DF_ExpandKey parent_key = df_expand_key_make(5381, 0);
DF_ExpandKey key = df_expand_key_make(df_hash_from_expand_key(parent_key), num);
DF_EvalVizBlockList root_blocks = df_eval_viz_block_list_from_eval_view_expr_keys(arena, scope, ctrl_ctx, parse_ctx, macro_map, eval_view, root_expr_string, parent_key, key);
DF_EvalVizBlockList root_blocks = df_eval_viz_block_list_from_eval_view_expr_keys(arena, di_scope, ctrl_ctx, parse_ctx, macro_map, eval_view, root_expr_string, parent_key, key);
df_eval_viz_block_list_concat__in_place(&blocks, &root_blocks);
}
}
@@ -626,7 +626,7 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF
{
DF_ExpandKey parent_key = df_expand_key_make(5381, 0);
DF_ExpandKey key = df_expand_key_make(df_hash_from_expand_key(parent_key), num);
DF_EvalVizBlockList root_blocks = df_eval_viz_block_list_from_eval_view_expr_keys(arena, scope, ctrl_ctx, parse_ctx, macro_map, eval_view, root_expr_string, parent_key, key);
DF_EvalVizBlockList root_blocks = df_eval_viz_block_list_from_eval_view_expr_keys(arena, di_scope, ctrl_ctx, parse_ctx, macro_map, eval_view, root_expr_string, parent_key, key);
df_eval_viz_block_list_concat__in_place(&blocks, &root_blocks);
}
}
@@ -635,10 +635,10 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF
////////////////////////////
//- rjf: debug info table fill -> build split debug info table blocks
//
case DF_WatchViewFillKind_Globals: dbgi_target = DBGI_FuzzySearchTarget_GlobalVariables; goto dbgi_table;
case DF_WatchViewFillKind_ThreadLocals: dbgi_target = DBGI_FuzzySearchTarget_ThreadVariables; goto dbgi_table;
case DF_WatchViewFillKind_Types: dbgi_target = DBGI_FuzzySearchTarget_UDTs; goto dbgi_table;
case DF_WatchViewFillKind_Procedures: dbgi_target = DBGI_FuzzySearchTarget_Procedures; goto dbgi_table;
case DF_WatchViewFillKind_Globals: fzy_target = FZY_Target_GlobalVariables; goto dbgi_table;
case DF_WatchViewFillKind_ThreadLocals: fzy_target = FZY_Target_ThreadVariables; goto dbgi_table;
case DF_WatchViewFillKind_Types: fzy_target = FZY_Target_UDTs; goto dbgi_table;
case DF_WatchViewFillKind_Procedures: fzy_target = FZY_Target_Procedures; goto dbgi_table;
dbgi_table:;
{
//- rjf: unpack context
@@ -646,10 +646,7 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
U64 thread_rip_unwind_vaddr = df_query_cached_rip_from_thread_unwind(thread, ctrl_ctx->unwind_count);
DF_Entity *module = df_module_from_process_vaddr(process, thread_rip_unwind_vaddr);
DF_Entity *binary = df_binary_file_from_module(module);
String8 exe_path = df_full_path_from_entity(scratch.arena, binary);
DBGI_Parse *dbgi = dbgi_parse_from_exe_path(scope, exe_path, os_now_microseconds()+100);
RDI_Parsed *rdi = &dbgi->rdi;
DI_Key dbgi_key = df_dbgi_key_from_module(module);
//- rjf: calculate top-level keys, expand root-level, grab root expansion node
DF_ExpandKey parent_key = df_expand_key_make(5381, 0);
@@ -660,7 +657,12 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF
//- rjf: query all filtered items from dbgi searching system
U128 fuzzy_search_key = {(U64)view, df_hash_from_string(str8_struct(&view))};
B32 items_stale = 0;
DBGI_FuzzySearchItemArray items = dbgi_fuzzy_search_items_from_key_exe_query(scope, fuzzy_search_key, exe_path, filter, dbgi_target, os_now_microseconds()+100, &items_stale);
FZY_Params params = {fzy_target};
{
params.dbgi_keys.count = 1;
params.dbgi_keys.v = &dbgi_key;
}
FZY_ItemArray items = fzy_items_from_key_params_query(fzy_scope, fuzzy_search_key, &params, filter, os_now_microseconds()+100, &items_stale);
if(items_stale)
{
df_gfx_request_frame();
@@ -691,7 +693,7 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF
U64 idx = 0;
for(DF_ExpandNode *child = root_node->first; child != 0; child = child->next)
{
U64 item_num = dbgi_fuzzy_item_num_from_array_element_idx__linear_search(&items, child->key.child_num);
U64 item_num = fzy_item_num_from_array_element_idx__linear_search(&items, child->key.child_num);
if(item_num != 0)
{
sub_expand_keys[idx] = child->key;
@@ -731,8 +733,8 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF
DF_EvalVizBlock *last_vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_DebugInfoTable, parent_key, root_key, 0);
{
last_vb->visual_idx_range = last_vb->semantic_idx_range = r1u64(0, items.count);
last_vb->dbgi_target = dbgi_target;
last_vb->backing_search_items = items;
last_vb->fzy_target = fzy_target;
last_vb->fzy_backing_items = items;
}
for(U64 sub_expand_idx = 0; sub_expand_idx < sub_expand_keys_count; sub_expand_idx += 1)
{
@@ -740,7 +742,7 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF
last_vb = df_eval_viz_block_split_and_continue(arena, &blocks, last_vb, sub_expand_item_idxs[sub_expand_idx]);
// rjf: grab name for the expanded row
String8 name = dbgi_fuzzy_item_string_from_rdi_target_element_idx(&dbgi->rdi, dbgi_target, sub_expand_keys[sub_expand_idx].child_num);
String8 name = fzy_item_string_from_rdi_target_element_idx(parse_ctx->rdi, fzy_target, sub_expand_keys[sub_expand_idx].child_num);
// rjf: recurse for sub-expansion
{
@@ -752,8 +754,8 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF
df_cfg_table_push_unparsed_string(arena, &child_cfg, view_rule_string, DF_CfgSrc_User);
}
}
DF_Eval eval = df_eval_from_string(arena, scope, ctrl_ctx, parse_ctx, macro_map, name);
df_append_viz_blocks_for_parent__rec(arena, scope, eval_view, ctrl_ctx, parse_ctx, macro_map, parent_key, sub_expand_keys[sub_expand_idx], name, eval, 0, &child_cfg, 0, &blocks);
DF_Eval eval = df_eval_from_string(arena, di_scope, ctrl_ctx, parse_ctx, macro_map, name);
df_append_viz_blocks_for_parent__rec(arena, di_scope, eval_view, ctrl_ctx, parse_ctx, macro_map, parent_key, sub_expand_keys[sub_expand_idx], name, eval, 0, &child_cfg, 0, &blocks);
}
}
df_eval_viz_block_end(&blocks, last_vb);
@@ -817,7 +819,8 @@ internal void
df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewState *ewv, B32 modifiable, U32 default_radix, Rng2F32 rect)
{
ProfBeginFunction();
DBGI_Scope *scope = dbgi_scope_open();
DI_Scope *di_scope = di_scope_open();
FZY_Scope *fzy_scope = fzy_scope_open();
Temp scratch = scratch_begin(0, 0);
//////////////////////////////
@@ -837,7 +840,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS
//////////////////////////////
//- rjf: process * thread info -> parse_ctx
//
EVAL_ParseCtx parse_ctx = df_eval_parse_ctx_from_process_vaddr(scope, process, thread_ip_vaddr);
EVAL_ParseCtx parse_ctx = df_eval_parse_ctx_from_process_vaddr(di_scope, process, thread_ip_vaddr);
//////////////////////////////
//- rjf: determine autocompletion string
@@ -888,19 +891,12 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS
CTRL_Unwind unwind = df_query_cached_unwind_from_thread(thread);
Architecture arch = df_architecture_from_entity(thread);
U64 reg_size = regs_block_size_from_architecture(arch);
U64 thread_unwind_ip_vaddr = 0;
void *thread_unwind_regs_block = push_array(scratch.arena, U8, reg_size);
U64 thread_unwind_ip_vaddr = 0;
if(unwind.frames.count != 0)
{
U64 idx = 0;
for(CTRL_UnwindFrame *f = unwind.first; f != 0; f = f->next, idx += 1)
{
if(idx == unwind_count)
{
thread_unwind_ip_vaddr = f->rip;
thread_unwind_regs_block = f->regs;
break;
}
}
thread_unwind_regs_block = unwind.frames.v[unwind_count%unwind.frames.count].regs;
thread_unwind_ip_vaddr = regs_rip_from_arch_block(arch, thread_unwind_regs_block);
}
//- rjf: lex & parse
@@ -919,7 +915,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS
//
if(state_dirty)
{
blocks = df_eval_viz_block_list_from_watch_view_state(scratch.arena, scope, &ctrl_ctx, &parse_ctx, &macro_map, view, ewv);
blocks = df_eval_viz_block_list_from_watch_view_state(scratch.arena, di_scope, fzy_scope, &ctrl_ctx, &parse_ctx, &macro_map, view, ewv);
}
//////////////////////////
@@ -1057,7 +1053,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS
ewv->text_edit_state_slots_count = u64_up_to_pow2(selection_dim.y+1);
ewv->text_edit_state_slots_count = Max(ewv->text_edit_state_slots_count, 64);
ewv->text_edit_state_slots = push_array(ewv->text_edit_arena, DF_WatchViewTextEditState*, ewv->text_edit_state_slots_count);
DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, scope, &ctrl_ctx, &parse_ctx, &macro_map, eval_view, default_radix, code_font, ui_top_font_size(),
DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, di_scope, &ctrl_ctx, &parse_ctx, &macro_map, eval_view, default_radix, code_font, ui_top_font_size(),
r1s64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y-1),
ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y-1)+1), &blocks);
DF_EvalVizRow *row = rows.first;
@@ -1089,7 +1085,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS
if(!ewv->text_editing && evt->slot == UI_EventActionSlot_Accept && selection_tbl.min.x <= 0)
{
taken = 1;
DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, scope, &ctrl_ctx, &parse_ctx, &macro_map, eval_view, default_radix, code_font, ui_top_font_size(),
DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, di_scope, &ctrl_ctx, &parse_ctx, &macro_map, eval_view, default_radix, code_font, ui_top_font_size(),
r1s64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y-1),
ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y-1)+1), &blocks);
DF_EvalVizRow *row = rows.first;
@@ -1100,6 +1096,25 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS
B32 is_expanded = df_expand_key_is_set(&eval_view->expand_tree_table, row->key);
df_expand_set_expansion(eval_view->arena, &eval_view->expand_tree_table, row->parent_key, row->key, !is_expanded);
}
if(row->flags & DF_EvalVizRowFlag_Canvas)
{
DF_CfgNode *cfg = df_cfg_tree_copy(scratch.arena, row->expand_ui_rule_node);
DF_CfgNode *cfg_root = push_array(scratch.arena, DF_CfgNode, 1);
cfg_root->first = cfg_root->last = cfg;
cfg_root->next = cfg_root->parent = &df_g_nil_cfg_node;
if(cfg != &df_g_nil_cfg_node)
{
cfg->parent = cfg_root;
}
DF_CmdParams p = df_cmd_params_from_view(ws, panel, view);
p.string = row->edit_expr;
p.view_spec = df_tab_view_spec_from_gfx_view_rule_spec(row->expand_ui_rule_spec);
p.cfg_node = cfg_root;
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_String);
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_ViewSpec);
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_CfgNode);
df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_OpenTab));
}
}
}
@@ -1188,13 +1203,13 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS
case DF_WatchViewColumnKind_Value:
if(editing_complete && evt->slot != UI_EventActionSlot_Cancel)
{
DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, scope, &ctrl_ctx, &parse_ctx, &macro_map, eval_view, default_radix, code_font, ui_top_font_size(),
DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, di_scope, &ctrl_ctx, &parse_ctx, &macro_map, eval_view, default_radix, code_font, ui_top_font_size(),
r1s64(ui_scroll_list_row_from_item(&row_blocks, y-1),
ui_scroll_list_row_from_item(&row_blocks, y-1)+1), &blocks);
B32 success = 0;
if(rows.first != 0)
{
DF_Eval write_eval = df_eval_from_string(scratch.arena, scope, &ctrl_ctx, &parse_ctx, &macro_map, new_string);
DF_Eval write_eval = df_eval_from_string(scratch.arena, di_scope, &ctrl_ctx, &parse_ctx, &macro_map, new_string);
success = df_commit_eval_value(parse_ctx.type_graph, parse_ctx.rdi, &ctrl_ctx, rows.first->eval, write_eval);
}
if(!success)
@@ -1230,7 +1245,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS
{
taken = 1;
String8List strs = {0};
DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, scope, &ctrl_ctx, &parse_ctx, &macro_map, eval_view, default_radix, code_font, ui_top_font_size(),
DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, di_scope, &ctrl_ctx, &parse_ctx, &macro_map, eval_view, default_radix, code_font, ui_top_font_size(),
r1s64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y-1),
ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y-1)+1), &blocks);
DF_EvalVizRow *row = rows.first;
@@ -1566,7 +1581,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS
//- rjf: viz blocks -> rows
DF_EvalVizWindowedRowList rows = {0};
{
rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, scope, &ctrl_ctx, &parse_ctx, &macro_map, eval_view, default_radix, code_font, ui_top_font_size(), r1s64(visible_row_rng.min-1, visible_row_rng.max), &blocks);
rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, di_scope, &ctrl_ctx, &parse_ctx, &macro_map, eval_view, default_radix, code_font, ui_top_font_size(), r1s64(visible_row_rng.min-1, visible_row_rng.max), &blocks);
}
//- rjf: build table
@@ -1631,7 +1646,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS
{
Vec2F32 canvas_dim = v2f32(scroll_list_params.dim_px.x - ui_top_font_size()*1.5f,
(row->skipped_size_in_rows+row->size_in_rows+row->chopped_size_in_rows)*scroll_list_params.row_height_px);
row->expand_ui_rule_spec->info.block_ui(ws, row->key, row->eval, row->edit_expr, scope, &ctrl_ctx, &parse_ctx, &macro_map, row->expand_ui_rule_node, canvas_dim);
row->expand_ui_rule_spec->info.block_ui(ws, row->key, row->eval, row->edit_expr, di_scope, &ctrl_ctx, &parse_ctx, &macro_map, row->expand_ui_rule_node, canvas_dim);
}
}
}
@@ -1906,7 +1921,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS
UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clip|UI_BoxFlag_Clickable, "###val_%I64x", row_hash);
UI_Parent(box)
{
row->value_ui_rule_spec->info.row_ui(row->key, row->eval, scope, &ctrl_ctx, &parse_ctx, &macro_map, row->value_ui_rule_node);
row->value_ui_rule_spec->info.row_ui(row->key, row->eval, di_scope, &ctrl_ctx, &parse_ctx, &macro_map, row->value_ui_rule_node);
}
sig = ui_signal_from_box(box);
}
@@ -2042,7 +2057,8 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS
}
scratch_end(scratch);
dbgi_scope_close(scope);
fzy_scope_close(fzy_scope);
di_scope_close(di_scope);
ProfEnd();
}
@@ -3235,17 +3251,26 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister)
{
ProfBeginFunction();
Temp scratch = scratch_begin(0, 0);
DBGI_Scope *scope = dbgi_scope_open();
DI_Scope *di_scope = di_scope_open();
FZY_Scope *fzy_scope = fzy_scope_open();
F32 row_height_px = floor_f32(ui_top_font_size()*2.5f);
DF_CtrlCtx ctrl_ctx = df_ctrl_ctx_from_view(ws, view);
DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread);
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
U64 thread_unwind_rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, ctrl_ctx.unwind_count);
DF_Entity *module = df_module_from_process_vaddr(process, thread_unwind_rip_vaddr);
DF_Entity *binary = df_binary_file_from_module(module);
String8 exe_path = df_full_path_from_entity(scratch.arena, binary);
String8 query = str8(view->query_buffer, view->query_string_size);
TG_Graph *graph = tg_graph_begin(bit_size_from_arch(df_architecture_from_entity(thread))/8, 256);
DI_KeyList dbgi_keys_list = df_push_active_dbgi_key_list(scratch.arena);
DI_KeyArray dbgi_keys = di_key_array_from_list(scratch.arena, &dbgi_keys_list);
FZY_Params params = {FZY_Target_Procedures, dbgi_keys};
U64 endt_us = os_now_microseconds()+200;
//- rjf: grab rdis, make type graphs for each
U64 rdis_count = dbgi_keys.count;
RDI_Parsed **rdis = push_array(scratch.arena, RDI_Parsed *, rdis_count);
TG_Graph **graphs = push_array(scratch.arena, TG_Graph *, rdis_count);
{
for(U64 idx = 0; idx < rdis_count; idx += 1)
{
rdis[idx] = di_rdi_from_key(di_scope, &dbgi_keys.v[idx], endt_us);
graphs[idx] = tg_graph_begin(rdi_addr_size_from_arch(rdis[idx]->top_level_info->architecture), 256);
}
}
//- rjf: grab state
typedef struct DF_SymbolListerViewState DF_SymbolListerViewState;
@@ -3257,10 +3282,8 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister)
//- rjf: query -> raddbg, filtered items
U128 fuzzy_search_key = {(U64)view, df_hash_from_string(str8_struct(&view))};
DBGI_Parse *dbgi = dbgi_parse_from_exe_path(scope, exe_path, os_now_microseconds()+100);
RDI_Parsed *rdi = &dbgi->rdi;
B32 items_stale = 0;
DBGI_FuzzySearchItemArray items = dbgi_fuzzy_search_items_from_key_exe_query(scope, fuzzy_search_key, exe_path, query, DBGI_FuzzySearchTarget_Procedures, os_now_microseconds()+100, &items_stale);
FZY_ItemArray items = fzy_items_from_key_params_query(fzy_scope, fuzzy_search_key, &params, query, endt_us, &items_stale);
if(items_stale)
{
df_gfx_request_frame();
@@ -3269,16 +3292,27 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister)
//- rjf: submit best match when hitting enter w/ no selection
if(slv->cursor.y == 0 && items.count != 0 && ui_slot_press(UI_EventActionSlot_Accept))
{
RDI_Procedure *procedure = rdi_element_from_idx(rdi, procedures, items.v[0].idx);
U64 name_size = 0;
U8 *name_base = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size);
String8 name = str8(name_base, name_size);
if(name.size != 0)
FZY_Item *item = &items.v[0];
U64 base_idx = 0;
for(U64 rdi_idx = 0; rdi_idx < rdis_count; rdi_idx += 1)
{
DF_CmdParams p = df_cmd_params_from_view(ws, panel, view);
p.string = name;
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_String);
df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_CompleteQuery));
RDI_Parsed *rdi = rdis[rdi_idx];
if(base_idx <= item->idx && item->idx < base_idx + rdi->procedures_count)
{
RDI_Procedure *procedure = rdi_element_from_idx(rdi, procedures, item->idx-base_idx);
U64 name_size = 0;
U8 *name_base = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size);
String8 name = str8(name_base, name_size);
if(name.size != 0)
{
DF_CmdParams p = df_cmd_params_from_view(ws, panel, view);
p.string = name;
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_String);
df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_CompleteQuery));
}
break;
}
base_idx += rdi->procedures_count;
}
}
@@ -3311,13 +3345,36 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister)
idx += 1)
UI_Focus((slv->cursor.y == idx+1) ? UI_FocusKind_On : UI_FocusKind_Off)
{
DBGI_FuzzySearchItem *item = &items.v[idx];
RDI_Procedure *procedure = rdi_element_from_idx(rdi, procedures, item->idx);
FZY_Item *item = &items.v[idx];
//- rjf: determine dbgi/rdi to which this item belongs
DI_Key dbgi_key = {0};
RDI_Parsed *rdi = &di_rdi_parsed_nil;
TG_Graph *graph = 0;
U64 base_idx = 0;
{
for(U64 rdi_idx = 0; rdi_idx < rdis_count; rdi_idx += 1)
{
if(base_idx <= item->idx && item->idx < base_idx + rdis[rdi_idx]->procedures_count)
{
dbgi_key = dbgi_keys.v[rdi_idx];
rdi = rdis[rdi_idx];
graph = graphs[rdi_idx];
break;
}
base_idx += rdis[rdi_idx]->procedures_count;
}
}
//- rjf: unpack this item's info
RDI_Procedure *procedure = rdi_element_from_idx(rdi, procedures, item->idx-base_idx);
U64 name_size = 0;
U8 *name_base = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size);
String8 name = str8(name_base, name_size);
RDI_TypeNode *type_node = rdi_element_from_idx(rdi, type_nodes, procedure->type_idx);
TG_Key type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), procedure->type_idx);
//- rjf: build item button
ui_set_next_hover_cursor(OS_Cursor_HandPoint);
UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable|
UI_BoxFlag_DrawBackground|
@@ -3330,12 +3387,14 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister)
{
UI_Box *box = df_code_label(1.f, 0, df_rgba_from_theme_color(DF_ThemeColor_CodeFunction), name);
ui_box_equip_fuzzy_match_ranges(box, &item->match_ranges);
if(!tg_key_match(tg_key_zero(), type_key))
if(!tg_key_match(tg_key_zero(), type_key) && graph != 0)
{
String8 type_string = tg_string_from_key(scratch.arena, graph, rdi, type_key);
df_code_label(0.5f, 0, df_rgba_from_theme_color(DF_ThemeColor_WeakText), type_string);
}
}
//- rjf: interact
UI_Signal sig = ui_signal_from_box(box);
if(ui_clicked(sig))
{
@@ -3346,8 +3405,8 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister)
}
if(ui_hovering(sig)) UI_Tooltip
{
U64 binary_voff = df_voff_from_binary_symbol_name(binary, name);
DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_binary_voff(binary, binary_voff);
U64 binary_voff = df_voff_from_dbgi_key_symbol_name(&dbgi_key, name);
DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, binary_voff);
String8 file_path = df_full_path_from_entity(scratch.arena, dasm2src_info.file);
S64 line_num = dasm2src_info.pt.line;
df_code_label(1.f, 0, df_rgba_from_theme_color(DF_ThemeColor_CodeFunction), name);
@@ -3367,7 +3426,8 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister)
}
}
dbgi_scope_close(scope);
fzy_scope_close(fzy_scope);
di_scope_close(di_scope);
scratch_end(scratch);
ProfEnd();
}
@@ -4527,7 +4587,6 @@ DF_VIEW_UI_FUNCTION_DEF(Scheduler)
{
ProfBeginFunction();
Temp scratch = scratch_begin(0, 0);
DBGI_Scope *scope = dbgi_scope_open();
String8 query = str8(view->query_buffer, view->query_string_size);
DF_CtrlCtx ctrl_ctx = df_ctrl_ctx_from_view(ws, view);
@@ -4742,8 +4801,8 @@ DF_VIEW_UI_FUNCTION_DEF(Scheduler)
U64 rip_vaddr = df_query_cached_rip_from_thread(entity);
DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr);
DF_Entity *binary = df_binary_file_from_module(module);
DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_binary_voff(binary, rip_voff);
DI_Key dbgi_key = df_dbgi_key_from_module(module);
DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff);
if(!df_entity_is_nil(line_info.file))
{
UI_PrefWidth(ui_children_sum(0)) df_entity_src_loc_button(ws, line_info.file, line_info.pt);
@@ -4760,7 +4819,6 @@ DF_VIEW_UI_FUNCTION_DEF(Scheduler)
sv->selected_column = cursor.x;
sv->selected_entity = (1 <= cursor.y && cursor.y <= items.count) ? df_handle_from_entity(items.v[cursor.y-1].entity) : df_handle_zero();
dbgi_scope_close(scope);
scratch_end(scratch);
ProfEnd();
}
@@ -4815,8 +4873,8 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack)
scroll_list_params.flags = UI_ScrollListFlag_All;
scroll_list_params.row_height_px = floor_f32(ui_top_font_size()*2.5f);
scroll_list_params.dim_px = dim_2f32(rect);
scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(3, unwind.count));
scroll_list_params.item_range = r1s64(0, unwind.count+1);
scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(3, unwind.frames.count));
scroll_list_params.item_range = r1s64(0, unwind.frames.count+1);
scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1;
}
UI_ScrollListSignal scroll_list_sig = {0};
@@ -4849,20 +4907,20 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack)
}
//- rjf: frame rows
U64 frame_idx = 0;
for(CTRL_UnwindFrame *frame = unwind.first; frame != 0; frame = frame->next, frame_idx += 1)
for(S64 row_num = visible_row_range.min; row_num <= visible_row_range.max && row_num <= unwind.frames.count; row_num += 1)
{
// rjf: out of range -> skip (TODO(rjf): this should be an array...)
if(frame_idx+1 < visible_row_range.min || visible_row_range.max < frame_idx+1)
if(row_num == 0)
{
continue;
}
U64 frame_idx = row_num-1;
CTRL_UnwindFrame *frame = &unwind.frames.v[frame_idx];
// rjf: determine selection
B32 row_selected = cs->cursor.y == ((S64)frame_idx+1);
B32 row_selected = (cs->cursor.y == row_num);
// rjf: regs => rip
U64 rip_vaddr = frame->rip;
U64 rip_vaddr = regs_rip_from_arch_block(thread->arch, frame->regs);
// rjf: rip_vaddr => module
DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
@@ -5036,7 +5094,7 @@ DF_VIEW_CMD_FUNCTION_DEF(Modules)
{
String8 exe_path = module->name;
String8 dbg_path = pick_string;
dbgi_force_exe_path_dbg_path(exe_path, dbg_path);
// TODO(rjf)
}
scratch_end(scratch);
}break;
@@ -5048,7 +5106,7 @@ DF_VIEW_UI_FUNCTION_DEF(Modules)
{
ProfBeginFunction();
Temp scratch = scratch_begin(0, 0);
DBGI_Scope *scope = dbgi_scope_open();
DI_Scope *scope = di_scope_open();
String8 query = str8(view->query_buffer, view->query_string_size);
//- rjf: get state
@@ -5215,16 +5273,17 @@ DF_VIEW_UI_FUNCTION_DEF(Modules)
B32 brw_is_selected = (row_is_selected && cursor.x == 3);
// rjf: unpack module info
DF_Entity *binary = df_binary_file_from_module(entity);
DBGI_Parse *dbgi = df_dbgi_parse_from_binary_file(scope, binary);
B32 dbgi_is_valid = (dbgi->dbg_props.modified != 0);
DI_Key dbgi_key = df_dbgi_key_from_module(entity);
String8 dbgi_path = dbgi_key.path;
RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0);
B32 dbgi_is_valid = (rdi != &di_rdi_parsed_nil);
// rjf: begin editing
if(txt_is_selected && edit_begin)
{
mv->txt_editing = 1;
mv->txt_size = Min(sizeof(mv->txt_buffer), dbgi->dbg_path.size);
MemoryCopy(mv->txt_buffer, dbgi->dbg_path.str, mv->txt_size);
mv->txt_size = Min(sizeof(mv->txt_buffer), dbgi_path.size);
MemoryCopy(mv->txt_buffer, dbgi_path.str, mv->txt_size);
mv->txt_cursor = txt_pt(1, 1+mv->txt_size);
mv->txt_mark = txt_pt(1, 1);
}
@@ -5236,7 +5295,7 @@ DF_VIEW_UI_FUNCTION_DEF(Modules)
UI_WidthFill
{
UI_TextColor(!dbgi_is_valid ? df_rgba_from_theme_color(DF_ThemeColor_FailureBackground) : ui_top_text_color())
sig = df_line_editf(DF_LineEditFlag_NoBackground, 0, 0, &mv->txt_cursor, &mv->txt_mark, mv->txt_buffer, sizeof(mv->txt_buffer), &mv->txt_size, 0, dbgi->dbg_path, "###dbg_path_%p", entity);
sig = df_line_editf(DF_LineEditFlag_NoBackground, 0, 0, &mv->txt_cursor, &mv->txt_mark, mv->txt_buffer, sizeof(mv->txt_buffer), &mv->txt_size, 0, dbgi_path, "###dbg_path_%p", entity);
edit_commit = (edit_commit || ui_committed(sig));
}
@@ -5254,8 +5313,8 @@ DF_VIEW_UI_FUNCTION_DEF(Modules)
{
ui_kill_action();
mv->txt_editing = 1;
mv->txt_size = Min(sizeof(mv->txt_buffer), dbgi->dbg_path.size);
MemoryCopy(mv->txt_buffer, dbgi->dbg_path.str, mv->txt_size);
mv->txt_size = Min(sizeof(mv->txt_buffer), dbgi_path.size);
MemoryCopy(mv->txt_buffer, dbgi_path.str, mv->txt_size);
mv->txt_cursor = txt_pt(1, 1+mv->txt_size);
mv->txt_mark = txt_pt(1, 1);
}
@@ -5294,7 +5353,7 @@ DF_VIEW_UI_FUNCTION_DEF(Modules)
{
String8 exe_path = commit_module->name;
String8 dbg_path = str8(mv->txt_buffer, mv->txt_size);
dbgi_force_exe_path_dbg_path(exe_path, dbg_path);
// TODO(rjf)
}
if(edit_submit)
{
@@ -5312,7 +5371,7 @@ DF_VIEW_UI_FUNCTION_DEF(Modules)
mv->selected_column = cursor.x;
mv->selected_entity = (1 <= cursor.y && cursor.y <= items.count) ? df_handle_from_entity(items.v[cursor.y-1].entity) : df_handle_zero();
dbgi_scope_close(scope);
di_scope_close(scope);
scratch_end(scratch);
ProfEnd();
}
@@ -5356,24 +5415,6 @@ DF_VIEW_CMD_FUNCTION_DEF(PendingEntity)
{
default:break;
// rjf: pick file
case DF_CoreCmdKind_PickFile:
{
DF_Entity *missing_file = df_entity_from_handle(pves->pick_file_override_target);
String8 pick_string = cmd->params.file_path;
if(!df_entity_is_nil(missing_file) && pick_string.size != 0)
{
DF_Entity *replacement = df_entity_from_path(pick_string, DF_EntityFromPathFlag_OpenAsNeeded|DF_EntityFromPathFlag_OpenMissing);
view->entity = df_handle_from_entity(replacement);
DF_CmdParams p = df_cmd_params_from_view(ws, panel, view);
p.entity = df_handle_from_entity(missing_file);
p.file_path = pick_string;
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity);
df_cmd_params_mark_slot(&p, DF_CmdParamSlot_FilePath);
df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SetFileReplacementPath));
}
}break;
// rjf: gather deferred commands to redispatch when entity is ready
case DF_CoreCmdKind_GoToLine:
case DF_CoreCmdKind_GoToAddress:
@@ -5442,52 +5483,8 @@ DF_VIEW_CMD_FUNCTION_DEF(PendingEntity)
DF_VIEW_UI_FUNCTION_DEF(PendingEntity)
{
// rjf: grab state
DF_PendingEntityViewState *pves = df_view_user_state(view, DF_PendingEntityViewState);
DF_Entity *entity = df_entity_from_handle(view->entity);
// rjf: entity is missing -> notify user
if(entity->flags & DF_EntityFlag_IsMissing)
{
UI_WidthFill UI_HeightFill UI_Column UI_Padding(ui_pct(1, 0))
{
Temp scratch = scratch_begin(0, 0);
String8 full_path = df_full_path_from_entity(scratch.arena, entity);
UI_PrefWidth(ui_children_sum(1)) UI_PrefHeight(ui_em(3, 1))
UI_Row UI_Padding(ui_pct(1, 0))
UI_PrefWidth(ui_text_dim(10, 1))
UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_FailureBackground))
{
UI_Font(ui_icon_font()) ui_label(df_g_icon_kind_text_table[DF_IconKind_WarningBig]);
ui_labelf("Could not find \"%S\".", full_path);
}
UI_PrefHeight(ui_em(3, 1))
UI_Row UI_Padding(ui_pct(1, 0))
UI_PrefWidth(ui_text_dim(10, 1))
UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_ActionText))
UI_BackgroundColor(df_rgba_from_theme_color(DF_ThemeColor_ActionBackground))
UI_BorderColor(df_rgba_from_theme_color(DF_ThemeColor_ActionBorder))
UI_CornerRadius(ui_top_font_size()/3)
UI_PrefWidth(ui_text_dim(10, 1))
UI_Focus(UI_FocusKind_On)
if(ui_clicked(ui_buttonf("Find alternative...")))
{
DF_CmdParams params = df_cmd_params_from_view(ws, panel, view);
params.cmd_spec = df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_PickFile);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_CmdSpec);
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_RunCommand));
pves->pick_file_override_target = df_handle_from_entity(entity);
}
scratch_end(scratch);
}
}
// rjf: entity is still loading -> loading animation
else
{
view->loading_t = view->loading_t_target = 1.f;
df_gfx_request_frame();
}
view->loading_t = view->loading_t_target = 1.f;
df_gfx_request_frame();
}
////////////////////////////////
@@ -5608,8 +5605,8 @@ DF_VIEW_CMD_FUNCTION_DEF(Code)
if(src2dasm_list->first != 0)
{
Rng1U64 voff_rng = src2dasm_list->first->v.voff_range;
DF_Entity *binary = src2dasm_list->first->v.binary;
DF_EntityList possible_modules = df_modules_from_binary_file(scratch.arena, binary);
DI_Key dbgi_key = src2dasm_list->first->v.dbgi_key;
DF_EntityList possible_modules = df_modules_from_dbgi_key(scratch.arena, &dbgi_key);
DF_Entity *thread_dst_module = df_module_from_thread_candidates(thread, &possible_modules);
U64 thread_dst_voff = voff_rng.min;
if(!df_entity_is_nil(thread_dst_module) && thread_dst_voff != 0)
@@ -5734,7 +5731,7 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
ProfBeginFunction();
Temp scratch = scratch_begin(0, 0);
HS_Scope *hs_scope = hs_scope_open();
DBGI_Scope *dbgi_scope = dbgi_scope_open();
DI_Scope *di_scope = di_scope_open();
TXT_Scope *txt_scope = txt_scope_open();
DF_CodeViewState *tv = df_view_user_state(view, DF_CodeViewState);
@@ -5761,7 +5758,7 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
U64 unwind_count = ctrl_ctx.unwind_count;
U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_count);
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
EVAL_ParseCtx parse_ctx = df_eval_parse_ctx_from_process_vaddr(dbgi_scope, process, rip_vaddr);
EVAL_ParseCtx parse_ctx = df_eval_parse_ctx_from_process_vaddr(di_scope, process, rip_vaddr);
//////////////////////////////
//- rjf: unpack file/text entity info
@@ -5911,8 +5908,8 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
U64 last_inst_on_unwound_rip_vaddr = rip_vaddr - !!unwind_count;
DF_Entity *module = df_module_from_process_vaddr(process, last_inst_on_unwound_rip_vaddr);
U64 rip_voff = df_voff_from_vaddr(module, last_inst_on_unwound_rip_vaddr);
DF_Entity *binary = df_binary_file_from_module(module);
DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_binary_voff(binary, rip_voff);
DI_Key dbgi_key = df_dbgi_key_from_module(module);
DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff);
if(dasm2src_info.file == entity && visible_line_num_range.min <= dasm2src_info.pt.line && dasm2src_info.pt.line <= visible_line_num_range.max)
{
U64 slice_line_idx = dasm2src_info.pt.line-visible_line_num_range.min;
@@ -5943,14 +5940,14 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
{
MemoryCopy(code_slice_params.line_src2dasm, src2dasm.v, sizeof(DF_TextLineSrc2DasmInfoList)*src2dasm.count);
}
code_slice_params.relevant_binaries = src2dasm.binaries;
code_slice_params.relevant_dbgi_keys = src2dasm.dbgi_keys;
}
}
//////////////////////////////
//- rjf: build missing & override interface
//
if(entity_is_missing)
if(entity_is_missing && !text_info_is_ready)
{
UI_WidthFill UI_HeightFill UI_Column UI_Padding(ui_pct(1, 0))
{
@@ -6187,7 +6184,7 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
String8 expr = txt_string_from_info_data_txt_rng(&text_info, data, expr_rng);
if(expr.size != 0)
{
DF_Eval eval = df_eval_from_string(scratch.arena, dbgi_scope, &ctrl_ctx, &parse_ctx, &eval_string2expr_map_nil, expr);
DF_Eval eval = df_eval_from_string(scratch.arena, di_scope, &ctrl_ctx, &parse_ctx, &eval_string2expr_map_nil, expr);
if(eval.mode != EVAL_EvalMode_NULL)
{
df_set_hover_eval(ws, sig.mouse_expr_baseline_pos, ctrl_ctx, entity, sig.mouse_pt, 0, expr);
@@ -6259,8 +6256,8 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
if(src2dasm_list->first != 0)
{
Rng1U64 voff_rng = src2dasm_list->first->v.voff_range;
DF_Entity *binary = src2dasm_list->first->v.binary;
DF_EntityList possible_modules = df_modules_from_binary_file(scratch.arena, binary);
DI_Key dbgi_key = src2dasm_list->first->v.dbgi_key;
DF_EntityList possible_modules = df_modules_from_dbgi_key(scratch.arena, &dbgi_key);
DF_Entity *thread_dst_module = df_module_from_thread_candidates(dropped_entity, &possible_modules);
U64 thread_dst_voff = voff_rng.min;
if(!df_entity_is_nil(thread_dst_module) && thread_dst_voff != 0)
@@ -6316,8 +6313,8 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
if(src2dasm_list->first != 0)
{
Rng1U64 voff_rng = src2dasm_list->first->v.voff_range;
DF_Entity *binary = src2dasm_list->first->v.binary;
DF_EntityList possible_modules = df_modules_from_binary_file(scratch.arena, binary);
DI_Key dbgi_key = src2dasm_list->first->v.dbgi_key;
DF_EntityList possible_modules = df_modules_from_dbgi_key(scratch.arena, &dbgi_key);
DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread);
DF_Entity *thread_dst_module = df_module_from_thread_candidates(thread, &possible_modules);
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
@@ -6475,20 +6472,19 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
//- rjf: determine up-to-dateness of source file
//
B32 file_is_out_of_date = 0;
String8 out_of_date_binary_name = {0};
for(DF_EntityNode *n = code_slice_params.relevant_binaries.first; n != 0; n = n->next)
String8 out_of_date_dbgi_name = {0};
for(DI_KeyNode *n = code_slice_params.relevant_dbgi_keys.first; n != 0; n = n->next)
{
DF_Entity *binary = n->entity;
if(!df_entity_is_nil(binary))
DI_Key key = n->v;
if(key.path.size != 0)
{
String8 full_path = df_full_path_from_entity(scratch.arena, entity);
TXTI_Handle handle = txti_handle_from_path(full_path);
TXTI_BufferInfo info = txti_buffer_info_from_handle(scratch.arena, handle);
DBGI_Parse *parse = df_dbgi_parse_from_binary_file(dbgi_scope, binary);
if(parse->exe_props.modified < info.timestamp)
if(key.min_timestamp < info.timestamp)
{
file_is_out_of_date = 1;
out_of_date_binary_name = binary->name;
out_of_date_dbgi_name = str8_skip_last_slash(key.path);
break;
}
}
@@ -6526,9 +6522,9 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
{
UI_PrefWidth(ui_children_sum(1)) UI_Row UI_PrefWidth(ui_text_dim(1, 1))
{
ui_labelf("This file has changed since ", out_of_date_binary_name);
UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_Highlight0)) ui_label(out_of_date_binary_name);
ui_labelf(" was built.");
ui_labelf("This file has changed since ", out_of_date_dbgi_name);
UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_Highlight0)) ui_label(out_of_date_dbgi_name);
ui_labelf(" was produced.");
}
}
}
@@ -6536,7 +6532,7 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
{
ui_label(full_path);
ui_spacer(ui_em(1.5f, 1));
ui_labelf("Row: %I64d, Col: %I64d", tv->cursor.line, tv->cursor.column);
ui_labelf("Line: %I64d, Col: %I64d", tv->cursor.line, tv->cursor.column);
ui_spacer(ui_pct(1, 0));
ui_labelf("(read only)");
ui_labelf("%s",
@@ -6548,7 +6544,7 @@ DF_VIEW_UI_FUNCTION_DEF(Code)
}
txt_scope_close(txt_scope);
dbgi_scope_close(dbgi_scope);
di_scope_close(di_scope);
hs_scope_close(hs_scope);
scratch_end(scratch);
ProfEnd();
@@ -6590,8 +6586,8 @@ DF_VIEW_CMD_FUNCTION_DEF(Disassembly)
DF_Entity *process = df_entity_from_handle(dv->process);
Architecture arch = df_architecture_from_entity(process);
U64 dasm_base_vaddr = AlignDownPow2(dv->base_vaddr, KB(64));
DF_Entity *dasm_module = df_module_from_process_vaddr(process, dasm_base_vaddr);
DF_Entity *dasm_binary = df_binary_file_from_module(dasm_module);
DF_Entity *dasm_module = df_module_from_process_vaddr(process, dasm_base_vaddr);
DI_Key dasm_dbgi_key = df_dbgi_key_from_module(dasm_module);
Rng1U64 dasm_vaddr_range = r1u64(dasm_base_vaddr, dasm_base_vaddr+KB(64));
U128 dasm_key = ctrl_hash_store_key_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, dasm_vaddr_range, 0);
U128 dasm_data_hash = {0};
@@ -6602,7 +6598,7 @@ DF_VIEW_CMD_FUNCTION_DEF(Disassembly)
dasm_params.style_flags = dv->style_flags;
dasm_params.syntax = DASM_Syntax_Intel;
dasm_params.base_vaddr = dasm_module->vaddr_rng.min;
dasm_params.exe_path = df_full_path_from_entity(scratch.arena, dasm_binary);
dasm_params.dbgi_key = dasm_dbgi_key;
}
DASM_Info dasm_info = dasm_info_from_key_params(dasm_scope, dasm_key, &dasm_params, &dasm_data_hash);
U128 dasm_text_hash = {0};
@@ -6801,7 +6797,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
HS_Scope *hs_scope = hs_scope_open();
DASM_Scope *dasm_scope = dasm_scope_open();
TXT_Scope *txt_scope = txt_scope_open();
DBGI_Scope *dbgi_scope = dbgi_scope_open();
DI_Scope *di_scope = di_scope_open();
DF_DisasmViewState *dv = df_view_user_state(view, DF_DisasmViewState);
//////////////////////////////
@@ -6826,7 +6822,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
DF_Entity *selected_process = df_entity_ancestor_from_kind(selected_thread, DF_EntityKind_Process);
U64 unwind_count = ctrl_ctx.unwind_count;
U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(selected_thread, unwind_count);
EVAL_ParseCtx parse_ctx = df_eval_parse_ctx_from_process_vaddr(dbgi_scope, selected_process, rip_vaddr);
EVAL_ParseCtx parse_ctx = df_eval_parse_ctx_from_process_vaddr(di_scope, selected_process, rip_vaddr);
//////////////////////////////
//- rjf: no disasm process open? -> snap to selected thread
@@ -6843,10 +6839,10 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
//
DF_Entity *process = df_entity_from_handle(dv->process);
Architecture arch = df_architecture_from_entity(process);
U64 dasm_base_vaddr = AlignDownPow2(dv->base_vaddr, KB(64));
U64 dasm_base_vaddr = AlignDownPow2(dv->base_vaddr, KB(16));
DF_Entity *dasm_module = df_module_from_process_vaddr(process, dasm_base_vaddr);
DF_Entity *dasm_binary = df_binary_file_from_module(dasm_module);
Rng1U64 dasm_vaddr_range = r1u64(dasm_base_vaddr, dasm_base_vaddr+KB(64));
DI_Key dasm_dbgi_key = df_dbgi_key_from_module(dasm_module);
Rng1U64 dasm_vaddr_range = r1u64(dasm_base_vaddr, dasm_base_vaddr+KB(16));
U128 dasm_key = ctrl_hash_store_key_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, dasm_vaddr_range, 0);
U128 dasm_data_hash = {0};
DASM_Params dasm_params = {0};
@@ -6856,7 +6852,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
dasm_params.style_flags = dv->style_flags;
dasm_params.syntax = DASM_Syntax_Intel;
dasm_params.base_vaddr = dasm_module->vaddr_rng.min;
dasm_params.exe_path = df_full_path_from_entity(scratch.arena, dasm_binary);
dasm_params.dbgi_key = dasm_dbgi_key;
}
DASM_Info dasm_info = dasm_info_from_key_params(dasm_scope, dasm_key, &dasm_params, &dasm_data_hash);
U128 dasm_text_hash = {0};
@@ -6869,7 +6865,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
//- rjf: unpack module info for this region
//
DF_Entity *module = df_module_from_process_vaddr(process, dasm_vaddr_range.min);
DF_Entity *binary = df_binary_file_from_module(module);
DI_Key dbgi_key = df_dbgi_key_from_module(module);
//////////////////////////////
//- rjf: is loading -> equip view with loading information
@@ -6958,7 +6954,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
{
code_slice_params.margin_float_off_px = 0;
}
df_entity_list_push(scratch.arena, &code_slice_params.relevant_binaries, binary);
di_key_list_push(scratch.arena, &code_slice_params.relevant_dbgi_keys, &dbgi_key);
// rjf: fill text info
{
@@ -7040,7 +7036,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
// rjf: fill dasm -> src info
{
DF_Entity *module = df_module_from_process_vaddr(process, dasm_vaddr_range.min);
DF_Entity *binary = df_binary_file_from_module(module);
DI_Key dbgi_key = df_dbgi_key_from_module(module);
for(S64 line_num = visible_line_num_range.min; line_num < visible_line_num_range.max; line_num += 1)
{
U64 vaddr = dasm_vaddr_range.min + dasm_inst_array_code_off_from_idx(&dasm_info.insts, line_num-1);
@@ -7049,7 +7045,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
DF_TextLineDasm2SrcInfoNode *dasm2src_n = push_array(scratch.arena, DF_TextLineDasm2SrcInfoNode, 1);
SLLQueuePush(code_slice_params.line_dasm2src[slice_idx].first, code_slice_params.line_dasm2src[slice_idx].last, dasm2src_n);
code_slice_params.line_dasm2src[slice_idx].count += 1;
dasm2src_n->v = df_text_line_dasm2src_info_from_binary_voff(binary, voff);
dasm2src_n->v = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, voff);
}
}
}
@@ -7119,7 +7115,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
String8 expr = str8_substr(code_slice_params.line_text[line_idx], r1u64(sig.mouse_expr_rng.min.column-1, sig.mouse_expr_rng.max.column-1));
if(expr.size != 0)
{
DF_Eval eval = df_eval_from_string(scratch.arena, dbgi_scope, &ctrl_ctx, &parse_ctx, &eval_string2expr_map_nil, expr);
DF_Eval eval = df_eval_from_string(scratch.arena, di_scope, &ctrl_ctx, &parse_ctx, &eval_string2expr_map_nil, expr);
if(eval.mode != EVAL_EvalMode_NULL)
{
U64 off = dasm_inst_array_code_off_from_idx(&dasm_info.insts, sig.mouse_expr_rng.min.line-1);
@@ -7219,9 +7215,9 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
{
U64 vaddr = dasm_vaddr_range.min+dasm_inst_array_code_off_from_idx(&dasm_info.insts, sig.goto_src_line_num-1);
DF_Entity *module = df_module_from_process_vaddr(process, vaddr);
DF_Entity *binary = df_binary_file_from_module(module);
DI_Key dbgi_key = df_dbgi_key_from_module(module);
U64 voff = df_voff_from_vaddr(module, vaddr);
DF_TextLineDasm2SrcInfo dasm2src = df_text_line_dasm2src_info_from_binary_voff(binary, voff);
DF_TextLineDasm2SrcInfo dasm2src = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, voff);
String8 file_path = df_full_path_from_entity(scratch.arena, dasm2src.file);
DF_CmdParams params = df_cmd_params_from_view(ws, panel, view);
params.text_point = dasm2src.pt;
@@ -7388,14 +7384,14 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly)
U64 cursor_vaddr = (1 <= dv->cursor.line && dv->cursor.line <= dasm_info.insts.count) ? (dasm_vaddr_range.min+dasm_info.insts.v[dv->cursor.line-1].code_off) : 0;
ui_labelf("%S", path_normalized_from_string(scratch.arena, module->name));
ui_spacer(ui_em(1.5f, 1));
ui_labelf("Address: 0x%I64x, Row: %I64d, Col: %I64d", cursor_vaddr, dv->cursor.line, dv->cursor.column);
ui_labelf("Address: 0x%I64x, Line: %I64d, Col: %I64d", cursor_vaddr, dv->cursor.line, dv->cursor.column);
ui_spacer(ui_pct(1, 0));
ui_labelf("(read only)");
ui_labelf("bin");
}
}
dbgi_scope_close(dbgi_scope);
di_scope_close(di_scope);
txt_scope_close(txt_scope);
dasm_scope_close(dasm_scope);
hs_scope_close(hs_scope);
@@ -7667,7 +7663,7 @@ DF_VIEW_UI_FUNCTION_DEF(Output)
{
ProfBeginFunction();
Temp scratch = scratch_begin(0, 0);
DBGI_Scope *scope = dbgi_scope_open();
DI_Scope *scope = di_scope_open();
DF_CodeViewState *tv = df_view_user_state(view, DF_CodeViewState);
//////////////////////////////
@@ -8182,13 +8178,13 @@ DF_VIEW_UI_FUNCTION_DEF(Output)
UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText))
UI_Font(code_font)
{
ui_labelf("Row: %I64d, Col: %I64d", tv->cursor.line, tv->cursor.column);
ui_labelf("Line: %I64d, Col: %I64d", tv->cursor.line, tv->cursor.column);
ui_spacer(ui_pct(1, 0));
ui_labelf("(read only)");
}
}
dbgi_scope_close(scope);
di_scope_close(scope);
scratch_end(scratch);
ProfEnd();
}
@@ -8547,21 +8543,23 @@ DF_VIEW_UI_FUNCTION_DEF(Memory)
CTRL_Unwind unwind = df_query_cached_unwind_from_thread(thread);
//- rjf: fill unwind frame annotations
if(unwind.first != 0)
if(unwind.frames.count != 0)
{
U64 last_stack_top = regs_rsp_from_arch_block(thread->arch, unwind.first->regs);
for(CTRL_UnwindFrame *f = unwind.first->next; f != 0; f = f->next)
U64 last_stack_top = regs_rsp_from_arch_block(thread->arch, unwind.frames.v[0].regs);
for(U64 idx = 1; idx < unwind.frames.count; idx += 1)
{
CTRL_UnwindFrame *f = &unwind.frames.v[idx];
U64 f_stack_top = regs_rsp_from_arch_block(thread->arch, f->regs);
Rng1U64 frame_vaddr_range = r1u64(last_stack_top, f_stack_top);
Rng1U64 frame_vaddr_range_in_viz = intersect_1u64(frame_vaddr_range, viz_range_bytes);
last_stack_top = f_stack_top;
if(dim_1u64(frame_vaddr_range_in_viz) != 0)
{
DF_Entity *module = df_module_from_process_vaddr(process, f->rip);
DF_Entity *binary = df_binary_file_from_module(module);
U64 rip_voff = df_voff_from_vaddr(module, f->rip);
String8 symbol_name = df_symbol_name_from_binary_voff(scratch.arena, binary, rip_voff);
U64 f_rip = regs_rip_from_arch_block(thread->arch, f->regs);
DF_Entity *module = df_module_from_process_vaddr(process, f_rip);
DI_Key dbgi_key = df_dbgi_key_from_module(module);
U64 rip_voff = df_voff_from_vaddr(module, f_rip);
String8 symbol_name = df_symbol_name_from_dbgi_key_voff(scratch.arena, &dbgi_key, rip_voff);
Annotation *annotation = push_array(scratch.arena, Annotation, 1);
annotation->name_string = symbol_name.size != 0 ? symbol_name : str8_lit("[external code]");
annotation->kind_string = str8_lit("Call Stack Frame");
@@ -8577,10 +8575,10 @@ DF_VIEW_UI_FUNCTION_DEF(Memory)
}
//- rjf: fill selected thread stack range annotation
if(unwind.first != 0)
if(unwind.frames.count > 0)
{
U64 stack_base_vaddr = thread->stack_base;
U64 stack_top_vaddr = regs_rsp_from_arch_block(thread->arch, unwind.first->regs);
U64 stack_top_vaddr = regs_rsp_from_arch_block(thread->arch, unwind.frames.v[0].regs);
Rng1U64 stack_vaddr_range = r1u64(stack_base_vaddr, stack_top_vaddr);
Rng1U64 stack_vaddr_range_in_viz = intersect_1u64(stack_vaddr_range, viz_range_bytes);
if(dim_1u64(stack_vaddr_range_in_viz) != 0)
@@ -8611,7 +8609,7 @@ DF_VIEW_UI_FUNCTION_DEF(Memory)
df_rgba_from_theme_color(DF_ThemeColor_Thread6),
df_rgba_from_theme_color(DF_ThemeColor_Thread7),
};
DBGI_Scope *scope = dbgi_scope_open();
DI_Scope *scope = di_scope_open();
U64 thread_rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, ctrl_ctx.unwind_count);
EVAL_ParseCtx parse_ctx = df_eval_parse_ctx_from_process_vaddr(scope, process, thread_rip_vaddr);
RDI_Parsed *rdi = parse_ctx.rdi;
@@ -8642,7 +8640,7 @@ DF_VIEW_UI_FUNCTION_DEF(Memory)
}
}
}
dbgi_scope_close(scope);
di_scope_close(scope);
}
}
+1 -2
View File
@@ -101,7 +101,6 @@ struct DF_PendingEntityViewState
{
Arena *deferred_cmd_arena;
DF_CmdList deferred_cmds;
DF_Handle pick_file_override_target;
Arena *complete_cfg_arena;
DF_CfgNode *complete_cfg_root;
};
@@ -496,7 +495,7 @@ internal String8 df_string_from_eval_viz_row_column_kind(Arena *arena, DF_EvalVi
internal DF_WatchViewTextEditState *df_watch_view_text_edit_state_from_pt(DF_WatchViewState *wv, DF_WatchViewPoint pt);
//- rjf: windowed watch tree visualization
internal DF_EvalVizBlockList df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_View *view, DF_WatchViewState *ews);
internal DF_EvalVizBlockList df_eval_viz_block_list_from_watch_view_state(Arena *arena, DI_Scope *di_scope, FZY_Scope *fzy_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_View *view, DF_WatchViewState *ews);
//- rjf: eval/watch views main hooks
internal void df_watch_view_init(DF_WatchViewState *ewv, DF_View *view, DF_WatchViewFillKind fill_kind);
+562
View File
@@ -0,0 +1,562 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Helpers
internal U64
fzy_hash_from_string(U64 seed, String8 string)
{
U64 result = seed;
for(U64 i = 0; i < string.size; i += 1)
{
result = ((result << 5) + result) + string.str[i];
}
return result;
}
internal U64
fzy_hash_from_params(FZY_Params *params)
{
U64 hash = 5381;
hash = fzy_hash_from_string(hash, str8_struct(&params->target));
for(U64 idx = 0; idx < params->dbgi_keys.count; idx += 1)
{
hash = fzy_hash_from_string(hash, str8_struct(&params->dbgi_keys.v[idx].min_timestamp));
hash = fzy_hash_from_string(hash, params->dbgi_keys.v[idx].path);
}
return hash;
}
internal U64
fzy_item_num_from_array_element_idx__linear_search(FZY_ItemArray *array, U64 element_idx)
{
U64 fuzzy_item_num = 0;
for(U64 idx = 0; idx < array->count; idx += 1)
{
if(array->v[idx].idx == element_idx)
{
fuzzy_item_num = idx+1;
break;
}
}
return fuzzy_item_num;
}
internal String8
fzy_item_string_from_rdi_target_element_idx(RDI_Parsed *rdi, FZY_Target target, U64 element_idx)
{
String8 result = {0};
switch(target)
{
// NOTE(rjf): no default - warn if we miss a case
case FZY_Target_Procedures:
{
RDI_Procedure *proc = rdi_element_from_idx(rdi, procedures, element_idx);
U64 name_size = 0;
U8 *name_base = rdi_string_from_idx(rdi, proc->name_string_idx, &name_size);
result = str8(name_base, name_size);
}break;
case FZY_Target_GlobalVariables:
{
RDI_GlobalVariable *gvar = rdi_element_from_idx(rdi, global_variables, element_idx);
U64 name_size = 0;
U8 *name_base = rdi_string_from_idx(rdi, gvar->name_string_idx, &name_size);
result = str8(name_base, name_size);
}break;
case FZY_Target_ThreadVariables:
{
RDI_ThreadVariable *tvar = rdi_element_from_idx(rdi, thread_variables, element_idx);
U64 name_size = 0;
U8 *name_base = rdi_string_from_idx(rdi, tvar->name_string_idx, &name_size);
result = str8(name_base, name_size);
}break;
case FZY_Target_UDTs:
{
RDI_UDT *udt = rdi_element_from_idx(rdi, udts, element_idx);
RDI_TypeNode *type_node = rdi_element_from_idx(rdi, type_nodes, udt->self_type_idx);
U64 name_size = 0;
U8 *name_base = rdi_string_from_idx(rdi, type_node->user_defined.name_string_idx, &name_size);
result = str8(name_base, name_size);
}break;
case FZY_Target_COUNT:{}break;
}
return result;
}
internal FZY_Params
fzy_params_copy(Arena *arena, FZY_Params *src)
{
FZY_Params dst = zero_struct;
MemoryCopyStruct(&dst, src);
dst.dbgi_keys.v = push_array(arena, DI_Key, dst.dbgi_keys.count);
MemoryCopy(dst.dbgi_keys.v, src->dbgi_keys.v, sizeof(DI_Key)*src->dbgi_keys.count);
for(U64 idx = 0; idx < dst.dbgi_keys.count; idx += 1)
{
dst.dbgi_keys.v[idx].path = push_str8_copy(arena, dst.dbgi_keys.v[idx].path);
}
return dst;
}
////////////////////////////////
//~ rjf: Main Layer Initialization
internal void
fzy_init(void)
{
Arena *arena = arena_alloc();
fzy_shared = push_array(arena, FZY_Shared, 1);
fzy_shared->arena = arena;
fzy_shared->slots_count = 256;
fzy_shared->stripes_count = os_logical_core_count();
fzy_shared->slots = push_array(arena, FZY_Slot, fzy_shared->slots_count);
fzy_shared->stripes = push_array(arena, FZY_Stripe, fzy_shared->stripes_count);
for(U64 idx = 0; idx < fzy_shared->stripes_count; idx += 1)
{
fzy_shared->stripes[idx].arena = arena_alloc();
fzy_shared->stripes[idx].rw_mutex = os_rw_mutex_alloc();
fzy_shared->stripes[idx].cv = os_condition_variable_alloc();
}
fzy_shared->thread_count = Min(os_logical_core_count(), 2);
fzy_shared->threads = push_array(arena, FZY_Thread, fzy_shared->thread_count);
for(U64 idx = 0; idx < fzy_shared->thread_count; idx += 1)
{
fzy_shared->threads[idx].u2f_ring_mutex = os_mutex_alloc();
fzy_shared->threads[idx].u2f_ring_cv = os_condition_variable_alloc();
fzy_shared->threads[idx].u2f_ring_size = KB(64);
fzy_shared->threads[idx].u2f_ring_base = push_array_no_zero(arena, U8, fzy_shared->threads[idx].u2f_ring_size);
fzy_shared->threads[idx].thread = os_launch_thread(fzy_search_thread__entry_point, (void *)idx, 0);
}
}
////////////////////////////////
//~ rjf: Scope Functions
internal FZY_Scope *
fzy_scope_open(void)
{
if(fzy_tctx == 0)
{
Arena *arena = arena_alloc();
fzy_tctx = push_array(arena, FZY_TCTX, 1);
fzy_tctx->arena = arena;
}
FZY_Scope *scope = fzy_tctx->free_scope;
if(scope != 0)
{
SLLStackPop(fzy_tctx->free_scope);
}
else
{
scope = push_array_no_zero(fzy_tctx->arena, FZY_Scope, 1);
}
MemoryZeroStruct(scope);
return scope;
}
internal void
fzy_scope_close(FZY_Scope *scope)
{
for(FZY_Touch *t = scope->first_touch, *next = 0; t != 0; t = next)
{
next = t->next;
SLLStackPush(fzy_tctx->free_touch, t);
if(t->node != 0)
{
ins_atomic_u64_dec_eval(&t->node->touch_count);
}
}
SLLStackPush(fzy_tctx->free_scope, scope);
}
internal void
fzy_scope_touch_node__stripe_mutex_r_guarded(FZY_Scope *scope, FZY_Node *node)
{
if(node != 0)
{
ins_atomic_u64_inc_eval(&node->touch_count);
}
FZY_Touch *touch = fzy_tctx->free_touch;
if(touch != 0)
{
SLLStackPop(fzy_tctx->free_touch);
}
else
{
touch = push_array_no_zero(fzy_tctx->arena, FZY_Touch, 1);
}
MemoryZeroStruct(touch);
SLLQueuePush(scope->first_touch, scope->last_touch, touch);
touch->node = node;
}
////////////////////////////////
//~ rjf: Cache Lookup Functions
internal FZY_ItemArray
fzy_items_from_key_params_query(FZY_Scope *scope, U128 key, FZY_Params *params, String8 query, U64 endt_us, B32 *stale_out)
{
Temp scratch = scratch_begin(0, 0);
FZY_ItemArray items = {0};
//- rjf: hash parameters
U64 params_hash = fzy_hash_from_params(params);
//- rjf: unpack key
U64 slot_idx = key.u64[1]%fzy_shared->slots_count;
U64 stripe_idx = slot_idx%fzy_shared->stripes_count;
FZY_Slot *slot = &fzy_shared->slots[slot_idx];
FZY_Stripe *stripe = &fzy_shared->stripes[stripe_idx];
//- rjf: query and/or request
OS_MutexScopeR(stripe->rw_mutex) for(;;)
{
// rjf: map key -> node
FZY_Node *node = 0;
for(FZY_Node *n = slot->first; n != 0; n = n->next)
{
if(u128_match(n->key, key))
{
node = n;
break;
}
}
// rjf: no node? -> allocate
if(node == 0) OS_MutexScopeRWPromote(stripe->rw_mutex)
{
node = push_array(stripe->arena, FZY_Node, 1);
SLLQueuePush(slot->first, slot->last, node);
node->key = key;
for(U64 idx = 0; idx < ArrayCount(node->buckets); idx += 1)
{
node->buckets[idx].arena = arena_alloc();
}
}
// rjf: try to grab last valid results for this key/query; determine if stale
B32 stale = 1;
if(params_hash == node->buckets[node->gen%ArrayCount(node->buckets)].params_hash &&
node->gen != 0)
{
fzy_scope_touch_node__stripe_mutex_r_guarded(scope, node);
items = node->gen_items;
stale = !str8_match(query, node->buckets[node->gen%ArrayCount(node->buckets)].query, 0);
if(stale_out != 0)
{
*stale_out = stale;
}
}
// rjf: if stale -> request again
if(stale) OS_MutexScopeRWPromote(stripe->rw_mutex)
{
if(node->gen <= node->submit_gen && node->submit_gen < node->gen + ArrayCount(node->buckets)-1)
{
node->submit_gen += 1;
arena_clear(node->buckets[node->submit_gen%ArrayCount(node->buckets)].arena);
node->buckets[node->submit_gen%ArrayCount(node->buckets)].query = push_str8_copy(node->buckets[node->submit_gen%ArrayCount(node->buckets)].arena, query);
node->buckets[node->submit_gen%ArrayCount(node->buckets)].params = fzy_params_copy(node->buckets[node->submit_gen%ArrayCount(node->buckets)].arena, params);
node->buckets[node->submit_gen%ArrayCount(node->buckets)].params_hash = params_hash;
}
if((node->submit_gen > node->gen+1 || os_now_microseconds() >= node->last_time_submitted_us+100000) &&
fzy_u2s_enqueue_req(key, endt_us))
{
node->last_time_submitted_us = os_now_microseconds();
}
}
// rjf: not stale, or timeout -> break
if(!stale || os_now_microseconds() >= endt_us)
{
break;
}
// rjf: no results, but have time to wait -> wait
os_condition_variable_wait_rw_r(stripe->cv, stripe->rw_mutex, endt_us);
}
scratch_end(scratch);
return items;
}
////////////////////////////////
//~ rjf: Searcher Threads
internal B32
fzy_u2s_enqueue_req(U128 key, U64 endt_us)
{
B32 sent = 0;
FZY_Thread *thread = &fzy_shared->threads[key.u64[1]%fzy_shared->thread_count];
OS_MutexScope(thread->u2f_ring_mutex) for(;;)
{
U64 unconsumed_size = thread->u2f_ring_write_pos - thread->u2f_ring_read_pos;
U64 available_size = thread->u2f_ring_size - unconsumed_size;
if(available_size >= sizeof(U128))
{
sent = 1;
thread->u2f_ring_write_pos += ring_write_struct(thread->u2f_ring_base, thread->u2f_ring_size, thread->u2f_ring_write_pos, &key);
break;
}
os_condition_variable_wait(thread->u2f_ring_cv, thread->u2f_ring_mutex, endt_us);
}
if(sent)
{
os_condition_variable_broadcast(thread->u2f_ring_cv);
}
return sent;
}
internal void
fzy_u2s_dequeue_req(Arena *arena, FZY_Thread *thread, U128 *key_out)
{
OS_MutexScope(thread->u2f_ring_mutex) for(;;)
{
U64 unconsumed_size = thread->u2f_ring_write_pos - thread->u2f_ring_read_pos;
if(unconsumed_size >= sizeof(U128))
{
thread->u2f_ring_read_pos += ring_read_struct(thread->u2f_ring_base, thread->u2f_ring_size, thread->u2f_ring_read_pos, key_out);
break;
}
os_condition_variable_wait(thread->u2f_ring_cv, thread->u2f_ring_mutex, max_U64);
}
os_condition_variable_broadcast(thread->u2f_ring_cv);
}
internal int
fzy_qsort_compare_items(FZY_Item *a, FZY_Item *b)
{
int result = 0;
if(a->match_ranges.count > b->match_ranges.count)
{
result = -1;
}
else if(a->match_ranges.count < b->match_ranges.count)
{
result = +1;
}
else if(a->missed_size < b->missed_size)
{
result = -1;
}
else if(a->missed_size > b->missed_size)
{
result = +1;
}
return result;
}
internal void
fzy_search_thread__entry_point(void *p)
{
ThreadNameF("[fzy] searcher #%I64u", (U64)p);
FZY_Thread *thread = &fzy_shared->threads[(U64)p];
for(;;)
{
Temp scratch = scratch_begin(0, 0);
DI_Scope *di_scope = di_scope_open();
////////////////////////////
//- rjf: dequeue next request
//
U128 key = {0};
fzy_u2s_dequeue_req(scratch.arena, thread, &key);
U64 slot_idx = key.u64[1]%fzy_shared->slots_count;
U64 stripe_idx = slot_idx%fzy_shared->stripes_count;
FZY_Slot *slot = &fzy_shared->slots[slot_idx];
FZY_Stripe *stripe = &fzy_shared->stripes[stripe_idx];
////////////////////////////
//- rjf: grab next exe_path/query for this key
//
B32 task_is_good = 0;
Arena *task_arena = 0;
String8 query = {0};
FZY_Params params = {FZY_Target_Procedures};
U64 initial_submit_gen = 0;
OS_MutexScopeW(stripe->rw_mutex)
{
for(FZY_Node *n = slot->first; n != 0; n = n->next)
{
if(u128_match(n->key, key))
{
FZY_Bucket *bucket = &n->buckets[n->submit_gen%ArrayCount(n->buckets)];
task_is_good = 1;
initial_submit_gen = n->submit_gen;
task_arena = bucket->arena;
query = bucket->query;
params = bucket->params;
break;
}
}
}
////////////////////////////
//- rjf: params -> look up all rdis
//
U64 rdis_count = params.dbgi_keys.count;
RDI_Parsed **rdis = push_array(scratch.arena, RDI_Parsed *, rdis_count);
if(task_is_good)
{
for(U64 idx = 0; idx < rdis_count; idx += 1)
{
rdis[idx] = di_rdi_from_key(di_scope, &params.dbgi_keys.v[idx], max_U64);
}
}
////////////////////////////
//- rjf: search target -> info about search space
//
U64 table_ptr_off = 0;
U64 table_count_off = 0;
U64 element_name_idx_off = 0;
U64 element_size = 0;
if(task_is_good)
{
switch(params.target)
{
// NOTE(rjf): no default!
case FZY_Target_COUNT:{}break;
case FZY_Target_Procedures:
{
table_ptr_off = OffsetOf(RDI_Parsed, procedures);
table_count_off = OffsetOf(RDI_Parsed, procedures_count);
element_name_idx_off = OffsetOf(RDI_Procedure, name_string_idx);
element_size = sizeof(RDI_Procedure);
}break;
case FZY_Target_GlobalVariables:
{
table_ptr_off = OffsetOf(RDI_Parsed, global_variables);
table_count_off = OffsetOf(RDI_Parsed, global_variables_count);
element_name_idx_off = OffsetOf(RDI_GlobalVariable, name_string_idx);
element_size = sizeof(RDI_GlobalVariable);
}break;
case FZY_Target_ThreadVariables:
{
table_ptr_off = OffsetOf(RDI_Parsed, thread_variables);
table_count_off = OffsetOf(RDI_Parsed, thread_variables_count);
element_name_idx_off = OffsetOf(RDI_ThreadVariable, name_string_idx);
element_size = sizeof(RDI_ThreadVariable);
}break;
case FZY_Target_UDTs:
{
table_ptr_off = OffsetOf(RDI_Parsed, udts);
table_count_off = OffsetOf(RDI_Parsed, udts_count);
element_size = sizeof(RDI_UDT);
}break;
}
}
////////////////////////////
//- rjf: rdis * query * params -> item list
//
FZY_ItemChunkList items_list = {0};
if(task_is_good)
{
U64 base_idx = 0;
for(U64 rdi_idx = 0; rdi_idx < rdis_count; rdi_idx += 1)
{
RDI_Parsed *rdi = rdis[rdi_idx];
void *table_base = (U8*)rdi + table_ptr_off;
U64 element_count = *MemberFromOffset(U64 *, rdi, table_count_off);
for(U64 idx = 1; task_is_good && idx < element_count; idx += 1)
{
void *element = (U8 *)(*(void **)table_base) + element_size*idx;
U32 *name_idx_ptr = (U32 *)((U8 *)element + element_name_idx_off);
if(params.target == FZY_Target_UDTs)
{
RDI_UDT *udt = (RDI_UDT *)element;
RDI_TypeNode *type_node = rdi_element_from_idx(rdi, type_nodes, udt->self_type_idx);
name_idx_ptr = &type_node->user_defined.name_string_idx;
}
U32 name_idx = *name_idx_ptr;
U64 name_size = 0;
U8 *name_base = rdi_string_from_idx(rdi, name_idx, &name_size);
String8 name = str8(name_base, name_size);
if(name.size == 0) { continue; }
FuzzyMatchRangeList matches = fuzzy_match_find(task_arena, query, name);
if(matches.count == matches.needle_part_count)
{
FZY_ItemChunk *chunk = items_list.last;
if(chunk == 0 || chunk->count >= chunk->cap)
{
chunk = push_array(scratch.arena, FZY_ItemChunk, 1);
chunk->cap = 1024;
chunk->count = 0;
chunk->v = push_array_no_zero(scratch.arena, FZY_Item, chunk->cap);
SLLQueuePush(items_list.first, items_list.last, chunk);
items_list.chunk_count += 1;
}
chunk->v[chunk->count].idx = base_idx + idx;
chunk->v[chunk->count].match_ranges = matches;
chunk->v[chunk->count].missed_size = (name_size > matches.total_dim) ? (name_size-matches.total_dim) : 0;
chunk->count += 1;
items_list.total_count += 1;
}
if(idx%100 == 99) OS_MutexScopeR(stripe->rw_mutex)
{
for(FZY_Node *n = slot->first; n != 0; n = n->next)
{
if(u128_match(n->key, key) && n->submit_gen > initial_submit_gen)
{
task_is_good = 0;
break;
}
}
}
}
base_idx += element_count;
}
}
//- rjf: item list -> item array
FZY_ItemArray items = {0};
if(task_is_good)
{
items.count = items_list.total_count;
items.v = push_array_no_zero(task_arena, FZY_Item, items.count);
U64 idx = 0;
for(FZY_ItemChunk *chunk = items_list.first; chunk != 0; chunk = chunk->next)
{
MemoryCopy(items.v+idx, chunk->v, sizeof(FZY_Item)*chunk->count);
idx += chunk->count;
}
}
//- rjf: sort item array
if(items.count != 0 && query.size != 0)
{
qsort(items.v, items.count, sizeof(FZY_Item), (int (*)(const void *, const void *))fzy_qsort_compare_items);
}
//- rjf: commit to cache - busyloop on scope touches
if(task_is_good)
{
for(B32 done = 0; !done;)
{
B32 found = 0;
OS_MutexScopeW(stripe->rw_mutex) for(FZY_Node *n = slot->first; n != 0; n = n->next)
{
if(u128_match(n->key, key))
{
if(n->touch_count == 0)
{
n->gen = initial_submit_gen;
n->gen_items = items;
done = 1;
}
found = 1;
break;
}
}
if(!found)
{
break;
}
}
}
di_scope_close(di_scope);
scratch_end(scratch);
}
}
+202
View File
@@ -0,0 +1,202 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef FUZZY_SEARCH_H
#define FUZZY_SEARCH_H
////////////////////////////////
//~ rjf: Result Types
typedef struct FZY_Item FZY_Item;
struct FZY_Item
{
U64 idx; // indexes into whole space of parameter tables. [rdis[0] element count) [rdis[1] element count) ... [rdis[n] element count)
U64 missed_size;
FuzzyMatchRangeList match_ranges;
};
typedef struct FZY_ItemChunk FZY_ItemChunk;
struct FZY_ItemChunk
{
FZY_ItemChunk *next;
FZY_Item *v;
U64 count;
U64 cap;
};
typedef struct FZY_ItemChunkList FZY_ItemChunkList;
struct FZY_ItemChunkList
{
FZY_ItemChunk *first;
FZY_ItemChunk *last;
U64 chunk_count;
U64 total_count;
};
typedef struct FZY_ItemArray FZY_ItemArray;
struct FZY_ItemArray
{
FZY_Item *v;
U64 count;
};
////////////////////////////////
//~ rjf: Search Parameter Types
typedef enum FZY_Target
{
FZY_Target_Procedures,
FZY_Target_GlobalVariables,
FZY_Target_ThreadVariables,
FZY_Target_UDTs,
FZY_Target_COUNT
}
FZY_Target;
typedef struct FZY_Params FZY_Params;
struct FZY_Params
{
FZY_Target target;
DI_KeyArray dbgi_keys;
};
////////////////////////////////
//~ rjf: Cache Types
typedef struct FZY_Bucket FZY_Bucket;
struct FZY_Bucket
{
Arena *arena;
String8 query;
FZY_Params params;
U64 params_hash;
};
typedef struct FZY_Node FZY_Node;
struct FZY_Node
{
FZY_Node *next;
U128 key;
U64 touch_count;
U64 last_time_submitted_us;
FZY_Bucket buckets[3];
U64 gen;
U64 submit_gen;
FZY_ItemArray gen_items;
};
typedef struct FZY_Slot FZY_Slot;
struct FZY_Slot
{
FZY_Node *first;
FZY_Node *last;
};
typedef struct FZY_Stripe FZY_Stripe;
struct FZY_Stripe
{
Arena *arena;
OS_Handle rw_mutex;
OS_Handle cv;
};
////////////////////////////////
//~ rjf: Scoped Access Types
typedef struct FZY_Touch FZY_Touch;
struct FZY_Touch
{
FZY_Touch *next;
FZY_Node *node;
};
typedef struct FZY_Scope FZY_Scope;
struct FZY_Scope
{
FZY_Scope *next;
FZY_Touch *first_touch;
FZY_Touch *last_touch;
};
typedef struct FZY_TCTX FZY_TCTX;
struct FZY_TCTX
{
Arena *arena;
FZY_Scope *free_scope;
FZY_Touch *free_touch;
};
////////////////////////////////
//~ rjf: Shared State Types
typedef struct FZY_Thread FZY_Thread;
struct FZY_Thread
{
OS_Handle thread;
OS_Handle u2f_ring_mutex;
OS_Handle u2f_ring_cv;
U64 u2f_ring_size;
U8 *u2f_ring_base;
U64 u2f_ring_write_pos;
U64 u2f_ring_read_pos;
};
typedef struct FZY_Shared FZY_Shared;
struct FZY_Shared
{
Arena *arena;
// rjf: search artifact cache table
U64 slots_count;
U64 stripes_count;
FZY_Slot *slots;
FZY_Stripe *stripes;
// rjf: threads
U64 thread_count;
FZY_Thread *threads;
};
////////////////////////////////
//~ rjf: Globals
global FZY_Shared *fzy_shared = 0;
thread_static FZY_TCTX *fzy_tctx = 0;
////////////////////////////////
//~ rjf: Helpers
internal U64 fzy_hash_from_string(U64 seed, String8 string);
internal U64 fzy_hash_from_params(FZY_Params *params);
internal U64 fzy_item_num_from_array_element_idx__linear_search(FZY_ItemArray *array, U64 element_idx);
internal String8 fzy_item_string_from_rdi_target_element_idx(RDI_Parsed *rdi, FZY_Target target, U64 element_idx);
internal FZY_Params fzy_params_copy(Arena *arena, FZY_Params *src);
////////////////////////////////
//~ rjf: Main Layer Initialization
internal void fzy_init(void);
////////////////////////////////
//~ rjf: Scope Functions
internal FZY_Scope *fzy_scope_open(void);
internal void fzy_scope_close(FZY_Scope *scope);
internal void fzy_scope_touch_node__stripe_mutex_r_guarded(FZY_Scope *scope, FZY_Node *node);
////////////////////////////////
//~ rjf: Cache Lookup Functions
internal FZY_ItemArray fzy_items_from_key_params_query(FZY_Scope *scope, U128 key, FZY_Params *params, String8 query, U64 endt_us, B32 *stale_out);
////////////////////////////////
//~ rjf: Searcher Threads
internal B32 fzy_u2s_enqueue_req(U128 key, U64 endt_us);
internal void fzy_u2s_dequeue_req(Arena *arena, FZY_Thread *thread, U128 *key_out);
internal int fzy_qsort_compare_items(FZY_Item *a, FZY_Item *b);
internal void fzy_search_thread__entry_point(void *p);
#endif // FUZZY_SEARCH_H
@@ -4,11 +4,11 @@
////////////////////////////////////////////////////////////////
// RAD Debug Info, (R)AD(D)BG(I) Format Library
//
// Defines standard RADDBGI debug information format types and
// Defines standard RDI debug information format types and
// functions.
#ifndef RADDBGI_FORMAT_H
#define RADDBGI_FORMAT_H
#ifndef RDI_FORMAT_H
#define RDI_FORMAT_H
////////////////////////////////////////////////////////////////
// Overridable procedure decoration
@@ -924,4 +924,4 @@ RDI_PROC RDI_EvalConversionKind rdi_eval_conversion_rule(RDI_EvalTypeGroup in, R
RDI_PROC RDI_U8* rdi_eval_conversion_message(RDI_EvalConversionKind conversion_kind, RDI_U64 *lennout);
RDI_PROC RDI_S32 rdi_eval_opcode_type_compatible(RDI_EvalOp op, RDI_EvalTypeGroup group);
#endif // RADDBGI_FORMAT_H
#endif // RDI_FORMAT_H
@@ -5,14 +5,14 @@
// RAD Debug Info Make, (R)AD(D)BG(I) (M)ake Library
//
// Library for building loose data structures which contain
// RADDBGI debug information, and baking that down into the
// proper flattened RADDBGI format.
// RDI debug information, and baking that down into the
// proper flattened RDI format.
//
// Requires prior inclusion of the RAD Debug Info, (R)AD(D)BG(I)
// Format Library, in raddbgi_format.h.
// Format Library, in rdi_format.h.
#ifndef RADDBGI_MAKE_H
#define RADDBGI_MAKE_H
#ifndef RDI_MAKE_H
#define RDI_MAKE_H
////////////////////////////////
//~ rjf: Overrideable Memory Operations
@@ -1252,4 +1252,4 @@ RDI_PROC RDIM_BakeSectionList rdim_bake_idx_run_section_list_from_idx_run_map(RD
RDI_PROC RDIM_String8List rdim_serialized_strings_from_params_bake_section_list(RDIM_Arena *arena, RDIM_BakeParams *params, RDIM_BakeSectionList *sections);
#endif // RADDBGI_MAKE_H
#endif // RDI_MAKE_H
+1
View File
@@ -39,4 +39,5 @@ dll_type_eval_tests(void)
Basics basics2 = {4, 5, 6, 7};
int x = 0;
(void)x;
*(int *)0 = 0;
}
+61
View File
@@ -0,0 +1,61 @@
#include <windows.h>
#include <winternl.h>
#include "mule_peb_trample_reload.c"
static void
HideModuleFromWindowsReload(HMODULE ModuleToFlush)
{
/* NOTE(casey): Normally you cannot "reload" an executable module with the same name,
because Windows checks a linked list of loaded modules and assumes that if
it's already loaded, it doesn't need to reload it, even though it may have to because
it has changed on disk.
This solution to that problem comes from some excellent spelunking by Martins Mozeiko,
who figured out that you could overwrite the filenames Windows stores in your process's
loaded module table, thus thwarting the Windows filename check against loaded modules,
allowing you to reload an existing module that has changed without requiring it to
have a different filename!
*/
PEB *Peb = (PEB *)__readgsqword(offsetof(TEB, ProcessEnvironmentBlock));
LIST_ENTRY *Head = &Peb->Ldr->InMemoryOrderModuleList;
for(LIST_ENTRY *Entry = Head->Flink;
Entry != Head;
Entry = Entry->Flink)
{
LDR_DATA_TABLE_ENTRY *Mod = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
if(Mod->DllBase == ModuleToFlush)
{
ZeroMemory(Mod->FullDllName.Buffer, Mod->FullDllName.Length);
Mod->DllBase = 0;
break;
}
}
}
int main(int argument_count, char **arguments)
{
char *exe_name = arguments[0];
HANDLE last_module = GetModuleHandle(0);
int (*loop_iteration_function)(int it) = (int (*)(int))GetProcAddress(last_module, "loop_iteration");
FILETIME last_filetime = {0};
int should_exit = 0;
for(int it = 0; !should_exit; it += 1)
{
int result = loop_iteration_function(it);
printf("%i\n", result);
Sleep(50);
FILETIME current_filetime = {0};
HANDLE current_exe_file = CreateFile(exe_name, 0, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
GetFileTime(current_exe_file, 0, 0, &current_filetime);
CloseHandle(current_exe_file);
if(it != 0 && CompareFileTime(&last_filetime, &current_filetime) < 0)
{
HideModuleFromWindowsReload(last_module);
last_module = LoadLibrary(arguments[0]);
loop_iteration_function = (int (*)(int))GetProcAddress(last_module, "loop_iteration");
}
last_filetime = current_filetime;
}
return 0;
}
+13
View File
@@ -0,0 +1,13 @@
__declspec(dllexport) int
loop_iteration(int it)
{
return 111;
#if 0
int sum = 0;
for(int i = 0; i < 1000; i += 1)
{
sum += it*i;
}
return sum;
#endif
}
+1 -1
View File
@@ -1607,7 +1607,7 @@ os_semaphore_close(OS_Handle semaphore)
}
internal B32
os_semaphore_take(OS_Handle semaphore)
os_semaphore_take(OS_Handle semaphore, U64 endt_us)
{
NotImplemented;
return 0;
+6 -6
View File
@@ -771,12 +771,6 @@ w32_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
result = HTCAPTION;
}
// rjf: title bar client area
if(is_over_title_bar_client_area)
{
result = HTCLIENT;
}
// rjf: normal edges
if(is_over_left) { result = HTLEFT; }
if(is_over_right) { result = HTRIGHT; }
@@ -788,6 +782,12 @@ w32_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
if(is_over_left && is_over_bottom) { result = HTBOTTOMLEFT; }
if(is_over_right && is_over_top) { result = HTTOPRIGHT; }
if(is_over_right && is_over_bottom) { result = HTBOTTOMRIGHT; }
// rjf: title bar client area
if(is_over_title_bar_client_area)
{
result = HTCLIENT;
}
}
}
}break;
+2 -3
View File
@@ -69,11 +69,10 @@ pe_bin_info_from_data(Arena *arena, String8 data)
}
// rjf: read pe magic
U32 coff_off = dos_header.coff_file_offset;
U32 pe_magic = 0;
if(valid)
{
str8_deserial_read_struct(data, coff_off, &pe_magic);
str8_deserial_read_struct(data, dos_header.coff_file_offset, &pe_magic);
}
// rjf: bad pe magic -> abort
@@ -83,7 +82,7 @@ pe_bin_info_from_data(Arena *arena, String8 data)
}
// rjf: read coff header
U32 coff_header_off = coff_off + sizeof(pe_magic);
U32 coff_header_off = dos_header.coff_file_offset + sizeof(pe_magic);
COFF_Header coff_header = {0};
if(valid)
{
+1 -1
View File
@@ -393,7 +393,7 @@ update_and_render(OS_Handle repaint_window_handle, void *user_data)
ProfEnd();
}
internal CTRL_WAKEUP_FUNCTION_DEF(wakeup_hook)
internal CTRL_WAKEUP_FUNCTION_DEF(wakeup_hook_ctrl)
{
os_send_wakeup_event();
}
+22 -14
View File
@@ -37,13 +37,8 @@
////////////////////////////////
//~ rjf: Hot, High Priority Tasks (Complete Unusability, Crashes, Fire-Worthy)
//
// [ ] robustify dbgi layer to renames (cache should not be based only on
// path - must invalidate naturally when new filetime occurs)
//
// [ ] raddbg jai.exe my_file.jai -- foobar -> raddbg consumes `--` incorrectly
// [ ] PDB files distributed with the build are not found by DbgHelp!!!
// [ ] Jai compiler debugging crash
// [ ] raddbgi file regeneration too strict
//
// [ ] Jump table thunks, on code w/o /INCREMENTAL:NO
//
@@ -52,15 +47,10 @@
// since that's not normally how Windows fonts work.
////////////////////////////////
//~ rjf: Demon/Cleanup Pass Tasks
//~ rjf: Hot, Medium Priority Tasks (Low-Hanging-Fruit Features, UI Jank, Cleanup)
//
// [ ] TLS eval -> in-process-memory EXE info
// [ ] unwinding -> in-process-memory EXE info
// [ ] "root" concept in hash store, which buckets keys & allows usage code to
// jettison a collection of keys in retained mode fashion
////////////////////////////////
//~ rjf: Hot, Medium Priority Tasks (Low-Hanging-Fruit Features, UI Jank, Cleanup)
//
// [ ] Jeff Notes
// [ ] highlighted text & ctrl+f -> auto-fill search query
@@ -379,6 +369,13 @@
// function was displayed in the window by default next to the thread.
// [x] ** It would be nice if thread listings displayed the name of the
// thread, instead of just the ID.
// [x] TLS eval -> in-process-memory EXE info
// [x] unwinding -> in-process-memory EXE info
// [x] new fuzzy searching layer
// [x] robustify dbgi layer to renames (cache should not be based only on
// path - must invalidate naturally when new filetime occurs)
// [x] rdi file regeneration too strict
// [x] raddbg jai.exe my_file.jai -- foobar -> raddbg consumes `--` incorrectly
#ifndef RADDBG_H
#define RADDBG_H
@@ -404,12 +401,23 @@ struct IPCInfo
////////////////////////////////
//~ rjf: Globals
#define IPC_SHARED_MEMORY_BUFFER_SIZE MB(16)
//- rjf: IPC resources
#define IPC_SHARED_MEMORY_BUFFER_SIZE MB(4)
StaticAssert(IPC_SHARED_MEMORY_BUFFER_SIZE > sizeof(IPCInfo), ipc_buffer_size_requirement);
read_only global String8 ipc_shared_memory_name = str8_lit_comp("_raddbg_ipc_shared_memory_");
read_only global String8 ipc_semaphore_name = str8_lit_comp("_raddbg_ipc_semaphore_");
global OS_Handle ipc_signal_semaphore = {0};
global OS_Handle ipc_lock_semaphore = {0};
global U8 *ipc_shared_memory_base = 0;
global U8 ipc_s2m_ring_buffer[MB(4)] = {0};
global U64 ipc_s2m_ring_write_pos = 0;
global U64 ipc_s2m_ring_read_pos = 0;
global OS_Handle ipc_s2m_ring_mutex = {0};
global OS_Handle ipc_s2m_ring_cv = {0};
//- rjf: frame time history
global U64 frame_time_us_history[64] = {0};
global U64 frame_time_us_history_idx = 0;
//- rjf: main thread log
global Log *main_thread_log = 0;
global String8 main_thread_log_path = {0};
+198 -74
View File
@@ -11,14 +11,21 @@
#define BUILD_TITLE "The RAD Debugger"
#define OS_FEATURE_GRAPHICAL 1
#define R_INIT_MANUAL 1
#define TEX_INIT_MANUAL 1
#define GEO_INIT_MANUAL 1
#define F_INIT_MANUAL 1
#define DF_INIT_MANUAL 1
#define DF_GFX_INIT_MANUAL 1
////////////////////////////////
//~ rjf: Includes
//- rjf: [lib]
#include "lib_raddbgi_format/raddbgi_format.h"
#include "lib_raddbgi_format/raddbgi_format.c"
#include "lib_raddbgi_format/raddbgi_format_parse.h"
#include "lib_raddbgi_format/raddbgi_format_parse.c"
#include "lib_rdi_format/rdi_format.h"
#include "lib_rdi_format/rdi_format.c"
#include "lib_rdi_format/rdi_format_parse.h"
#include "lib_rdi_format/rdi_format_parse.c"
#include "third_party/rad_lzb_simple/rad_lzb_simple.h"
#include "third_party/rad_lzb_simple/rad_lzb_simple.c"
@@ -27,12 +34,11 @@
#include "os/os_inc.h"
#include "task_system/task_system.h"
#include "ico/ico.h"
#include "raddbgi_make_local/raddbgi_make_local.h"
#include "rdi_make_local/rdi_make_local.h"
#include "mdesk/mdesk.h"
#include "hash_store/hash_store.h"
#include "file_stream/file_stream.h"
#include "text_cache/text_cache.h"
#include "dasm_cache/dasm_cache.h"
#include "path/path.h"
#include "txti/txti.h"
#include "coff/coff.h"
@@ -42,14 +48,15 @@
#include "msf/msf.h"
#include "pdb/pdb.h"
#include "pdb/pdb_stringize.h"
#include "raddbgi_from_pdb/raddbgi_from_pdb.h"
#include "rdi_from_pdb/rdi_from_pdb.h"
#include "regs/regs.h"
#include "regs/raddbgi/regs_raddbgi.h"
#include "regs/rdi/regs_rdi.h"
#include "type_graph/type_graph.h"
#include "dbgi/dbgi.h"
#include "dasm_cache/dasm_cache.h"
#include "fuzzy_search/fuzzy_search.h"
#include "demon/demon_inc.h"
#include "eval/eval_inc.h"
#include "unwind/unwind.h"
#include "ctrl/ctrl_inc.h"
#include "font_provider/font_provider_inc.h"
#include "render/render_inc.h"
@@ -66,12 +73,11 @@
#include "os/os_inc.c"
#include "task_system/task_system.c"
#include "ico/ico.c"
#include "raddbgi_make_local/raddbgi_make_local.c"
#include "rdi_make_local/rdi_make_local.c"
#include "mdesk/mdesk.c"
#include "hash_store/hash_store.c"
#include "file_stream/file_stream.c"
#include "text_cache/text_cache.c"
#include "dasm_cache/dasm_cache.c"
#include "path/path.c"
#include "txti/txti.c"
#include "coff/coff.c"
@@ -81,14 +87,15 @@
#include "msf/msf.c"
#include "pdb/pdb.c"
#include "pdb/pdb_stringize.c"
#include "raddbgi_from_pdb/raddbgi_from_pdb.c"
#include "rdi_from_pdb/rdi_from_pdb.c"
#include "regs/regs.c"
#include "regs/raddbgi/regs_raddbgi.c"
#include "regs/rdi/regs_rdi.c"
#include "type_graph/type_graph.c"
#include "dbgi/dbgi.c"
#include "dasm_cache/dasm_cache.c"
#include "fuzzy_search/fuzzy_search.c"
#include "demon/demon_inc.c"
#include "eval/eval_inc.c"
#include "unwind/unwind.c"
#include "ctrl/ctrl_inc.c"
#include "font_provider/font_provider_inc.c"
#include "render/render_inc.c"
@@ -100,6 +107,42 @@
#include "df/df_inc.c"
#include "raddbg.c"
////////////////////////////////
//~ rjf: IPC Signaler Thread
internal void
ipc_signaler_thread__entry_point(void *p)
{
for(;;)
{
if(os_semaphore_take(ipc_signal_semaphore, max_U64))
{
if(os_semaphore_take(ipc_lock_semaphore, max_U64))
{
IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base;
String8 msg = str8((U8 *)(ipc_info+1), ipc_info->msg_size);
msg.size = Min(msg.size, IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo));
OS_MutexScope(ipc_s2m_ring_mutex) for(;;)
{
U64 unconsumed_size = ipc_s2m_ring_write_pos - ipc_s2m_ring_read_pos;
U64 available_size = (sizeof(ipc_s2m_ring_buffer) - unconsumed_size);
if(available_size >= sizeof(U64)+sizeof(msg.size))
{
ipc_s2m_ring_write_pos += ring_write_struct(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_write_pos, &msg.size);
ipc_s2m_ring_write_pos += ring_write(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_write_pos, msg.str, msg.size);
break;
}
os_condition_variable_wait(ipc_s2m_ring_cv, ipc_s2m_ring_mutex, max_U64);
}
os_condition_variable_broadcast(ipc_s2m_ring_cv);
os_send_wakeup_event();
ipc_info->msg_size = 0;
os_semaphore_drop(ipc_lock_semaphore);
}
}
}
}
////////////////////////////////
//~ rjf: Entry Point
@@ -178,7 +221,7 @@ entry_point(CmdLine *cmd_line)
}
//- rjf: set up layers
ctrl_set_wakeup_hook(wakeup_hook);
ctrl_set_wakeup_hook(wakeup_hook_ctrl);
//- rjf: dispatch to top-level codepath based on execution mode
switch(exec_mode)
@@ -187,12 +230,16 @@ entry_point(CmdLine *cmd_line)
default:
case ExecMode_Normal:
{
//- rjf: set up shared memory for ipc
OS_Handle ipc_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_shared_memory_name);
void *ipc_shared_memory_base = os_shared_memory_view_open(ipc_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE));
OS_Handle ipc_semaphore = os_semaphore_alloc(1, 1, ipc_semaphore_name);
IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base;
ipc_info->msg_size = 0;
//- rjf: manual layer initialization
{
r_init(cmd_line);
tex_init();
geo_init();
f_init();
DF_StateDeltaHistory *hist = df_state_delta_history_alloc();
df_core_init(cmd_line, hist);
df_gfx_init(update_and_render, df_state_delta_history());
}
//- rjf: setup initial target from command line args
{
@@ -247,56 +294,97 @@ entry_point(CmdLine *cmd_line)
}
}
//- rjf: set up shared resources for ipc to this instance; launch IPC signaler thread
{
Temp scratch = scratch_begin(0, 0);
U32 instance_pid = os_get_pid();
String8 ipc_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_shared_memory_%i_", instance_pid);
String8 ipc_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_signal_semaphore_%i_", instance_pid);
String8 ipc_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_lock_semaphore_%i_", instance_pid);
OS_Handle ipc_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_shared_memory_name);
ipc_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE));
ipc_signal_semaphore = os_semaphore_alloc(0, 1, ipc_signal_semaphore_name);
ipc_lock_semaphore = os_semaphore_alloc(1, 1, ipc_lock_semaphore_name);
ipc_s2m_ring_mutex = os_mutex_alloc();
ipc_s2m_ring_cv = os_condition_variable_alloc();
IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base;
MemoryZeroStruct(ipc_info);
os_launch_thread(ipc_signaler_thread__entry_point, 0, 0);
scratch_end(scratch);
}
//- rjf: main application loop
{
for(;;)
{
//- rjf: get IPC messages & dispatch ui commands from them
//- rjf: consume IPC messages, dispatch UI commands
{
if(os_semaphore_take(ipc_semaphore, max_U64))
Temp scratch = scratch_begin(0, 0);
B32 consumed = 0;
String8 msg = {0};
OS_MutexScope(ipc_s2m_ring_mutex)
{
if(ipc_info->msg_size != 0)
U64 unconsumed_size = ipc_s2m_ring_write_pos - ipc_s2m_ring_read_pos;
if(unconsumed_size >= sizeof(U64))
{
U8 *buffer = (U8 *)(ipc_info+1);
U64 msg_size = ipc_info->msg_size;
String8 cmd_string = str8(buffer, msg_size);
ipc_info->msg_size = 0;
DF_Window *dst_window = df_gfx_state->first_window;
for(DF_Window *window = dst_window; window != 0; window = window->next)
consumed = 1;
ipc_s2m_ring_read_pos += ring_read_struct(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_read_pos, &msg.size);
msg.size = Min(msg.size, unconsumed_size);
msg.str = push_array(scratch.arena, U8, msg.size);
ipc_s2m_ring_read_pos += ring_read(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_read_pos, msg.str, msg.size);
}
}
if(consumed)
{
os_condition_variable_broadcast(ipc_s2m_ring_cv);
}
if(msg.size != 0)
{
log_infof("IPC message received: \"%S\"", msg);
DF_Window *dst_window = df_gfx_state->first_window;
for(DF_Window *window = dst_window; window != 0; window = window->next)
{
if(os_window_is_focused(window->os))
{
if(os_window_is_focused(window->os))
{
dst_window = window;
break;
}
}
if(dst_window != 0)
{
Temp scratch = scratch_begin(0, 0);
String8 cmd_spec_string = df_cmd_name_part_from_string(cmd_string);
DF_CmdSpec *cmd_spec = df_cmd_spec_from_string(cmd_spec_string);
if(!df_cmd_spec_is_nil(cmd_spec))
{
DF_CmdParams params = df_cmd_params_from_gfx();
DF_CtrlCtx ctrl_ctx = df_ctrl_ctx_from_window(dst_window);
String8 error = df_cmd_params_apply_spec_query(scratch.arena, &ctrl_ctx, &params, cmd_spec, df_cmd_arg_part_from_string(cmd_string));
if(error.size == 0)
{
df_push_cmd__root(&params, cmd_spec);
}
else
{
DF_CmdParams params = df_cmd_params_from_window(dst_window);
params.string = error;
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_String);
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Error));
}
}
scratch_end(scratch);
dst_window = window;
break;
}
}
if(dst_window != 0)
{
dst_window->window_temporarily_focused_ipc = 1;
String8 cmd_spec_string = df_cmd_name_part_from_string(msg);
DF_CmdSpec *cmd_spec = df_cmd_spec_from_string(cmd_spec_string);
if(!df_cmd_spec_is_nil(cmd_spec))
{
DF_CmdParams params = df_cmd_params_from_window(dst_window);
DF_CtrlCtx ctrl_ctx = df_ctrl_ctx_from_window(dst_window);
String8 error = df_cmd_params_apply_spec_query(scratch.arena, &ctrl_ctx, &params, cmd_spec, df_cmd_arg_part_from_string(msg));
if(error.size == 0)
{
df_push_cmd__root(&params, cmd_spec);
df_gfx_request_frame();
}
else
{
DF_CmdParams params = df_cmd_params_from_window(dst_window);
params.string = error;
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_String);
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Error));
df_gfx_request_frame();
}
}
else
{
DF_CmdParams params = df_cmd_params_from_window(dst_window);
params.string = push_str8f(scratch.arena, "\"%S\" is not a command.", cmd_spec_string);
df_cmd_params_mark_slot(&params, DF_CmdParamSlot_String);
df_push_cmd__root(&params, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Error));
df_gfx_request_frame();
}
}
os_semaphore_drop(ipc_semaphore);
}
scratch_end(scratch);
}
//- rjf: update & render frame
@@ -344,25 +432,61 @@ entry_point(CmdLine *cmd_line)
{
Temp scratch = scratch_begin(0, 0);
//- rjf: grab ipc shared memory
OS_Handle ipc_shared_memory = os_shared_memory_open(ipc_shared_memory_name);
void *ipc_shared_memory_base = os_shared_memory_view_open(ipc_shared_memory, r1u64(0, MB(16)));
if(ipc_shared_memory_base != 0)
//- rjf: grab explicit PID argument
U32 dst_pid = 0;
if(cmd_line_has_argument(cmd_line, str8_lit("pid")))
{
OS_Handle ipc_semaphore = os_semaphore_open(ipc_semaphore_name);
IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base;
if(os_semaphore_take(ipc_semaphore, os_now_microseconds() + Million(6)))
String8 dst_pid_string = cmd_line_string(cmd_line, str8_lit("pid"));
U64 dst_pid_u64 = 0;
if(dst_pid_string.size != 0 &&
try_u64_from_str8_c_rules(dst_pid_string, &dst_pid_u64))
{
U8 *buffer = (U8 *)(ipc_info+1);
U64 buffer_max = IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo);
StringJoin join = {str8_lit(""), str8_lit(" "), str8_lit("")};
String8 msg = str8_list_join(scratch.arena, &cmd_line->inputs, &join);
ipc_info->msg_size = Min(buffer_max, msg.size);
MemoryCopy(buffer, msg.str, ipc_info->msg_size);
os_semaphore_drop(ipc_semaphore);
dst_pid = (U32)dst_pid_u64;
}
}
//- rjf: no explicit PID? -> find PID to send message to, by looking for other raddbg instances
if(dst_pid == 0)
{
U32 this_pid = os_get_pid();
DMN_ProcessIter it = {0};
dmn_process_iter_begin(&it);
for(DMN_ProcessInfo info = {0}; dmn_process_iter_next(scratch.arena, &it, &info);)
{
if(str8_match(str8_skip_last_slash(str8_chop_last_dot(cmd_line->exe_name)), str8_skip_last_slash(str8_chop_last_dot(info.name)), StringMatchFlag_CaseInsensitive) &&
this_pid != info.pid)
{
dst_pid = info.pid;
break;
}
}
dmn_process_iter_end(&it);
}
//- rjf: grab destination instance's shared memory resources
String8 ipc_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_shared_memory_%i_", dst_pid);
String8 ipc_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_signal_semaphore_%i_", dst_pid);
String8 ipc_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_lock_semaphore_%i_", dst_pid);
OS_Handle ipc_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_shared_memory_name);
ipc_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE));
ipc_signal_semaphore = os_semaphore_alloc(0, 1, ipc_signal_semaphore_name);
ipc_lock_semaphore = os_semaphore_alloc(1, 1, ipc_lock_semaphore_name);
//- rjf: got resources -> write message
if(ipc_shared_memory_base != 0 &&
os_semaphore_take(ipc_lock_semaphore, max_U64))
{
IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base;
U8 *buffer = (U8 *)(ipc_info+1);
U64 buffer_max = IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo);
StringJoin join = {str8_lit(""), str8_lit(" "), str8_lit("")};
String8 msg = str8_list_join(scratch.arena, &cmd_line->inputs, &join);
ipc_info->msg_size = Min(buffer_max, msg.size);
MemoryCopy(buffer, msg.str, ipc_info->msg_size);
os_semaphore_drop(ipc_signal_semaphore);
os_semaphore_drop(ipc_lock_semaphore);
}
scratch_end(scratch);
}break;
@@ -5,17 +5,17 @@
#define BUILD_VERSION_MINOR 9
#define BUILD_VERSION_PATCH 10
#define BUILD_RELEASE_PHASE_STRING_LITERAL "ALPHA"
#define BUILD_TITLE "raddbgi_breakpad_from_pdb"
#define BUILD_TITLE "rdi_breakpad_from_pdb"
#define BUILD_CONSOLE_INTERFACE 1
////////////////////////////////
//~ rjf: Includes
//- rjf: [lib]
#include "lib_raddbgi_format/raddbgi_format.h"
#include "lib_raddbgi_format/raddbgi_format_parse.h"
#include "lib_raddbgi_format/raddbgi_format.c"
#include "lib_raddbgi_format/raddbgi_format_parse.c"
#include "lib_rdi_format/rdi_format.h"
#include "lib_rdi_format/rdi_format_parse.h"
#include "lib_rdi_format/rdi_format.c"
#include "lib_rdi_format/rdi_format_parse.c"
#include "third_party/rad_lzb_simple/rad_lzb_simple.h"
#include "third_party/rad_lzb_simple/rad_lzb_simple.c"
@@ -24,27 +24,27 @@
#include "base/base_inc.h"
#include "os/os_inc.h"
#include "task_system/task_system.h"
#include "raddbgi_make_local/raddbgi_make_local.h"
#include "rdi_make_local/rdi_make_local.h"
#include "coff/coff.h"
#include "codeview/codeview.h"
#include "codeview/codeview_stringize.h"
#include "msf/msf.h"
#include "pdb/pdb.h"
#include "pdb/pdb_stringize.h"
#include "raddbgi_from_pdb/raddbgi_from_pdb.h"
#include "rdi_from_pdb/rdi_from_pdb.h"
//- rjf: [c]
#include "base/base_inc.c"
#include "os/os_inc.c"
#include "task_system/task_system.c"
#include "raddbgi_make_local/raddbgi_make_local.c"
#include "rdi_make_local/rdi_make_local.c"
#include "coff/coff.c"
#include "codeview/codeview.c"
#include "codeview/codeview_stringize.c"
#include "msf/msf.c"
#include "pdb/pdb.c"
#include "pdb/pdb_stringize.c"
#include "raddbgi_from_pdb/raddbgi_from_pdb.c"
#include "rdi_from_pdb/rdi_from_pdb.c"
////////////////////////////////
//~ rjf: Baking Tasks
@@ -209,7 +209,7 @@ entry_point(CmdLine *cmdline)
//- rjf: display help
if(do_help || user2convert->errors.node_count != 0)
{
fprintf(stderr, "--- raddbgi_breakpad_from_pdb -------------------------------------------------\n\n");
fprintf(stderr, "--- rdi_breakpad_from_pdb -----------------------------------------------------\n\n");
fprintf(stderr, "This utility converts debug information from PDBs into the textual Breakpad\n");
fprintf(stderr, "symbol information format, used for various external utilities, using the RAD\n");
@@ -2,7 +2,7 @@
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: RADDBGI Enum -> String Functions
//~ rjf: RDI Enum -> String Functions
internal String8
rdi_string_from_data_section_tag(RDI_DataSectionTag tag){
@@ -79,7 +79,7 @@ rdi_string_from_local_kind(RDI_LocalKind local_kind){
}
////////////////////////////////
//~ rjf: RADDBGI Flags -> String Functions
//~ rjf: RDI Flags -> String Functions
internal void
rdi_stringize_binary_section_flags(Arena *arena, String8List *out,
@@ -1,8 +1,8 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef RADDBGI_DUMP_H
#define RADDBGI_DUMP_H
#ifndef RDI_DUMP_H
#define RDI_DUMP_H
////////////////////////////////
//~ rjf: RADDBG Stringize Helper Types
@@ -39,7 +39,7 @@ struct RDI_ScopeBundle
};
////////////////////////////////
//~ rjf: RADDBGI Enum -> String Functions
//~ rjf: RDI Enum -> String Functions
internal String8 rdi_string_from_data_section_tag(RDI_DataSectionTag tag);
internal String8 rdi_string_from_arch(RDI_Arch arch);
@@ -49,7 +49,7 @@ internal String8 rdi_string_from_member_kind(RDI_MemberKind member_kind);
internal String8 rdi_string_from_local_kind(RDI_LocalKind local_kind);
////////////////////////////////
//~ rjf: RADDBGI Flags -> String Functions
//~ rjf: RDI Flags -> String Functions
internal void rdi_stringize_binary_section_flags(Arena *arena, String8List *out, RDI_BinarySectionFlags flags);
internal void rdi_stringize_type_modifier_flags(Arena *arena, String8List *out, RDI_TypeModifierFlags flags);
@@ -57,7 +57,7 @@ internal void rdi_stringize_user_defined_type_flags(Arena *arena, String8List *o
internal void rdi_stringize_link_flags(Arena *arena, String8List *out, RDI_LinkFlags flags);
////////////////////////////////
//~ rjf: RADDBG Compound Stringize Functions
//~ rjf: RDI Compound Stringize Functions
internal void rdi_stringize_data_sections(Arena *arena, String8List *out, RDI_Parsed *parsed, U32 indent_level);
internal void rdi_stringize_top_level_info(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_TopLevelInfo *tli, U32 indent_level);
@@ -72,4 +72,4 @@ internal void rdi_stringize_thread_variable(Arena *arena, String8List *out, RDI_
internal void rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_Procedure *proc, U32 indent_level);
internal void rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_ScopeBundle *bundle, RDI_Scope *scope, U32 indent_level);
#endif // RADDBGI_DUMP_H
#endif // RDI_DUMP_H
@@ -8,27 +8,33 @@
#define BUILD_VERSION_MINOR 9
#define BUILD_VERSION_PATCH 10
#define BUILD_RELEASE_PHASE_STRING_LITERAL "ALPHA"
#define BUILD_TITLE "raddbgi_dump"
#define BUILD_TITLE "rdi_dump"
#define BUILD_CONSOLE_INTERFACE 1
////////////////////////////////
//~ rjf: Includes
//- rjf: [lib]
#include "lib_raddbgi_format/raddbgi_format.h"
#include "lib_raddbgi_format/raddbgi_format_parse.h"
#include "lib_raddbgi_format/raddbgi_format.c"
#include "lib_raddbgi_format/raddbgi_format_parse.c"
#include "lib_rdi_format/rdi_format.h"
#include "lib_rdi_format/rdi_format_parse.h"
#include "lib_rdi_format/rdi_format.c"
#include "lib_rdi_format/rdi_format_parse.c"
#include "third_party/rad_lzb_simple/rad_lzb_simple.h"
#include "third_party/rad_lzb_simple/rad_lzb_simple.c"
//- rjf: [h]
#include "base/base_inc.h"
#include "os/os_inc.h"
#include "raddbgi_dump.h"
#include "path/path.h"
#include "dbgi/dbgi.h"
#include "rdi_dump.h"
//- rjf: [c]
#include "base/base_inc.c"
#include "os/os_inc.c"
#include "raddbgi_dump.c"
#include "path/path.c"
#include "dbgi/dbgi.c"
#include "rdi_dump.c"
////////////////////////////////
//~ rjf: Entry Point
@@ -40,6 +46,7 @@ entry_point(CmdLine *cmd_line)
//- rjf: set up
//
Arena *arena = arena_alloc();
DI_Scope *di_scope = di_scope_open();
String8List errors = {0};
//////////////////////////////
@@ -70,11 +77,8 @@ entry_point(CmdLine *cmd_line)
String8 input_data = {0};
DumpFlags dump_flags = (U32)0xffffffff;
{
// rjf: extract input file path & load data
// rjf: extract input file path
input_name = str8_list_first(&cmd_line->inputs);
if(input_name.size > 0) { input_data = os_data_from_file_path(arena, input_name); }
else {str8_list_pushf(arena, &errors, "error (input): No input RADDBGI file specified.");}
if(input_name.size != 0 && input_data.size == 0) { str8_list_pushf(arena, &errors, "error (input): No input RADDBGI file successfully loaded; either the path or file contents are invalid."); }
// rjf: extract dump options
{
@@ -107,17 +111,22 @@ entry_point(CmdLine *cmd_line)
}
//////////////////////////////
//- rjf: parse raddbg from input data
//- rjf: obtain rdi parse
//
RDI_ParseStatus parse_status = RDI_ParseStatus_Good;
RDI_Parsed raddbg_ = {0};
RDI_Parsed *raddbg = &raddbg_;
RDI_Parsed *rdi = &di_rdi_parsed_nil;
if(input_name.size == 0)
{
parse_status = rdi_parse(input_data.str, input_data.size, &raddbg_);
if(parse_status != RDI_ParseStatus_Good)
{
str8_list_pushf(arena, &errors, "error (parse): RADDBGI file wasn't parsed successfully. (0x%x)", parse_status);
}
str8_list_pushf(arena, &errors, "error (input): No input RDI file specified.");
}
else
{
DI_Key key = {input_name};
di_open(&key);
rdi = di_rdi_from_key(di_scope, &key, max_U64);
}
if(rdi == &di_rdi_parsed_nil)
{
str8_list_pushf(arena, &errors, "error (input): No input RDI file successfully loaded; either the path or file contents are invalid.");
}
//////////////////////////////
@@ -133,13 +142,13 @@ entry_point(CmdLine *cmd_line)
//- rjf: build dump strings
//
String8List dump = {0};
if(parse_status == RDI_ParseStatus_Good)
if(rdi != &di_rdi_parsed_nil)
{
//- rjf: DATA SECTIONS
if(dump_flags & DumpFlag_DataSections)
{
str8_list_pushf(arena, &dump, "# DATA SECTIONS:\n");
rdi_stringize_data_sections(arena, &dump, raddbg, 1);
rdi_stringize_data_sections(arena, &dump, rdi, 1);
str8_list_push(arena, &dump, str8_lit("\n"));
}
@@ -147,7 +156,7 @@ entry_point(CmdLine *cmd_line)
if(dump_flags & DumpFlag_TopLevelInfo)
{
str8_list_pushf(arena, &dump, "# TOP LEVEL INFO:\n");
rdi_stringize_top_level_info(arena, &dump, raddbg, raddbg->top_level_info, 1);
rdi_stringize_top_level_info(arena, &dump, rdi, rdi->top_level_info, 1);
str8_list_push(arena, &dump, str8_lit("\n"));
}
@@ -155,11 +164,11 @@ entry_point(CmdLine *cmd_line)
if(dump_flags & DumpFlag_BinarySections)
{
str8_list_pushf(arena, &dump, "# BINARY SECTIONS:\n");
RDI_BinarySection *ptr = raddbg->binary_sections;
for(U32 i = 0; i < raddbg->binary_sections_count; i += 1, ptr += 1)
RDI_BinarySection *ptr = rdi->binary_sections;
for(U32 i = 0; i < rdi->binary_sections_count; i += 1, ptr += 1)
{
str8_list_pushf(arena, &dump, " section[%u]:\n", i);
rdi_stringize_binary_section(arena, &dump, raddbg, ptr, 2);
rdi_stringize_binary_section(arena, &dump, rdi, ptr, 2);
str8_list_push(arena, &dump, str8_lit("\n"));
}
str8_list_push(arena, &dump, str8_lit("\n"));
@@ -170,16 +179,16 @@ entry_point(CmdLine *cmd_line)
{
RDI_FilePathBundle file_path_bundle = {0};
{
file_path_bundle.file_paths = raddbg->file_paths;
file_path_bundle.file_path_count = raddbg->file_paths_count;
file_path_bundle.file_paths = rdi->file_paths;
file_path_bundle.file_path_count = rdi->file_paths_count;
}
str8_list_pushf(arena, &dump, "# FILE PATHS\n");
RDI_FilePathNode *ptr = raddbg->file_paths;
for(U32 i = 0; i < raddbg->file_paths_count; i += 1, ptr += 1)
RDI_FilePathNode *ptr = rdi->file_paths;
for(U32 i = 0; i < rdi->file_paths_count; i += 1, ptr += 1)
{
if(ptr->parent_path_node == 0)
{
rdi_stringize_file_path(arena, &dump, raddbg, &file_path_bundle, ptr, 1);
rdi_stringize_file_path(arena, &dump, rdi, &file_path_bundle, ptr, 1);
}
}
str8_list_push(arena, &dump, str8_lit("\n"));
@@ -189,11 +198,11 @@ entry_point(CmdLine *cmd_line)
if(dump_flags & DumpFlag_SourceFiles)
{
str8_list_pushf(arena, &dump, "# SOURCE FILES\n");
RDI_SourceFile *ptr = raddbg->source_files;
for(U32 i = 0; i < raddbg->source_files_count; i += 1, ptr += 1)
RDI_SourceFile *ptr = rdi->source_files;
for(U32 i = 0; i < rdi->source_files_count; i += 1, ptr += 1)
{
str8_list_pushf(arena, &dump, " source_file[%u]:\n", i);
rdi_stringize_source_file(arena, &dump, raddbg, ptr, 2);
rdi_stringize_source_file(arena, &dump, rdi, ptr, 2);
str8_list_push(arena, &dump, str8_lit("\n"));
}
str8_list_push(arena, &dump, str8_lit("\n"));
@@ -203,11 +212,11 @@ entry_point(CmdLine *cmd_line)
if(dump_flags & DumpFlag_Units)
{
str8_list_pushf(arena, &dump, "# UNITS\n");
RDI_Unit *ptr = raddbg->units;
for (U32 i = 0; i < raddbg->units_count; i += 1, ptr += 1)
RDI_Unit *ptr = rdi->units;
for (U32 i = 0; i < rdi->units_count; i += 1, ptr += 1)
{
str8_list_pushf(arena, &dump, " unit[%u]:\n", i);
rdi_stringize_unit(arena, &dump, raddbg, ptr, 2);
rdi_stringize_unit(arena, &dump, rdi, ptr, 2);
str8_list_push(arena, &dump, str8_lit("\n"));
}
str8_list_push(arena, &dump, str8_lit("\n"));
@@ -217,8 +226,8 @@ entry_point(CmdLine *cmd_line)
if(dump_flags & DumpFlag_UnitVMap)
{
str8_list_pushf(arena, &dump, "# UNIT VMAP\n");
RDI_VMapEntry *ptr = raddbg->unit_vmap;
for(U32 i = 0; i < raddbg->unit_vmap_count; i += 1, ptr += 1)
RDI_VMapEntry *ptr = rdi->unit_vmap;
for(U32 i = 0; i < rdi->unit_vmap_count; i += 1, ptr += 1)
{
str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", ptr->voff, ptr->idx);
}
@@ -229,11 +238,11 @@ entry_point(CmdLine *cmd_line)
if(dump_flags & DumpFlag_TypeNodes)
{
str8_list_pushf(arena, &dump, "# TYPE NODES:\n");
RDI_TypeNode *ptr = raddbg->type_nodes;
for(U32 i = 0; i < raddbg->type_nodes_count; i += 1, ptr += 1)
RDI_TypeNode *ptr = rdi->type_nodes;
for(U32 i = 0; i < rdi->type_nodes_count; i += 1, ptr += 1)
{
str8_list_pushf(arena, &dump, " type[%u]:\n", i);
rdi_stringize_type_node(arena, &dump, raddbg, ptr, 2);
rdi_stringize_type_node(arena, &dump, rdi, ptr, 2);
str8_list_push(arena, &dump, str8_lit("\n"));
}
str8_list_push(arena, &dump, str8_lit("\n"));
@@ -244,17 +253,17 @@ entry_point(CmdLine *cmd_line)
{
RDI_UDTMemberBundle member_bundle = {0};
{
member_bundle.members = raddbg->members;
member_bundle.enum_members = raddbg->enum_members;
member_bundle.member_count = raddbg->members_count;
member_bundle.enum_member_count = raddbg->enum_members_count;
member_bundle.members = rdi->members;
member_bundle.enum_members = rdi->enum_members;
member_bundle.member_count = rdi->members_count;
member_bundle.enum_member_count = rdi->enum_members_count;
}
str8_list_pushf(arena, &dump, "# UDTS:\n");
RDI_UDT *ptr = raddbg->udts;
for(U32 i = 0; i < raddbg->udts_count; i += 1, ptr += 1)
RDI_UDT *ptr = rdi->udts;
for(U32 i = 0; i < rdi->udts_count; i += 1, ptr += 1)
{
str8_list_pushf(arena, &dump, " udt[%u]:\n", i);
rdi_stringize_udt(arena, &dump, raddbg, &member_bundle, ptr, 2);
rdi_stringize_udt(arena, &dump, rdi, &member_bundle, ptr, 2);
str8_list_push(arena, &dump, str8_lit("\n"));
}
str8_list_push(arena, &dump, str8_lit("\n"));
@@ -264,11 +273,11 @@ entry_point(CmdLine *cmd_line)
if(dump_flags & DumpFlag_GlobalVariables)
{
str8_list_pushf(arena, &dump, "# GLOBAL VARIABLES:\n");
RDI_GlobalVariable *ptr = raddbg->global_variables;
for(U32 i = 0; i < raddbg->global_variables_count; i += 1, ptr += 1)
RDI_GlobalVariable *ptr = rdi->global_variables;
for(U32 i = 0; i < rdi->global_variables_count; i += 1, ptr += 1)
{
str8_list_pushf(arena, &dump, " global_variable[%u]:\n", i);
rdi_stringize_global_variable(arena, &dump, raddbg, ptr, 2);
rdi_stringize_global_variable(arena, &dump, rdi, ptr, 2);
str8_list_push(arena, &dump, str8_lit("\n"));
}
str8_list_push(arena, &dump, str8_lit("\n"));
@@ -278,8 +287,8 @@ entry_point(CmdLine *cmd_line)
if(dump_flags & DumpFlag_GlobalVMap)
{
str8_list_pushf(arena, &dump, "# GLOBAL VMAP:\n");
RDI_VMapEntry *ptr = raddbg->global_vmap;
for(U32 i = 0; i < raddbg->global_vmap_count; i += 1, ptr += 1)
RDI_VMapEntry *ptr = rdi->global_vmap;
for(U32 i = 0; i < rdi->global_vmap_count; i += 1, ptr += 1)
{
str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", ptr->voff, ptr->idx);
}
@@ -290,11 +299,11 @@ entry_point(CmdLine *cmd_line)
if(dump_flags & DumpFlag_ThreadVariables)
{
str8_list_pushf(arena, &dump, "# THREAD VARIABLES:\n");
RDI_ThreadVariable *ptr = raddbg->thread_variables;
for(U32 i = 0; i < raddbg->thread_variables_count; i += 1, ptr += 1)
RDI_ThreadVariable *ptr = rdi->thread_variables;
for(U32 i = 0; i < rdi->thread_variables_count; i += 1, ptr += 1)
{
str8_list_pushf(arena, &dump, " thread_variable[%u]:\n", i);
rdi_stringize_thread_variable(arena, &dump, raddbg, ptr, 2);
rdi_stringize_thread_variable(arena, &dump, rdi, ptr, 2);
str8_list_push(arena, &dump, str8_lit("\n"));
}
str8_list_push(arena, &dump, str8_lit("\n"));
@@ -304,11 +313,11 @@ entry_point(CmdLine *cmd_line)
if(dump_flags & DumpFlag_Procedures)
{
str8_list_pushf(arena, &dump, "# PROCEDURES:\n");
RDI_Procedure *ptr = raddbg->procedures;
for(U32 i = 0; i < raddbg->procedures_count; i += 1, ptr += 1)
RDI_Procedure *ptr = rdi->procedures;
for(U32 i = 0; i < rdi->procedures_count; i += 1, ptr += 1)
{
str8_list_pushf(arena, &dump, " procedure[%u]:\n", i);
rdi_stringize_procedure(arena, &dump, raddbg, ptr, 2);
rdi_stringize_procedure(arena, &dump, rdi, ptr, 2);
str8_list_push(arena, &dump, str8_lit("\n"));
}
str8_list_push(arena, &dump, str8_lit("\n"));
@@ -319,24 +328,24 @@ entry_point(CmdLine *cmd_line)
{
RDI_ScopeBundle scope_bundle = {0};
{
scope_bundle.scopes = raddbg->scopes;
scope_bundle.scope_count = raddbg->scopes_count;
scope_bundle.scope_voffs = raddbg->scope_voffs;
scope_bundle.scope_voff_count = raddbg->scope_voffs_count;
scope_bundle.locals = raddbg->locals;
scope_bundle.local_count = raddbg->locals_count;
scope_bundle.location_blocks = raddbg->location_blocks;
scope_bundle.location_block_count = raddbg->location_blocks_count;
scope_bundle.location_data = raddbg->location_data;
scope_bundle.location_data_size = raddbg->location_data_size;
scope_bundle.scopes = rdi->scopes;
scope_bundle.scope_count = rdi->scopes_count;
scope_bundle.scope_voffs = rdi->scope_voffs;
scope_bundle.scope_voff_count = rdi->scope_voffs_count;
scope_bundle.locals = rdi->locals;
scope_bundle.local_count = rdi->locals_count;
scope_bundle.location_blocks = rdi->location_blocks;
scope_bundle.location_block_count = rdi->location_blocks_count;
scope_bundle.location_data = rdi->location_data;
scope_bundle.location_data_size = rdi->location_data_size;
}
str8_list_pushf(arena, &dump, "# SCOPES:\n");
RDI_Scope *ptr = raddbg->scopes;
for(U32 i = 0; i < raddbg->scopes_count; i += 1, ptr += 1)
RDI_Scope *ptr = rdi->scopes;
for(U32 i = 0; i < rdi->scopes_count; i += 1, ptr += 1)
{
if(ptr->parent_scope_idx == 0)
{
rdi_stringize_scope(arena, &dump, raddbg, &scope_bundle, ptr, 1);
rdi_stringize_scope(arena, &dump, rdi, &scope_bundle, ptr, 1);
str8_list_push(arena, &dump, str8_lit("\n"));
}
}
@@ -347,8 +356,8 @@ entry_point(CmdLine *cmd_line)
if(dump_flags & DumpFlag_ScopeVMap)
{
str8_list_pushf(arena, &dump, "# SCOPE VMAP:\n");
RDI_VMapEntry *ptr = raddbg->scope_vmap;
for(U32 i = 0; i < raddbg->scope_vmap_count; i += 1, ptr += 1)
RDI_VMapEntry *ptr = rdi->scope_vmap;
for(U32 i = 0; i < rdi->scope_vmap_count; i += 1, ptr += 1)
{
str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", ptr->voff, ptr->idx);
}
@@ -359,11 +368,11 @@ entry_point(CmdLine *cmd_line)
if(dump_flags & DumpFlag_NameMaps)
{
str8_list_pushf(arena, &dump, "# NAME MAP:\n");
RDI_NameMap *ptr = raddbg->name_maps;
for(U32 i = 0; i < raddbg->name_maps_count; i += 1, ptr += 1)
RDI_NameMap *ptr = rdi->name_maps;
for(U32 i = 0; i < rdi->name_maps_count; i += 1, ptr += 1)
{
RDI_ParsedNameMap name_map = {0};
rdi_name_map_parse(raddbg, ptr, &name_map);
rdi_name_map_parse(rdi, ptr, &name_map);
str8_list_pushf(arena, &dump, " name_map[%u]:\n", i);
RDI_NameMapBucket *bucket = name_map.buckets;
for(U32 j = 0; j < name_map.bucket_count; j += 1, bucket += 1)
@@ -376,7 +385,7 @@ entry_point(CmdLine *cmd_line)
for(;node < node_opl; node += 1)
{
String8 string = {0};
string.str = rdi_string_from_idx(raddbg, node->string_idx, &string.size);
string.str = rdi_string_from_idx(rdi, node->string_idx, &string.size);
str8_list_pushf(arena, &dump, " match \"%.*s\": ", str8_varg(string));
if(node->match_count == 1)
{
@@ -386,7 +395,7 @@ entry_point(CmdLine *cmd_line)
{
RDI_U32 idx_count = 0;
RDI_U32 *idx_run =
rdi_idx_run_from_first_count(raddbg, node->match_idx_or_idx_run_first,
rdi_idx_run_from_first_count(rdi, node->match_idx_or_idx_run_first,
node->match_count, &idx_count);
if(idx_count > 0)
{
@@ -411,10 +420,10 @@ entry_point(CmdLine *cmd_line)
if(dump_flags & DumpFlag_Strings)
{
str8_list_pushf(arena, &dump, "# STRINGS:\n");
for(U64 string_idx = 0; string_idx < raddbg->string_count; string_idx += 1)
for(U64 string_idx = 0; string_idx < rdi->string_count; string_idx += 1)
{
String8 string = {0};
string.str = rdi_string_from_idx(raddbg, string_idx, &string.size);
string.str = rdi_string_from_idx(rdi, string_idx, &string.size);
str8_list_pushf(arena, &dump, " string[%I64u]: \"%S\"\n", string_idx, string);
}
str8_list_push(arena, &dump, str8_lit("\n"));
@@ -428,4 +437,6 @@ entry_point(CmdLine *cmd_line)
{
fwrite(n->string.str, 1, n->string.size, stdout);
}
di_scope_close(di_scope);
}
@@ -1,8 +1,8 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef RADDBGI_DWARF_H
#define RADDBGI_DWARF_H
#ifndef RDI_DWARF_H
#define RDI_DWARF_H
// https://dwarfstd.org/doc/DWARF4.pdf
// https://dwarfstd.org/doc/DWARF5.pdf
@@ -1489,5 +1489,5 @@ static String8 dwarf_string_from_line_ext_op(DWARF_LineExtOp op);
static String8 dwarf_string_from_line_entry_format(DWARF_LineEntryFormat format);
static String8 dwarf_string_from_section_code(DWARF_SectionCode sec_code);
#endif //RADDBGI_DWARF_H
#endif //RDI_DWARF_H
@@ -1,8 +1,8 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef RADDBGI_DWARF_STRINGIZE_H
#define RADDBGI_DWARF_STRINGIZE_H
#ifndef RDI_DWARF_STRINGIZE_H
#define RDI_DWARF_STRINGIZE_H
////////////////////////////////
//~ DWARF Stringize Functions
@@ -25,4 +25,4 @@ dwarf_stringize_addr(Arena *arena, String8List *out, DWARF_AddrUnit *unit, U32 i
#endif //RADDBGI_DWARF_STRINGIZE_H
#endif //RDI_DWARF_STRINGIZE_H
@@ -1,8 +1,8 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef RADDBGI_ELF_H
#define RADDBGI_ELF_H
#ifndef RDI_ELF_H
#define RDI_ELF_H
// https://refspecs.linuxfoundation.org/elf/elf.pdf
@@ -514,4 +514,4 @@ static String8 elf_string_from_symbol_binding(ELF_SymbolBinding binding);
static String8 elf_string_from_symbol_type(ELF_SymbolType type);
static String8 elf_string_from_symbol_visibility(ELF_SymbolVisibility visibility);
#endif //RADDBGI_ELF_H
#endif //RDI_ELF_H
@@ -1,27 +1,27 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#include "lib_raddbgi_format/raddbgi_format.h"
#include "lib_rdi_format/rdi_format.h"
#include "base/base_inc.h"
#include "os/os_inc.h"
#include "raddbgi_make_local/raddbgi_make_local.h"
#include "rdi_make_local/rdi_make_local.h"
#include "raddbgi_elf.h"
#include "raddbgi_dwarf.h"
#include "rdi_elf.h"
#include "rdi_dwarf.h"
#include "raddbgi_dwarf_stringize.h"
#include "rdi_dwarf_stringize.h"
#include "raddbgi_from_dwarf.h"
#include "rdi_from_dwarf.h"
#include "lib_raddbgi_format/raddbgi_format.c"
#include "lib_rdi_format/rdi_format.c"
#include "base/base_inc.c"
#include "os/os_inc.c"
#include "raddbgi_make_local/raddbgi_make_local.c"
#include "rdi_make_local/rdi_make_local.c"
#include "raddbgi_elf.c"
#include "raddbgi_dwarf.c"
#include "rdi_elf.c"
#include "rdi_dwarf.c"
#include "raddbgi_dwarf_stringize.c"
#include "rdi_dwarf_stringize.c"
// TODO(allen):
// [ ] need sample data for .debug_names
@@ -1,8 +1,8 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef RADDBGI_FROM_DWARF_H
#define RADDBGI_FROM_DWARF_H
#ifndef RDI_FROM_DWARF_H
#define RDI_FROM_DWARF_H
////////////////////////////////
//~ Program Parameters Type
@@ -47,4 +47,4 @@ static DWARFCONV_Params *dwarf_convert_params_from_cmd_line(Arena *arena, CmdLin
#endif //RADDBGI_FROM_DWARF_H
#endif //RDI_FROM_DWARF_H
@@ -147,7 +147,7 @@ Case("source_path_name_map",NormalSourcePathNameMap)\
}
////////////////////////////////
//~ rjf: COFF <-> RADDBGI Canonical Conversions
//~ rjf: COFF <-> RDI Canonical Conversions
internal RDI_BinarySectionFlags
p2r_rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags)
@@ -169,7 +169,7 @@ p2r_rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags)
}
////////////////////////////////
//~ rjf: CodeView <-> RADDBGI Canonical Conversions
//~ rjf: CodeView <-> RDI Canonical Conversions
internal RDI_Arch
p2r_rdi_arch_from_cv_arch(CV_Arch cv_arch)
@@ -2935,7 +2935,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
//- rjf: types pass 2: produce per-itype itype chain
//
// this pass is to ensure that subsequent passes always produce types for
// dependent itypes first - guaranteeing raddbgi's "only reference backward"
// dependent itypes first - guaranteeing rdi's "only reference backward"
// rule (which eliminates cycles). each itype slot gets a list of itypes,
// starting with the deepest dependency - when types are produced per-itype,
// this chain is walked, so that deeper dependencies are built first, and
@@ -2974,7 +2974,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in)
//- rjf: types pass 3: construct all types from TPI
//
// this doesn't gather struct/class/union/enum members, which is done by
// subsequent passes, to build RADDBGI "UDT" information, which is distinct
// subsequent passes, to build RDI "UDT" information, which is distinct
// from regular type info.
//
RDIM_Type **itype_type_ptrs = 0;
@@ -1,8 +1,8 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef RADDBGI_FROM_PDB_H
#define RADDBGI_FROM_PDB_H
#ifndef RDI_FROM_PDB_H
#define RDI_FROM_PDB_H
////////////////////////////////
//~ rjf: Export Artifact Flags
@@ -514,12 +514,12 @@ internal U64 p2r_hash_from_voff(U64 voff);
internal P2R_User2Convert *p2r_user2convert_from_cmdln(Arena *arena, CmdLine *cmdline);
////////////////////////////////
//~ rjf: COFF => RADDBGI Canonical Conversions
//~ rjf: COFF => RDI Canonical Conversions
internal RDI_BinarySectionFlags p2r_rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags);
////////////////////////////////
//~ rjf: CodeView => RADDBGI Canonical Conversions
//~ rjf: CodeView => RDI Canonical Conversions
internal RDI_Arch p2r_rdi_arch_from_cv_arch(CV_Arch arch);
internal RDI_RegisterCode p2r_rdi_reg_code_from_cv_reg_code(RDI_Arch arch, CV_Reg reg_code);
@@ -626,4 +626,4 @@ internal P2R_Bake2Serialize *p2r_bake(Arena *arena, P2R_Convert2Bake *in);
internal P2R_Bake2Serialize *p2r_compress(Arena *arena, P2R_Bake2Serialize *in);
#endif // RADDBGI_FROM_PDB_H
#endif // RDI_FROM_PDB_H
@@ -8,15 +8,15 @@
#define BUILD_VERSION_MINOR 9
#define BUILD_VERSION_PATCH 10
#define BUILD_RELEASE_PHASE_STRING_LITERAL "ALPHA"
#define BUILD_TITLE "raddbgi_from_pdb"
#define BUILD_TITLE "rdi_from_pdb"
#define BUILD_CONSOLE_INTERFACE 1
////////////////////////////////
//~ rjf: Includes
//- rjf: [lib]
#include "lib_raddbgi_format/raddbgi_format.h"
#include "lib_raddbgi_format/raddbgi_format.c"
#include "lib_rdi_format/rdi_format.h"
#include "lib_rdi_format/rdi_format.c"
#include "third_party/rad_lzb_simple/rad_lzb_simple.h"
#include "third_party/rad_lzb_simple/rad_lzb_simple.c"
@@ -24,27 +24,27 @@
#include "base/base_inc.h"
#include "os/os_inc.h"
#include "task_system/task_system.h"
#include "raddbgi_make_local/raddbgi_make_local.h"
#include "rdi_make_local/rdi_make_local.h"
#include "coff/coff.h"
#include "codeview/codeview.h"
#include "codeview/codeview_stringize.h"
#include "msf/msf.h"
#include "pdb/pdb.h"
#include "pdb/pdb_stringize.h"
#include "raddbgi_from_pdb.h"
#include "rdi_from_pdb.h"
//- rjf: [c]
#include "base/base_inc.c"
#include "os/os_inc.c"
#include "task_system/task_system.c"
#include "raddbgi_make_local/raddbgi_make_local.c"
#include "rdi_make_local/rdi_make_local.c"
#include "coff/coff.c"
#include "codeview/codeview.c"
#include "codeview/codeview_stringize.c"
#include "msf/msf.c"
#include "pdb/pdb.c"
#include "pdb/pdb_stringize.c"
#include "raddbgi_from_pdb.c"
#include "rdi_from_pdb.c"
////////////////////////////////
//~ rjf: Entry Point
@@ -62,7 +62,7 @@ entry_point(CmdLine *cmdline)
//- rjf: display help
if(do_help || user2convert->errors.node_count != 0)
{
fprintf(stderr, "--- raddbgi_from_pdb ----------------------------------------------------------\n\n");
fprintf(stderr, "--- rdi_from_pdb --------------------------------------------------------------\n\n");
fprintf(stderr, "This utility converts debug information from PDBs into the RAD Debug Info.\n");
fprintf(stderr, "format. The following arguments are accepted:\n\n");
@@ -1,4 +1,4 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#include "lib_raddbgi_make/raddbgi_make.c"
#include "lib_rdi_make/rdi_make.c"
@@ -45,6 +45,6 @@
#define RDIM_ProfBegin(...) ProfBeginDynamic(__VA_ARGS__)
#define RDIM_ProfEnd(...) ProfEnd()
#include "lib_raddbgi_make/raddbgi_make.h"
#include "lib_rdi_make/rdi_make.h"
#endif // RDI_CONS_LOCAL_H
@@ -3,10 +3,10 @@
//- GENERATED CODE
#ifndef REGS_RADDBGI_META_H
#define REGS_RADDBGI_META_H
#ifndef REGS_RDI_META_H
#define REGS_RDI_META_H
C_LINKAGE_BEGIN
C_LINKAGE_END
#endif // REGS_RADDBGI_META_H
#endif // REGS_RDI_META_H
@@ -1,4 +1,4 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#include "regs/raddbgi/generated/regs_raddbgi.meta.c"
#include "regs/rdi/generated/regs_rdi.meta.c"
@@ -1,10 +1,10 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef REGS_RADDBGI_H
#define REGS_RADDBGI_H
#ifndef REGS_RDI_H
#define REGS_RDI_H
internal RDI_RegisterCode regs_rdi_code_from_arch_reg_code(Architecture arch, REGS_RegCode code);
internal REGS_RegCode regs_reg_code_from_arch_rdi_code(Architecture arch, RDI_RegisterCode reg);
#endif //REGS_RADDBGI_H
#endif //REGS_RDI_H
+4 -4
View File
@@ -13,7 +13,7 @@ internal U64
regs_rip_from_arch_block(Architecture arch, void *block)
{
U64 result = 0;
switch(arch)
if(block != 0) switch(arch)
{
default:{}break;
case Architecture_x64:{result = ((REGS_RegBlockX64 *)block)->rip.u64;}break;
@@ -26,7 +26,7 @@ internal U64
regs_rsp_from_arch_block(Architecture arch, void *block)
{
U64 result = 0;
switch(arch)
if(block != 0) switch(arch)
{
default:{}break;
case Architecture_x64:{result = ((REGS_RegBlockX64 *)block)->rsp.u64;}break;
@@ -38,7 +38,7 @@ regs_rsp_from_arch_block(Architecture arch, void *block)
internal void
regs_arch_block_write_rip(Architecture arch, void *block, U64 rip)
{
switch(arch)
if(block != 0) switch(arch)
{
default:{}break;
case Architecture_x64:{((REGS_RegBlockX64 *)block)->rip.u64 = rip;}break;
@@ -49,7 +49,7 @@ regs_arch_block_write_rip(Architecture arch, void *block, U64 rip)
internal void
regs_arch_block_write_rsp(Architecture arch, void *block, U64 rsp)
{
switch(arch)
if(block != 0) switch(arch)
{
default:{}break;
case Architecture_x64:{((REGS_RegBlockX64 *)block)->rsp.u64 = rsp;}break;
+14 -8
View File
@@ -496,7 +496,7 @@ r_window_equip(OS_Handle handle)
os_graphical_message(1, str8_lit("Fatal Error"), str8_cstring(buffer));
os_exit_process(1);
}
r_d3d11_state->dxgi_factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER);
//- rjf: create framebuffer & view
@@ -841,18 +841,13 @@ r_window_begin_frame(OS_Handle window, R_Handle window_equip)
Vec2S32 resolution = {(S32)(client_rect.x1 - client_rect.x0), (S32)(client_rect.y1 - client_rect.y0)};
//- rjf: resolution change
B32 resize_done = 0;
if(wnd->last_resolution.x != resolution.x ||
wnd->last_resolution.y != resolution.y)
{
resize_done = 1;
wnd->last_resolution = resolution;
// rjf: resize swapchain & main framebuffer
wnd->framebuffer_rtv->Release();
wnd->framebuffer->Release();
wnd->swapchain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
wnd->swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)(&wnd->framebuffer));
r_d3d11_state->device->CreateRenderTargetView(wnd->framebuffer, 0, &wnd->framebuffer_rtv);
// rjf: release screen-sized render target resources, if there
if(wnd->stage_scratch_color_srv){wnd->stage_scratch_color_srv->Release();}
if(wnd->stage_scratch_color_rtv){wnd->stage_scratch_color_rtv->Release();}
@@ -867,6 +862,13 @@ r_window_begin_frame(OS_Handle window, R_Handle window_equip)
if(wnd->geo3d_depth_dsv) {wnd->geo3d_depth_dsv->Release();}
if(wnd->geo3d_depth) {wnd->geo3d_depth->Release();}
// rjf: resize swapchain & main framebuffer
wnd->framebuffer_rtv->Release();
wnd->framebuffer->Release();
wnd->swapchain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
wnd->swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)(&wnd->framebuffer));
r_d3d11_state->device->CreateRenderTargetView(wnd->framebuffer, 0, &wnd->framebuffer_rtv);
// rjf: create stage color targets
{
D3D11_TEXTURE2D_DESC color_desc = {};
@@ -946,6 +948,10 @@ r_window_begin_frame(OS_Handle window, R_Handle window_equip)
Vec4F32 clear_color = {0, 0, 0, 0};
d_ctx->ClearRenderTargetView(wnd->framebuffer_rtv, clear_color.v);
d_ctx->ClearRenderTargetView(wnd->stage_color_rtv, clear_color.v);
if(resize_done)
{
d_ctx->Flush();
}
}
ProfEnd();
}
+10 -10
View File
@@ -15,16 +15,16 @@
//~ rjf: Includes
//- rjf: [lib]
#include "lib_raddbgi_format/raddbgi_format.h"
#include "lib_raddbgi_format/raddbgi_format_parse.h"
#include "lib_raddbgi_format/raddbgi_format.c"
#include "lib_raddbgi_format/raddbgi_format_parse.c"
#include "lib_rdi_format/rdi_format.h"
#include "lib_rdi_format/rdi_format_parse.h"
#include "lib_rdi_format/rdi_format.c"
#include "lib_rdi_format/rdi_format_parse.c"
//- rjf: [h]
#include "base/base_inc.h"
#include "os/os_inc.h"
#include "task_system/task_system.h"
#include "raddbgi_make_local/raddbgi_make_local.h"
#include "rdi_make_local/rdi_make_local.h"
#include "mdesk/mdesk.h"
#include "hash_store/hash_store.h"
#include "file_stream/file_stream.h"
@@ -38,9 +38,9 @@
#include "msf/msf.h"
#include "pdb/pdb.h"
#include "pdb/pdb_stringize.h"
#include "raddbgi_from_pdb/raddbgi_from_pdb.h"
#include "rdi_from_pdb/rdi_from_pdb.h"
#include "regs/regs.h"
#include "regs/raddbgi/regs_raddbgi.h"
#include "regs/rdi/regs_rdi.h"
#include "type_graph/type_graph.h"
#include "dbgi/dbgi.h"
#include "demon/demon_inc.h"
@@ -52,7 +52,7 @@
#include "base/base_inc.c"
#include "os/os_inc.c"
#include "task_system/task_system.c"
#include "raddbgi_make_local/raddbgi_make_local.c"
#include "rdi_make_local/rdi_make_local.c"
#include "mdesk/mdesk.c"
#include "hash_store/hash_store.c"
#include "file_stream/file_stream.c"
@@ -66,9 +66,9 @@
#include "msf/msf.c"
#include "pdb/pdb.c"
#include "pdb/pdb_stringize.c"
#include "raddbgi_from_pdb/raddbgi_from_pdb.c"
#include "rdi_from_pdb/rdi_from_pdb.c"
#include "regs/regs.c"
#include "regs/raddbgi/regs_raddbgi.c"
#include "regs/rdi/regs_rdi.c"
#include "type_graph/type_graph.c"
#include "dbgi/dbgi.c"
#include "demon/demon_inc.c"
+6
View File
@@ -17,6 +17,12 @@ txt_lang_kind_from_extension(String8 extension)
str8_match(extension, str8_lit("cxx"), StringMatchFlag_CaseInsensitive) ||
str8_match(extension, str8_lit("cc"), StringMatchFlag_CaseInsensitive) ||
str8_match(extension, str8_lit("c++"), StringMatchFlag_CaseInsensitive) ||
str8_match(extension, str8_lit("ixx"), StringMatchFlag_CaseInsensitive) ||
str8_match(extension, str8_lit("cxxm"), StringMatchFlag_CaseInsensitive) ||
str8_match(extension, str8_lit("c++m"), StringMatchFlag_CaseInsensitive) ||
str8_match(extension, str8_lit("ccm"), StringMatchFlag_CaseInsensitive) ||
str8_match(extension, str8_lit("cppm"), StringMatchFlag_CaseInsensitive) ||
str8_match(extension, str8_lit("mpp"), StringMatchFlag_CaseInsensitive) ||
str8_match(extension, str8_lit("C"), 0) ||
str8_match(extension, str8_lit("hpp"), StringMatchFlag_CaseInsensitive) ||
str8_match(extension, str8_lit("hxx"), StringMatchFlag_CaseInsensitive) ||
-859
View File
@@ -1,859 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Memory View Helpers
internal UNW_MemView
unw_memview_from_data(String8 data, U64 base_vaddr)
{
UNW_MemView result = {0};
result.data = data.str;
result.addr_first = base_vaddr;
result.addr_opl = base_vaddr + data.size;
return result;
}
internal B32
unw_memview_read(UNW_MemView *memview, U64 addr, U64 size, void *out)
{
B32 result = 0;
if(memview->addr_first <= addr && addr + size <= memview->addr_opl)
{
MemoryCopy(out, (U8*)memview->data + addr - memview->addr_first, size);
result = 1;
}
return result;
}
////////////////////////////////
//~ rjf: PE/X64 Unwind Implementation
//- rjf: helpers
internal UNW_Step
unw_pe_x64__epilog(String8 bindata, PE_BinInfo *bin, U64 base_vaddr, UNW_MemView*memview, REGS_RegBlockX64 *regs)
{
UNW_Step result = {0};
U64 missed_read_addr = 0;
//- setup parsing context
U64 ip_voff = regs->rip.u64 - base_vaddr;
U64 sec_number = pe_section_num_from_voff(bindata, bin, ip_voff);
COFF_SectionHeader *sec = coff_section_header_from_num(bindata, bin->section_array_off, sec_number);
void* inst_base = pe_ptr_from_section_num(bindata, bin, sec_number);
U64 inst_size = sec->vsize;
//- setup parsing variables
B32 keep_parsing = 1;
U64 off = ip_voff - sec->voff;
//- parsing loop
for(;keep_parsing;)
{
keep_parsing = 0;
U8 inst_byte = 0;
if(off + sizeof(inst_byte) <= inst_size)
{
void *ptr = (U8*)inst_base + off;
MemoryCopy(&inst_byte, ptr, sizeof(inst_byte));
}
off += 1;
U8 rex = 0;
if((inst_byte & 0xF0) == 0x40)
{
rex = inst_byte & 0xF; // rex prefix
if(off + sizeof(inst_base) <= inst_size)
{
void *ptr = (U8*)inst_base + off;
MemoryCopy(&inst_byte, ptr, sizeof(inst_byte));
}
off += 1;
}
switch(inst_byte)
{
// pop
case 0x58:
case 0x59:
case 0x5A:
case 0x5B:
case 0x5C:
case 0x5D:
case 0x5E:
case 0x5F:
{
U64 sp = regs->rsp.u64;
U64 value = 0;
if(!unw_memview_read_struct(memview, sp, &value))
{
missed_read_addr = sp;
goto error_out;
}
// modify register
PE_UnwindGprRegX64 gpr_reg = (inst_byte - 0x58) + (rex & 1)*8;
REGS_Reg64 *reg = unw_pe_x64__gpr_reg(regs, gpr_reg);
// not a final instruction
keep_parsing = 1;
// commit registers
reg->u64 = value;
regs->rsp.u64 = sp + 8;
}break;
// add $nnnn,%rsp
case 0x81:
{
// skip one byte (we already know what it is in this scenario)
off += 1;
// read the 4-byte immediate
S32 imm = 0;
if(off + sizeof(imm) < inst_size)
{
void *ptr = (U8*)inst_base + off;
MemoryCopy(&imm, ptr, sizeof(imm));
}
off += 4;
// not a final instruction
keep_parsing = 1;
// update stack pointer
regs->rsp.u64 = (U64)(regs->rsp.u64 + imm);
}break;
// add $n,%rsp
case 0x83:
{
// skip one byte (we already know what it is in this scenario)
off += 1;
// read the 1-byte immediate
S8 imm = 0;
if(off + sizeof(imm) < inst_size)
{
void *ptr = (U8*)inst_base + off;
MemoryCopy(&imm, ptr, sizeof(imm));
}
off += 1;
// update stack pointer
regs->rsp.u64 = (U64)(regs->rsp.u64 + imm);
keep_parsing = 1;
}break;
// lea imm8/imm32,$rsp
case 0x8D:
{
// read source register
U8 modrm = 0;
if(off + sizeof(modrm) < inst_size)
{
void *ptr = (U8*)inst_base + off;
MemoryCopy(&modrm, ptr, sizeof(modrm));
}
PE_UnwindGprRegX64 gpr_reg = (modrm & 7) + (rex & 1)*8;
REGS_Reg64 *reg = unw_pe_x64__gpr_reg(regs, gpr_reg);
U64 reg_value = reg->u64;
// advance to the immediate
off += 1;
S32 imm = 0;
// read 1-byte immediate
if((modrm >> 6) == 1)
{
S8 imm8 = 0;
if(off + sizeof(imm8) < inst_size)
{
void *ptr = (U8*)inst_base + off;
MemoryCopy(&imm8, ptr, sizeof(imm8));
}
imm = imm8;
off += 1;
}
// read 4-byte immediate
else
{
if(off + sizeof(imm) < inst_size)
{
void *ptr = (U8*)inst_base + off;
MemoryCopy(&imm, ptr, sizeof(imm));
}
off += 4;
}
regs->rsp.u64 = (U64)(reg_value + imm);
keep_parsing = 1;
}break;
// ret $nn
case 0xC2:
{
// read new ip
U64 sp = regs->rsp.u64;
U64 new_ip = 0;
if(!unw_memview_read_struct(memview, sp, &new_ip))
{
missed_read_addr = sp;
goto error_out;
}
// read 2-byte immediate & advance stack pointer
U16 imm = 0;
if(off + sizeof(imm) < inst_size)
{
void *ptr = (U8*)inst_base + off;
MemoryCopy(&imm, ptr, sizeof(imm));
}
U64 new_sp = sp + 8 + imm;
// commit registers
regs->rip.u64 = new_ip;
regs->rsp.u64 = new_sp;
}break;
// ret / rep; ret
case 0xF3:
{
Assert(!"Hit me!");
}
case 0xC3:
{
// read new ip
U64 sp = regs->rsp.u64;
U64 new_ip = 0;
if(!unw_memview_read_struct(memview, sp, &new_ip))
{
missed_read_addr = sp;
goto error_out;
}
// advance stack pointer
U64 new_sp = sp + 8;
// commit registers
regs->rip.u64 = new_ip;
regs->rsp.u64 = new_sp;
}break;
// jmp nnnn
case 0xE9:
{
Assert(!"Hit Me");
// TODO(allen): general idea: read the immediate, move the ip, leave the sp, done
// we don't have any cases to exercise this right now. no guess implementation!
}break;
// jmp n
case 0xEB:
{
Assert(!"Hit Me");
// TODO(allen): general idea: read the immediate, move the ip, leave the sp, done
// we don't have any cases to exercise this right now. no guess implementation!
}break;
}
}
error_out:;
if(missed_read_addr != 0)
{
result.dead = 1;
result.missed_read = 1;
result.missed_read_addr = missed_read_addr;
}
return(result);
}
internal B32
unw_pe_x64__voff_is_in_epilog(String8 bindata, PE_BinInfo *bin, U64 voff, PE_IntelPdata *final_pdata)
{
// NOTE(allen): There are restrictions placed on how an epilog is allowed
// to be formed (https://docs.microsoft.com/en-us/cpp/build/prolog-and-epilog?view=msvc-160)
// Here we interpret machine code directly according to the rules
// given there to determine if the code we're looking at looks like an epilog.
// TODO(allen): Figure out how to verify this.
//- setup parsing context
U64 sec_number = pe_section_num_from_voff(bindata, bin, voff);
COFF_SectionHeader *sec = coff_section_header_from_num(bindata, bin->section_array_off, sec_number);
void* inst_base = pe_ptr_from_section_num(bindata, bin, sec_number);
U64 inst_size = sec->vsize;
//- setup parsing variables
B32 is_epilog = 0;
B32 keep_parsing = 1;
U64 off = voff - sec->voff;
//- check first instruction
{
B32 inst_read_success = 0;
U8 inst[4];
if (off + sizeof(inst) < inst_size){
void *ptr = (U8*)inst_base + off;
MemoryCopy(&inst, ptr, sizeof(inst));
inst_read_success = 1;
}
if (!inst_read_success){
keep_parsing = 0;
}
else{
if ((inst[0] & 0xF8) == 0x48){
switch (inst[1]){
// add $nnnn,%rsp
case 0x81:
{
if (inst[0] == 0x48 && inst[2] == 0xC4){
off += 7;
}
else{
keep_parsing = 0;
}
}break;
// add $n,%rsp
case 0x83:
{
if (inst[0] == 0x48 && inst[2] == 0xC4){
off += 4;
}
else{
keep_parsing = 0;
}
}break;
// lea n(reg),%rsp
case 0x8D:
{
if ((inst[0] & 0x06) == 0 &&
((inst[2] >> 3) & 0x07) == 0x04 &&
(inst[2] & 0x07) != 0x04){
U8 imm_size = (inst[2] >> 6);
// 1-byte immediate
if (imm_size == 1){
off += 4;
}
// 4-byte immediate
else if (imm_size == 2){
off += 7;
}
else{
keep_parsing = 0;
}
}
else{
keep_parsing = 0;
}
}break;
}
}
}
}
//- parsing loop
if (keep_parsing){
for (;;){
// read inst
U8 inst_byte = 0;
if (off + sizeof(inst_byte) < inst_size){
void *ptr = (U8*)inst_base + off;
MemoryCopy(&inst_byte, ptr, sizeof(inst_byte));
}
else{
goto loop_break;
}
// when (... I don't know ...) rely on the next byte
U64 check_off = off;
U8 check_inst_byte = inst_byte;
if ((inst_byte & 0xF0) == 0x40){
check_off = off + 1;
if (off + sizeof(check_inst_byte) < inst_size){
void *ptr = (U8*)inst_base + off;
MemoryCopy(&check_inst_byte, ptr, sizeof(check_inst_byte));
}
else{
goto loop_break;
}
}
switch (check_inst_byte){
// pop
case 0x58:case 0x59:case 0x5A:case 0x5B:
case 0x5C:case 0x5D:case 0x5E:case 0x5F:
{
off = check_off + 1;
}break;
// ret
case 0xC2:case 0xC3:
{
is_epilog = 1;
goto loop_break;
}break;
// jmp nnnn
case 0xE9:
{
U64 imm_off = check_off + 1;
S32 imm = 0;
if (off + sizeof(imm) < inst_size){
void *ptr = (U8*)inst_base + off;
MemoryCopy(&imm, ptr, sizeof(imm));
}
else{
goto loop_break;
}
U64 next_off = (U64)(imm_off + sizeof(imm) + imm);
if (!(final_pdata->voff_first <= next_off && next_off < final_pdata->voff_one_past_last)){
goto loop_break;
}
off = next_off;
// TODO(allen): why isn't this just the end of the epilog?
}break;
// rep; ret (for amd64 prediction bug)
case 0xF3:
{
U8 next_inst_byte = 0;
if (off + sizeof(next_inst_byte) < inst_size){
void *ptr = (U8*)inst_base + off;
MemoryCopy(&next_inst_byte, ptr, sizeof(next_inst_byte));
}
is_epilog = (next_inst_byte == 0xC3);
goto loop_break;
}break;
default: goto loop_break;
}
}
loop_break:;
}
//- fill result
B32 result = is_epilog;
return(result);
}
internal REGS_Reg64*
unw_pe_x64__gpr_reg(REGS_RegBlockX64 *regs, PE_UnwindGprRegX64 unw_reg){
static REGS_Reg64 dummy = {0};
REGS_Reg64 *result = &dummy;
switch (unw_reg){
case PE_UnwindGprRegX64_RAX: result = &regs->rax; break;
case PE_UnwindGprRegX64_RCX: result = &regs->rcx; break;
case PE_UnwindGprRegX64_RDX: result = &regs->rdx; break;
case PE_UnwindGprRegX64_RBX: result = &regs->rbx; break;
case PE_UnwindGprRegX64_RSP: result = &regs->rsp; break;
case PE_UnwindGprRegX64_RBP: result = &regs->rbp; break;
case PE_UnwindGprRegX64_RSI: result = &regs->rsi; break;
case PE_UnwindGprRegX64_RDI: result = &regs->rdi; break;
case PE_UnwindGprRegX64_R8 : result = &regs->r8 ; break;
case PE_UnwindGprRegX64_R9 : result = &regs->r9 ; break;
case PE_UnwindGprRegX64_R10: result = &regs->r10; break;
case PE_UnwindGprRegX64_R11: result = &regs->r11; break;
case PE_UnwindGprRegX64_R12: result = &regs->r12; break;
case PE_UnwindGprRegX64_R13: result = &regs->r13; break;
case PE_UnwindGprRegX64_R14: result = &regs->r14; break;
case PE_UnwindGprRegX64_R15: result = &regs->r15; break;
}
return(result);
}
//- rjf: unwind step
internal UNW_Step
unw_unwind_pe_x64(String8 bindata, PE_BinInfo *bin, U64 base_vaddr, UNW_MemView *memview, REGS_RegBlockX64 *regs)
{
UNW_Step result = {0};
U64 missed_read_addr = 0;
//- grab ip_voff (several places can use this)
U64 ip_voff = regs->rip.u64 - base_vaddr;
//- get pdata entry from current ip
PE_IntelPdata *initial_pdata = 0;
{
U64 initial_pdata_off = pe_intel_pdata_off_from_voff__binary_search(bindata, bin, ip_voff);
if(initial_pdata_off != 0)
{
initial_pdata = (PE_IntelPdata*)(bindata.str + initial_pdata_off);
}
}
//- no pdata; unwind by reading stack pointer
if(initial_pdata == 0)
{
// read ip from stack pointer
U64 sp = regs->rsp.u64;
U64 new_ip = 0;
if(!unw_memview_read_struct(memview, sp, &new_ip))
{
missed_read_addr = sp;
goto error_out;
}
// advance stack pointer
U64 new_sp = sp + 8;
// commit registers
regs->rip.u64 = new_ip;
regs->rsp.u64 = new_sp;
}
//- got pdata; perform unwinding with exception handling
else
{
// try epilog unwind
B32 did_epilog_unwind = 0;
if(unw_pe_x64__voff_is_in_epilog(bindata, bin, ip_voff, initial_pdata))
{
result = unw_pe_x64__epilog(bindata, bin, base_vaddr, memview, regs);
did_epilog_unwind = 1;
}
// try xdata unwind
if(!did_epilog_unwind)
{
B32 did_machframe = 0;
// get frame reg
REGS_Reg64 *frame_reg = 0;
U64 frame_off = 0;
{
U64 unwind_info_off = initial_pdata->voff_unwind_info;
PE_UnwindInfo *unwind_info = (PE_UnwindInfo*)(pe_ptr_from_voff(bindata, bin, unwind_info_off));
U32 frame_reg_id = PE_UNWIND_INFO_REG_FROM_FRAME(unwind_info->frame);
U64 frame_off_val = PE_UNWIND_INFO_OFF_FROM_FRAME(unwind_info->frame);
if (frame_reg_id != 0){
frame_reg = unw_pe_x64__gpr_reg(regs, frame_reg_id);
// TODO(allen): at this point if frame_reg is zero, the exe is corrupted.
}
frame_off = frame_off_val;
}
PE_IntelPdata *last_pdata = 0;
PE_IntelPdata *pdata = initial_pdata;
for (;pdata != last_pdata;)
{
//- rjf: unpack unwind info & codes
U64 unwind_info_off = pdata->voff_unwind_info;
PE_UnwindInfo *unwind_info = (PE_UnwindInfo*)(pe_ptr_from_voff(bindata, bin, unwind_info_off));
PE_UnwindCode *unwind_codes = (PE_UnwindCode*)(unwind_info + 1);
//- rjf: unpack frame base
U64 frame_base = regs->rsp.u64;
if(frame_reg != 0)
{
U64 raw_frame_base = frame_reg->u64;
U64 adjusted_frame_base = raw_frame_base - frame_off*16;
if(adjusted_frame_base < raw_frame_base)
{
frame_base = adjusted_frame_base;
}
else
{
frame_base = 0;
}
}
//- rjf: bad unwind info -> abort
if(unwind_info == 0)
{
result.dead = 1;
goto error_out;
}
//- op code interpreter
PE_UnwindCode *code_ptr = unwind_codes;
PE_UnwindCode *code_opl = unwind_codes + unwind_info->codes_num;
for(PE_UnwindCode *next_code_ptr = 0; code_ptr < code_opl; code_ptr = next_code_ptr)
{
// extract op code parts
U32 op_code = PE_UNWIND_OPCODE_FROM_FLAGS(code_ptr->flags);
U32 op_info = PE_UNWIND_INFO_FROM_FLAGS(code_ptr->flags);
// determine number of op code slots
U32 slot_count = pe_slot_count_from_unwind_op_code(op_code);
if(op_code == PE_UnwindOpCode_ALLOC_LARGE && op_info == 1)
{
slot_count += 1;
}
// check op code slot count
if (slot_count == 0 || code_ptr + slot_count > code_opl){
result.dead = 1;
goto end_xdata_unwind;
}
// set next op code pointer
next_code_ptr = code_ptr + slot_count;
// interpret this op code
U64 code_voff = pdata->voff_first + code_ptr->off_in_prolog;
if (code_voff <= ip_voff){
switch (op_code){
case PE_UnwindOpCode_PUSH_NONVOL:
{
// read value from stack pointer
U64 sp = regs->rsp.u64;
U64 value = 0;
if(!unw_memview_read_struct(memview, sp, &value))
{
missed_read_addr = sp;
goto error_out;
}
// advance stack pointer
U64 new_sp = sp + 8;
// commit registers
REGS_Reg64 *reg = unw_pe_x64__gpr_reg(regs, op_info);
reg->u64 = value;
regs->rsp.u64 = new_sp;
}break;
case PE_UnwindOpCode_ALLOC_LARGE:
{
// read alloc size
U64 size = 0;
if (op_info == 0){
size = code_ptr[1].u16*8;
}
else if (op_info == 1){
size = code_ptr[1].u16 + ((U32)code_ptr[2].u16 << 16);
}
else{
result.dead = 1;
goto end_xdata_unwind;
}
// advance stack pointer
U64 sp = regs->rsp.u64;
U64 new_sp = sp + size;
// advance stack pointer
regs->rsp.u64 = new_sp;
}break;
case PE_UnwindOpCode_ALLOC_SMALL:
{
// advance stack pointer
regs->rsp.u64 += op_info*8 + 8;
}break;
case PE_UnwindOpCode_SET_FPREG:
{
// put stack pointer back to the frame base
regs->rsp.u64 = frame_base;
}break;
case PE_UnwindOpCode_SAVE_NONVOL:
{
// read value from frame base
U64 off = code_ptr[1].u16*8;
U64 addr = frame_base + off;
U64 value = 0;
if (!unw_memview_read_struct(memview, addr, &value)){
missed_read_addr = addr;
goto error_out;
}
// commit to register
REGS_Reg64 *reg = unw_pe_x64__gpr_reg(regs, op_info);
reg->u64 = value;
}break;
case PE_UnwindOpCode_SAVE_NONVOL_FAR:
{
// read value from frame base
U64 off = code_ptr[1].u16 + ((U32)code_ptr[2].u16 << 16);
U64 addr = frame_base + off;
U64 value = 0;
if (!unw_memview_read_struct(memview, addr, &value)){
missed_read_addr = addr;
goto error_out;
}
// commit to register
REGS_Reg64 *reg = unw_pe_x64__gpr_reg(regs, op_info);
reg->u64 = value;
}break;
case PE_UnwindOpCode_EPILOG:
{
result.dead = 1;
}break;
case PE_UnwindOpCode_SPARE_CODE:
{
result.dead = 1;
// Assert(!"Hit me!");
// TODO(allen): ???
}break;
case PE_UnwindOpCode_SAVE_XMM128:
{
// read new register values
U8 buf[16];
U64 off = code_ptr[1].u16*16;
U64 addr = frame_base + off;
if (!unw_memview_read(memview, addr, 16, buf)){
missed_read_addr = addr;
goto error_out;
}
// commit to register
void *xmm_reg = (&regs->ymm0) + op_info;
MemoryCopy(xmm_reg, buf, sizeof(buf));
}break;
case PE_UnwindOpCode_SAVE_XMM128_FAR:
{
// read new register values
U8 buf[16];
U64 off = code_ptr[1].u16 + ((U32)code_ptr[2].u16 << 16);
U64 addr = frame_base + off;
if (!unw_memview_read(memview, addr, 16, buf)){
missed_read_addr = addr;
goto error_out;
}
// commit to register
void *xmm_reg = (&regs->ymm0) + op_info;
MemoryCopy(xmm_reg, buf, sizeof(buf));
}break;
case PE_UnwindOpCode_PUSH_MACHFRAME:
{
// NOTE(rjf): this was found by stepping through kernel code after an exception was
// thrown, encountered in the exception_stepping_tests (after the throw) in mule_main
if(op_info > 1)
{
result.dead = 1;
goto end_xdata_unwind;
}
// read values
U64 sp_og = regs->rsp.u64;
U64 sp_adj = sp_og;
if(op_info == 1)
{
sp_adj += 8;
}
U64 ip_value = 0;
if(!unw_memview_read_struct(memview, sp_adj, &ip_value))
{
missed_read_addr = sp_adj;
goto error_out;
}
U64 sp_after_ip = sp_adj + 8;
U16 ss_value = 0;
if(!unw_memview_read_struct(memview, sp_after_ip, &ss_value))
{
missed_read_addr = sp_after_ip;
goto error_out;
}
U64 sp_after_ss = sp_after_ip + 8;
U64 rflags_value = 0;
if(!unw_memview_read_struct(memview, sp_after_ss, &rflags_value))
{
missed_read_addr = sp_after_ss;
goto error_out;
}
U64 sp_after_rflags = sp_after_ss + 8;
U64 sp_value = 0;
if(!unw_memview_read_struct(memview, sp_after_rflags, &sp_value))
{
missed_read_addr = sp_after_rflags;
goto error_out;
}
// commit registers
regs->rip.u64 = ip_value;
regs->ss.u16 = ss_value;
regs->rflags.u64 = rflags_value;
regs->rsp.u64 = sp_value;
// mark machine frame
did_machframe = 1;
}break;
}
}
}
//- iterate pdata chain
U32 flags = PE_UNWIND_INFO_FLAGS_FROM_HDR(unwind_info->header);
if (!(flags & PE_UnwindInfoFlag_CHAINED)){
break;
}
U64 code_count_rounded = AlignPow2(unwind_info->codes_num, sizeof(PE_UnwindCode));
U64 code_size = code_count_rounded*sizeof(PE_UnwindCode);
U64 chained_pdata_off = unwind_info_off + sizeof(PE_UnwindInfo) + code_size;
last_pdata = pdata;
pdata = (PE_IntelPdata*)pe_ptr_from_voff(bindata, bin, chained_pdata_off);
}
if(!did_machframe)
{
U64 sp = regs->rsp.u64;
U64 new_ip = 0;
if(!unw_memview_read_struct(memview, sp, &new_ip))
{
missed_read_addr = sp;
goto error_out;
}
// advance stack pointer
U64 new_sp = sp + 8;
// commit registers
regs->rip.u64 = new_ip;
regs->rsp.u64 = new_sp;
}
end_xdata_unwind:;
}
}
error_out:;
if(missed_read_addr != 0)
{
result.dead = 1;
result.missed_read = 1;
result.missed_read_addr = missed_read_addr;
}
if(!result.dead)
{
result.stack_pointer = regs->rsp.u64;
}
return(result);
}
-62
View File
@@ -1,62 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef UNWIND_H
#define UNWIND_H
////////////////////////////////
//~ rjf: Memory View Types
//
// Memory views are used to provide a slice (or, in the future, slices) of data
// required to do a proper unwind. This is generally a very small region in an
// address space, generally some things on the stack. But, some formats don't
// restrict this in an organized way, and so theoretically you might have some
// unwind information require arbitrary reads at an unknown address. So this
// "memory view" concept serves as kind of a "stand-in" for "provided memory
// info from the user". This keeps the control flow of this layer simpler, so
// we aren't calling a user-supplied hook to read memory or anything like that.
typedef struct UNW_MemView UNW_MemView;
struct UNW_MemView
{
// Upgrade Path:
// 1. A list of ranges like this one
// 2. Binary-searchable list of ranges
// 3. In-line growth strategy for missing pages (hardwired to source of new data)
// 4. Abstracted source of new data
void *data;
U64 addr_first;
U64 addr_opl;
};
////////////////////////////////
//~ rjf: Unwind Step Results
typedef struct UNW_Step UNW_Step;
struct UNW_Step
{
B32 dead;
B32 missed_read;
U64 missed_read_addr;
U64 stack_pointer;
};
////////////////////////////////
//~ rjf: Memory View Helpers
internal UNW_MemView unw_memview_from_data(String8 data, U64 base_vaddr);
internal B32 unw_memview_read(UNW_MemView *memview, U64 addr, U64 size, void *out);
#define unw_memview_read_struct(v,addr,p) unw_memview_read((v), (addr), sizeof(*(p)), (p))
////////////////////////////////
//~ rjf: PE/X64 Unwind Implementation
//- rjf: helpers
internal UNW_Step unw_pe_x64__epilog(String8 bindata, PE_BinInfo *bin, U64 base_vaddr, UNW_MemView *memview, REGS_RegBlockX64 *regs_inout);
internal B32 unw_pe_x64__voff_is_in_epilog(String8 bindata, PE_BinInfo *bin, U64 voff, PE_IntelPdata *final_pdata);
internal REGS_Reg64 *unw_pe_x64__gpr_reg(REGS_RegBlockX64 *regs, PE_UnwindGprRegX64 unw_reg);
//- rjf: unwind step
internal UNW_Step unw_unwind_pe_x64(String8 bindata, PE_BinInfo *bin, U64 base_vaddr, UNW_MemView *memview, REGS_RegBlockX64 *regs_inout);
#endif // UNWIND_H