Merge remote-tracking branch 'EpicGamesExt/dev'

This commit is contained in:
2025-05-20 22:08:31 -04:00
297 changed files with 66738 additions and 50023 deletions
+14 -10
View File
@@ -13,6 +13,19 @@ jobs:
runs-on: windows-2022
strategy:
fail-fast: false
matrix:
target:
- raddbg
- radlink
- rdi_from_pdb
- raddump
- rdi_breakpad_from_pdb
compiler:
- msvc
- clang
mode:
- debug
- release
steps:
- name: checkout
uses: actions/checkout@v2
@@ -20,13 +33,4 @@ jobs:
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
call build raddbg msvc debug || exit /b 1
call build rdi_from_pdb msvc debug || exit /b 1
call build rdi_from_dwarf msvc debug || exit /b 1
call build rdi_dump msvc debug || exit /b 1
call build raddbg clang debug || exit /b 1
call build rdi_from_pdb clang debug || exit /b 1
call build rdi_from_dwarf clang debug || exit /b 1
call build rdi_dump clang debug || exit /b 1
call build radlink msvc debug || exit /b 1
call build radlink clang debug || exit /b 1
call build ${{ matrix.target }} ${{ matrix.compiler }} ${{ matrix.mode }} || exit /b 1
+14 -3
View File
@@ -90,10 +90,11 @@ You should see the following output:
```
[debug mode]
[msvc compile]
[default mode, assuming `raddbg` build]
metagen_main.c
searching C:\devel\raddebugger/src... 309 files found
parsing metadesk... 15 metadesk files parsed
gathering tables... 96 tables found
searching C:\devel\raddebugger/src... 447 files found
parsing metadesk... 14 metadesk files parsed
gathering tables... 93 tables found
generating layer code...
raddbg_main.c
```
@@ -101,6 +102,16 @@ raddbg_main.c
If everything worked correctly, there will be a `build` folder in the root
level of the codebase, and it will contain a freshly-built `raddbg.exe`.
This `raddbg.exe` will have been built in **debug mode**, which is not built
with optimizations, and may perform worse. To produce a
**release mode executable**, run `build.bat` with a `release` argument:
```
build release
```
This build will take significantly longer.
## Short-To-Medium-Term Roadmap
### The Initial Alpha Battle-Testing Phase
+10 -7
View File
@@ -40,6 +40,7 @@ if "%~1"=="release" if "%~2"=="" echo [default mode, assuming `raddbg` build] &&
set auto_compile_flags=
if "%telemetry%"=="1" set auto_compile_flags=%auto_compile_flags% -DPROFILE_TELEMETRY=1 && echo [telemetry profiling enabled]
if "%asan%"=="1" set auto_compile_flags=%auto_compile_flags% -fsanitize=address && echo [asan enabled]
if "%opengl%"=="1" set auto_compile_flags=%auto_compile_flags% -DR_BACKEND=R_BACKEND_OPENGL && echo [opengl render backend]
:: --- Compile/Link Line Definitions ------------------------------------------
set cl_common= /I..\src\ /I..\local\ /nologo /FC /Z7
@@ -52,14 +53,14 @@ set cl_link= /link /MANIFEST:EMBED /INCREMENTAL:NO /pdbaltpath:%%%%_PDB%%%
set clang_link= -fuse-ld=lld -Xlinker /MANIFEST:EMBED -Xlinker /pdbaltpath:%%%%_PDB%%%% -Xlinker /NATVIS:"%~dp0\src\natvis\base.natvis"
set cl_out= /out:
set clang_out= -o
set cl_natvis= /NATVIS:
set clang_natvis= -Xlinker /NATVIS:
set cl_linker=
set clang_linker= -Xlinker
:: --- Per-Build Settings -----------------------------------------------------
set link_dll=-DLL
set link_icon=logo.res
if "%msvc%"=="1" set link_natvis=%cl_natvis%
if "%clang%"=="1" set link_natvis=%clang_natvis%
if "%msvc%"=="1" set linker=%cl_linker%
if "%clang%"=="1" set linker=%clang_linker%
if "%msvc%"=="1" set only_compile=/c
if "%clang%"=="1" set only_compile=-c
if "%msvc%"=="1" set EHsc=/EHsc
@@ -106,18 +107,20 @@ if not "%no_meta%"=="1" (
:: --- Build Everything (@build_targets) --------------------------------------
pushd build
if "%raddbg%"=="1" set didbuild=1 && %compile% ..\src\raddbg\raddbg_main.c %compile_link% %link_icon% %out%raddbg.exe || exit /b 1
if "%radlink%"=="1" set didbuild=1 && %compile% ..\src\linker\lnk.c %compile_link% %link_natvis%"%~dp0\src\linker\linker.natvis" %out%radlink.exe || exit /b 1
if "%radlink%"=="1" set didbuild=1 && %compile% ..\src\linker\lnk.c %compile_link% %linker% /NOIMPLIB %linker% /NATVIS:"%~dp0\src\linker\linker.natvis" %out%radlink.exe || exit /b 1
if "%radcon%"=="1" set didbuild=1 && %compile% ..\src\radcon\radcon_main.c %compile_link% %out%radcon.exe || exit /b 1
if "%raddump%"=="1" set didbuild=1 && %compile% ..\src\raddump\raddump_main.c %compile_link% %out%raddump.exe || exit /b 1
if "%rdi_from_pdb%"=="1" set didbuild=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" set didbuild=1 && %compile% ..\src\rdi_from_dwarf\rdi_from_dwarf.c %compile_link% %out%rdi_from_dwarf.exe || exit /b 1
if "%rdi_dump%"=="1" set didbuild=1 && %compile% ..\src\rdi_dump\rdi_dump_main.c %compile_link% %out%rdi_dump.exe || exit /b 1
if "%rdi_from_dwarf%"=="1" set didbuild=1 && %compile% ..\src\rdi_from_dwarf\rdi_from_dwarf_main.c %compile_link% %out%rdi_from_dwarf.exe || exit /b 1
if "%rdi_breakpad_from_pdb%"=="1" set didbuild=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 "%tester%"=="1" set didbuild=1 && %compile% ..\src\tester\tester_main.c %compile_link% %out%tester.exe || exit /b 1
if "%ryan_scratch%"=="1" set didbuild=1 && %compile% ..\src\scratch\ryan_scratch.c %compile_link% %out%ryan_scratch.exe || exit /b 1
if "%eval_scratch%"=="1" set didbuild=1 && %compile% ..\src\scratch\eval_scratch.c %compile_link% %out%eval_scratch.exe || exit /b 1
if "%textperf%"=="1" set didbuild=1 && %compile% ..\src\scratch\textperf.c %compile_link% %out%textperf.exe || exit /b 1
if "%convertperf%"=="1" set didbuild=1 && %compile% ..\src\scratch\convertperf.c %compile_link% %out%convertperf.exe || exit /b 1
if "%debugstringperf%"=="1" set didbuild=1 && %compile% ..\src\scratch\debugstringperf.c %compile_link% %out%debugstringperf.exe || exit /b 1
if "%parse_inline_sites%"=="1" set didbuild=1 && %compile% ..\src\scratch\parse_inline_sites.c %compile_link% %out%parse_inline_sites.exe || exit /b 1
if "%strip_lib_debug%"=="1" set didbuild=1 && %compile% ..\src\strip_lib_debug\strip_lib_debug.c %compile_link% %out%strip_lib_debug.exe || exit /b 1
if "%mule_main%"=="1" set didbuild=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" set didbuild=1 && %compile% ..\src\mule\mule_module.cpp %compile_link% %link_dll% %out%mule_module.dll || exit /b 1
if "%mule_hotload%"=="1" set didbuild=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
+6 -4
View File
@@ -15,11 +15,11 @@ if [ -v gcc ]; then compiler="${CC:-gcc}"; echo "[gcc compile]"; fi
auto_compile_flags=''
# --- Get Current Git Commit Id -----------------------------------------------
git_hash=$(git rev-parse HEAD)
git_hash=$(git describe --always --dirty)
git_hash_full=$(git rev-parse HEAD)
# --- Compile/Link Line Definitions -------------------------------------------
clang_common="-I../src/ -I../local/ -g -DBUILD_GIT_HASH=\"$git_hash\" -DBUILD_GIT_HASH_FULL=\"$git_hash_full\" -Wno-unknown-warning-option -fdiagnostics-absolute-paths -Wall -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Wno-initializer-overrides -Wno-incompatible-pointer-types-discards-qualifiers -Wno-for-loop-analysis -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf"
clang_common="-I../src/ -I/usr/include/freetype2/ -I../local/ -g -DBUILD_GIT_HASH=\"$git_hash\" -DBUILD_GIT_HASH_FULL=\"$git_hash_full\" -Wno-unknown-warning-option -fdiagnostics-absolute-paths -Wall -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Wno-initializer-overrides -Wno-incompatible-pointer-types-discards-qualifiers -Wno-for-loop-analysis -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf"
clang_debug="$compiler -g -O0 -DBUILD_DEBUG=1 ${clang_common} ${auto_compile_flags}"
clang_release="$compiler -g -O2 -DBUILD_DEBUG=0 ${clang_common} ${auto_compile_flags}"
clang_link="-lpthread -lm -lrt -ldl"
@@ -33,6 +33,8 @@ gcc_out="-o"
# --- Per-Build Settings ------------------------------------------------------
link_dll="-fPIC"
link_os_gfx="-lX11 -lXext"
link_render="-lGL -lEGL"
link_font_provider="-lfreetype"
# --- Choose Compile/Link Lines -----------------------------------------------
if [ -v gcc ]; then compile_debug="$gcc_debug"; fi
@@ -62,13 +64,13 @@ fi
# --- Build Everything (@build_targets) ---------------------------------------
cd build
if [ -v raddbg ]; then didbuild=1 && $compile ../src/raddbg/raddbg_main.c $compile_link $link_os_gfx $out raddbg; fi
if [ -v raddbg ]; then didbuild=1 && $compile ../src/raddbg/raddbg_main.c $compile_link $link_os_gfx $link_render $link_font_provider $out raddbg; fi
if [ -v radlink ]; then didbuild=1 && $compile ../src/linker/lnk.c $compile_link $out radlink; fi
if [ -v rdi_from_pdb ]; then didbuild=1 && $compile ../src/rdi_from_pdb/rdi_from_pdb_main.c $compile_link $out rdi_from_pdb; fi
if [ -v rdi_from_dwarf ]; then didbuild=1 && $compile ../src/rdi_from_dwarf/rdi_from_dwarf.c $compile_link $out rdi_from_dwarf; fi
if [ -v rdi_dump ]; then didbuild=1 && $compile ../src/rdi_dump/rdi_dump_main.c $compile_link $out rdi_dump; fi
if [ -v rdi_breakpad_from_pdb ]; then didbuild=1 && $compile ../src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c $compile_link $out rdi_breakpad_from_pdb; fi
if [ -v ryan_scratch ]; then didbuild=1 && $compile ../src/scratch/ryan_scratch.c $compile_link $link_os_gfx $out ryan_scratch; fi
if [ -v ryan_scratch ]; then didbuild=1 && $compile ../src/scratch/ryan_scratch.c $compile_link $link_os_gfx $link_render $link_font_provider $out ryan_scratch; fi
cd ..
# --- Warn On No Builds -------------------------------------------------------
BIN
View File
Binary file not shown.
+14 -6
View File
@@ -45,12 +45,20 @@ load_paths =
commands =
{
//- rjf: fkey command slots (change locally but do not commit)
.f1 = { .win = "build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.f2 = { .win = "build rdi_from_pdb", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.f3 = { .win = "pushd build && raddbg.exe --user:local_dev.raddbg_user --project:local_dev.raddbg_project --xuto_run && popd",.linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
// .f1 = { .win = "build textperf release telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
// .f3 = { .win = "pushd build && textperf.exe --capture && popd",.linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
//- rjf: [raddbg]
.f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
//- rjf: [textperf]
// .f1 = { .win = "raddbg_stable --ipc kill_all && build no_meta telemetry textperf && raddbg_stable --ipc bring_to_front && raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
//- rjf: [tester]
// .f1 = { .win = "raddbg_stable --ipc kill_all && build no_meta tester", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
//- rjf: running target
.f3 = { .win = "raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
// .f3 = { .win = "pushd build && raddbg --user:dev.raddbg_user && popd", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
// .f3 = { .win = "C:/devel/raddebugger/build/raddbg.exe --capture --user:C:/devel/raddebugger/build/local_dev.raddbg_user --project:C:/devel/raddebugger/build/local_dev.raddbg_project", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
// .f3 = { .win = "wsl_launch /mnt/c/devel/raddebugger/build/raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
//- rjf: local target builds
.build_raddbg = { .win = "build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
+12 -3
View File
@@ -1,6 +1,9 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#undef LAYER_COLOR
#define LAYER_COLOR 0x59b6c3ff
////////////////////////////////
//~ rjf: Top-Level Layer Initialization
@@ -23,8 +26,9 @@ async_init(CmdLine *cmdline)
String8 work_thread_count_string = cmd_line_string(cmdline, str8_lit("work_threads_count"));
if(work_thread_count_string.size == 0 || !try_u64_from_str8_c_rules(work_thread_count_string, &async_shared->work_threads_count))
{
async_shared->work_threads_count = Max(1, os_get_system_info()->logical_processor_count-1);
async_shared->work_threads_count = Max(4, os_get_system_info()->logical_processor_count-1);
}
async_shared->work_threads_count = Max(4, async_shared->work_threads_count);
async_shared->work_threads = push_array(arena, OS_Handle, async_shared->work_threads_count);
for EachIndex(idx, async_shared->work_threads_count)
{
@@ -57,6 +61,7 @@ async_push_work_(ASYNC_WorkFunctionType *work_function, ASYNC_WorkParams *params
work.output = params->output;
work.semaphore = params->semaphore;
work.completion_counter = params->completion_counter;
work.working_counter = params->working_counter;
// rjf: loop; try to write into user -> writer ring buffer. if we're on a
// worker thread, determine if we need to execute this task locally on this
@@ -159,7 +164,6 @@ async_task_join(ASYNC_Task *task)
internal ASYNC_Work
async_pop_work(void)
{
ProfBeginFunction();
ASYNC_Work work = {0};
B32 done = 0;
ASYNC_Priority taken_priority = ASYNC_Priority_Low;
@@ -194,7 +198,6 @@ async_pop_work(void)
}
os_condition_variable_broadcast(async_shared->ring_cv);
os_condition_variable_broadcast(async_shared->rings[taken_priority].ring_cv);
ProfEnd();
return work;
}
@@ -223,6 +226,12 @@ async_execute_work(ASYNC_Work work)
{
ins_atomic_u64_inc_eval(work.completion_counter);
}
//- rjf: decrement working counter
if(work.working_counter != 0)
{
ins_atomic_u64_dec_eval(work.working_counter);
}
}
////////////////////////////////
+2
View File
@@ -29,6 +29,7 @@ struct ASYNC_WorkParams
void **output;
OS_Handle semaphore;
U64 *completion_counter;
U64 *working_counter;
U64 endt_us;
ASYNC_Priority priority;
};
@@ -41,6 +42,7 @@ struct ASYNC_Work
void **output;
OS_Handle semaphore;
U64 *completion_counter;
U64 *working_counter;
};
////////////////////////////////
+1 -1
View File
@@ -159,7 +159,7 @@
#endif
#if !defined(BUILD_VERSION_PATCH)
# define BUILD_VERSION_PATCH 15
# define BUILD_VERSION_PATCH 18
#endif
#define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH)
+34
View File
@@ -602,3 +602,37 @@ ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_s
}
return read_size;
}
////////////////////////////////
internal U64
u64_array_bsearch(U64 *arr, U64 count, U64 value)
{
if(count > 1 && arr[0] <= value && value < arr[count-1])
{
U64 l = 0;
U64 r = count - 1;
for(; l <= r; )
{
U64 m = l + (r - l) / 2;
if(arr[m] == value)
{
return m;
}
else if(arr[m] < value)
{
l = m + 1;
}
else
{
r = m - 1;
}
}
}
else if (count == 1 && arr[0] == value)
{
return 0;
}
return max_U64;
}
+44 -7
View File
@@ -65,6 +65,14 @@
# define C_LINKAGE
#endif
////////////////////////////////
//~ rjf: Versions
#define Version(major, minor, patch) (U64)((((U64)(major) & 0xffff) << 32) | ((((U64)(minor) & 0xffff) << 16)) | ((((U64)(patch) & 0xffff) << 0)))
#define MajorFromVersion(version) (((version) & 0xffff00000000ull) >> 32)
#define MinorFromVersion(version) (((version) & 0x0000ffff0000ull) >> 16)
#define PatchFromVersion(version) (((version) & 0x00000000ffffull) >> 0)
////////////////////////////////
//~ rjf: Units
@@ -348,6 +356,9 @@ C_LINKAGE void __asan_unpoison_memory_region(void const volatile *addr, size_t s
#define IsPow2OrZero(x) ((((x) - 1)&(x)) == 0)
#define ExtractBit(word, idx) (((word) >> (idx)) & 1)
#define Extract8(word, pos) (((word) >> ((pos)*8)) & max_U8)
#define Extract16(word, pos) (((word) >> ((pos)*16)) & max_U16)
#define Extract32(word, pos) (((word) >> ((pos)*32)) & max_U32)
#if LANG_CPP
# define zero_struct {}
@@ -379,11 +390,33 @@ typedef S64 B64;
typedef float F32;
typedef double F64;
typedef void VoidProc(void);
typedef struct U128 U128;
struct U128
typedef union U128 U128;
union U128
{
U8 u8[16];
U16 u16[8];
U32 u32[4];
U64 u64[2];
};
typedef union U256 U256;
union U256
{
U8 u8[32];
U16 u16[16];
U32 u32[8];
U64 u64[4];
U128 u128[2];
};
typedef union U512 U512;
union U512
{
U8 u8[64];
U16 u16[32];
U32 u32[16];
U64 u64[8];
U128 u128[4];
U256 u256[2];
};
////////////////////////////////
//~ rjf: Basic Types & Spaces
@@ -565,15 +598,15 @@ global U32 max_U32 = 0xffffffff;
global U16 max_U16 = 0xffff;
global U8 max_U8 = 0xff;
global S64 max_S64 = (S64)0x7fffffffffffffffull;
global S64 max_S64 = (S64)0x7fffffffffffffffll;
global S32 max_S32 = (S32)0x7fffffff;
global S16 max_S16 = (S16)0x7fff;
global S8 max_S8 = (S8)0x7f;
global S64 min_S64 = (S64)0xffffffffffffffffull;
global S32 min_S32 = (S32)0xffffffff;
global S16 min_S16 = (S16)0xffff;
global S8 min_S8 = (S8)0xff;
global S64 min_S64 = (S64)0x8000000000000000ll;
global S32 min_S32 = (S32)0x80000000;
global S16 min_S16 = (S16)0x8000;
global S8 min_S8 = (S8)0x80;
global const U32 bitmask1 = 0x00000001;
global const U32 bitmask2 = 0x00000003;
@@ -885,4 +918,8 @@ internal U64 ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_dat
#define quick_sort(ptr, count, element_size, cmp_function) qsort((ptr), (count), (element_size), (int (*)(const void *, const void *))(cmp_function))
////////////////////////////////
internal U64 u64_array_bsearch(U64 *arr, U64 count, U64 value);
#endif // BASE_CORE_H
+3
View File
@@ -121,6 +121,9 @@ update(void)
{
ProfTick(0);
ins_atomic_u64_inc_eval(&global_update_tick_idx);
#if defined(FONT_CACHE_H)
fnt_frame();
#endif
#if OS_FEATURE_GRAPHICAL
B32 result = frame();
#else
+2 -2
View File
@@ -4,8 +4,8 @@
////////////////////////////////
//~ rjf: Base Includes
#undef MARKUP_LAYER_COLOR
#define MARKUP_LAYER_COLOR 0.20f, 0.60f, 0.80f
#undef LAYER_COLOR
#define LAYER_COLOR 0.20f, 0.60f, 0.80f
#include "base_core.c"
#include "base_profile.c"
+3 -3
View File
@@ -49,12 +49,12 @@ internal void log_select(Log *log);
internal void log_msg(LogMsgKind kind, String8 string);
internal void log_msgf(LogMsgKind kind, char *fmt, ...);
#define log_info(s) log_msg(LogMsgKind_Info, (s))
#define log_infof(fmt, ...) log_msgf(LogMsgKind_Info, (fmt), __VA_ARGS__)
#define log_infof(...) log_msgf(LogMsgKind_Info, __VA_ARGS__)
#define log_user_error(s) log_msg(LogMsgKind_UserError, (s))
#define log_user_errorf(fmt, ...) log_msgf(LogMsgKind_UserError, (fmt), __VA_ARGS__)
#define log_user_errorf(...) log_msgf(LogMsgKind_UserError, __VA_ARGS__)
#define LogInfoNamedBlock(s) DeferLoop(log_infof("%S:\n{\n", (s)), log_infof("}\n"))
#define LogInfoNamedBlockF(fmt, ...) DeferLoop((log_infof(fmt, __VA_ARGS__), log_infof(":\n{\n")), log_infof("}\n"))
#define LogInfoNamedBlockF(...) DeferLoop((log_infof(__VA_ARGS__), log_infof(":\n{\n")), log_infof("}\n"))
////////////////////////////////
//~ rjf: Log Scopes
+12 -2
View File
@@ -4,9 +4,19 @@
#ifndef BASE_MARKUP_H
#define BASE_MARKUP_H
#define RADDBG_MARKUP_IMPLEMENTATION
#define RADDBG_MARKUP_VSNPRINTF raddbg_vsnprintf
#if OS_LINUX
# define RADDBG_MARKUP_STUBS
#endif
#include "lib_raddbg_markup/raddbg_markup.h"
#if !defined(LAYER_COLOR)
# define LAYER_COLOR 0x404040ff
#endif
internal void set_thread_name(String8 string);
internal void set_thread_namef(char *fmt, ...);
#define ThreadNameF(...) (set_thread_namef(__VA_ARGS__))
#define ThreadName(str) (set_thread_name(str))
#define ThreadNameF(...) (set_thread_namef(__VA_ARGS__), raddbg_thread_color_u32(LAYER_COLOR))
#endif // BASE_MARKUP_H
+152 -7
View File
@@ -386,6 +386,21 @@ derotate_4x4f32(Mat4x4F32 mat)
return mat;
}
internal Mat4x4F32
transpose_4x4f32(Mat4x4F32 mat)
{
Mat4x4F32 result =
{
{
mat.v[0][0], mat.v[1][0], mat.v[2][0], mat.v[3][0],
mat.v[0][1], mat.v[1][1], mat.v[2][1], mat.v[3][1],
mat.v[0][2], mat.v[1][2], mat.v[2][2], mat.v[3][2],
mat.v[0][3], mat.v[1][3], mat.v[2][3], mat.v[3][3],
}
};
return result;
}
////////////////////////////////
//~ rjf: Range Ops
@@ -480,7 +495,9 @@ internal Rng2F32 intersect_2f32(Rng2F32 a, Rng2F32 b) {Rng2F32 c; c.p0
internal Vec2F32 clamp_2f32(Rng2F32 r, Vec2F32 v) {v.x = Clamp(r.min.x, v.x, r.max.x); v.y = Clamp(r.min.y, v.y, r.max.y); return v;}
////////////////////////////////
//~ rjf: Miscellaneous Ops
//~ rjf: Color Operations
//- rjf: hsv <-> rgb
internal Vec3F32
hsv_from_rgb(Vec3F32 rgb)
@@ -567,16 +584,102 @@ rgba_from_hsva(Vec4F32 hsva)
return rgba;
}
internal Vec4F32
rgba_from_u32(U32 hex)
//- rjf: srgb <-> linear
internal Vec3F32
linear_from_srgb(Vec3F32 srgb)
{
Vec4F32 result = v4f32(((hex&0xff000000)>>24)/255.f,
((hex&0x00ff0000)>>16)/255.f,
((hex&0x0000ff00)>> 8)/255.f,
((hex&0x000000ff)>> 0)/255.f);
Vec3F32 result;
for EachElement(idx, srgb.v)
{
result.v[idx] = (srgb.v[idx] < 0.0404482362771082f ? srgb.v[idx] / 12.92f : pow_f32((srgb.v[idx] + 0.055f) / 1.055f, 2.4f));
}
return result;
}
internal Vec3F32
srgb_from_linear(Vec3F32 linear)
{
Vec3F32 result;
for EachElement(idx, linear.v)
{
result.v[idx] = (0 <= linear.v[idx] && linear.v[idx] < 0.00313066844250063) ? linear.v[idx]*12.92f : 1.05f * pow_f32(linear.v[idx], 1.f/2.4f) - 0.055f;
}
return result;
}
internal Vec4F32
linear_from_srgba(Vec4F32 srgba)
{
Vec4F32 result;
result.xyz = linear_from_srgb(srgba.xyz);
result.w = srgba.w;
return result;
}
internal Vec4F32
srgba_from_linear(Vec4F32 linear)
{
Vec4F32 result;
result.xyz = srgb_from_linear(linear.xyz);
result.w = linear.w;
return result;
}
//- rjf: oklab <-> linear
internal Vec3F32
oklab_from_linear(Vec3F32 linear)
{
F32 l = (0.4122214708f * linear.x + 0.5363325363f * linear.y + 0.0514459929f * linear.z);
F32 m = (0.2119034982f * linear.x + 0.6806995451f * linear.y + 0.1073969566f * linear.z);
F32 s = (0.0883024619f * linear.x + 0.2817188376f * linear.y + 0.6299787005f * linear.z);
F32 l_ = cbrt_f32(l);
F32 m_ = cbrt_f32(m);
F32 s_ = cbrt_f32(s);
Vec3F32 result;
result.x = 0.2104542553f*l_ + 0.7936177850f*m_ - 0.0040720468f*s_;
result.y = 1.9779984951f*l_ - 2.4285922050f*m_ + 0.4505937099f*s_;
result.z = 0.0259040371f*l_ + 0.7827717662f*m_ - 0.8086757660f*s_;
return result;
}
internal Vec3F32
linear_from_oklab(Vec3F32 oklab)
{
F32 l_ = oklab.x + 0.3963377774f * oklab.y + 0.2158037573f * oklab.z;
F32 m_ = oklab.x - 0.1055613458f * oklab.y - 0.0638541728f * oklab.z;
F32 s_ = oklab.x - 0.0894841775f * oklab.y - 1.2914855480f * oklab.z;
F32 l = l_*l_*l_;
F32 m = m_*m_*m_;
F32 s = s_*s_*s_;
Vec3F32 result;
result.x = +4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s;
result.y = -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s;
result.z = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s;
return result;
}
internal Vec4F32
oklab_from_lineara(Vec4F32 lineara)
{
Vec4F32 result;
result.xyz = oklab_from_linear(lineara.xyz);
result.w = lineara.w;
return result;
}
internal Vec4F32
lineara_from_oklab(Vec4F32 oklab)
{
Vec4F32 result;
result.xyz = linear_from_oklab(oklab.xyz);
result.w = oklab.w;
return result;
}
//- rjf: rgba <-> u32
internal U32
u32_from_rgba(Vec4F32 rgba)
{
@@ -588,6 +691,16 @@ u32_from_rgba(Vec4F32 rgba)
return result;
}
internal Vec4F32
rgba_from_u32(U32 hex)
{
Vec4F32 result = v4f32(((hex&0xff000000)>>24)/255.f,
((hex&0x00ff0000)>>16)/255.f,
((hex&0x0000ff00)>> 8)/255.f,
((hex&0x000000ff)>> 0)/255.f);
return result;
}
////////////////////////////////
//~ rjf: List Type Functions
@@ -634,6 +747,37 @@ rng1u64_array_from_list(Arena *arena, Rng1U64List *list)
return arr;
}
internal U64
rng_1u64_array_bsearch(Rng1U64Array arr, U64 value)
{
if(arr.count > 0 && arr.v[0].min <= value && value < arr.v[arr.count-1].max)
{
U64 l = 0;
U64 r = arr.count - 1;
for(; l <= r; )
{
U64 m = l + (r - l) / 2;
if(contains_1u64(arr.v[m], value))
{
return m;
}
else if(arr.v[m].min < value)
{
l = m + 1;
}
else
{
r = m - 1;
}
}
}
else if(arr.count == 1 && contains_1u64(arr.v[0], value))
{
return 0;
}
return max_U64;
}
internal void
rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng)
{
@@ -657,3 +801,4 @@ rng1s64_array_from_list(Arena *arena, Rng1S64List *list)
}
return arr;
}
+25 -7
View File
@@ -379,14 +379,15 @@ struct Rng1S64Array
#define abs_s64(v) (S64)llabs(v)
#define sqrt_f32(v) sqrtf(v)
#define cbrt_f32(v) cbrtf(v)
#define mod_f32(a, b) fmodf((a), (b))
#define pow_f32(b, e) powf((b), (e))
#define ceil_f32(v) ceilf(v)
#define floor_f32(v) floorf(v)
#define round_f32(v) roundf(v)
#define abs_f32(v) fabsf(v)
#define radians_from_turns_f32(v) ((v)*2*3.1415926535897f)
#define turns_from_radians_f32(v) ((v)/2*3.1415926535897f)
#define radians_from_turns_f32(v) ((v)*(2*3.1415926535897f))
#define turns_from_radians_f32(v) ((v)/(2*3.1415926535897f))
#define degrees_from_turns_f32(v) ((v)*360.f)
#define turns_from_degrees_f32(v) ((v)/360.f)
#define degrees_from_radians_f32(v) (degrees_from_turns_f32(turns_from_radians_f32(v)))
@@ -396,14 +397,15 @@ struct Rng1S64Array
#define tan_f32(v) tanf(radians_from_turns_f32(v))
#define sqrt_f64(v) sqrt(v)
#define cbrt_f64(v) cbrt(v)
#define mod_f64(a, b) fmod((a), (b))
#define pow_f64(b, e) pow((b), (e))
#define ceil_f64(v) ceil(v)
#define floor_f64(v) floor(v)
#define round_f64(v) round(v)
#define abs_f64(v) fabs(v)
#define radians_from_turns_f64(v) ((v)*2*3.1415926535897)
#define turns_from_radians_f64(v) ((v)/2*3.1415926535897)
#define radians_from_turns_f64(v) ((v)*(2*3.1415926535897))
#define turns_from_radians_f64(v) ((v)/(2*3.1415926535897))
#define degrees_from_turns_f64(v) ((v)*360.0)
#define turns_from_degrees_f64(v) ((v)/360.0)
#define degrees_from_radians_f64(v) (degrees_from_turns_f64(turns_from_radians_f64(v)))
@@ -543,6 +545,7 @@ internal Mat4x4F32 mul_4x4f32(Mat4x4F32 a, Mat4x4F32 b);
internal Mat4x4F32 scale_4x4f32(Mat4x4F32 m, F32 scale);
internal Mat4x4F32 inverse_4x4f32(Mat4x4F32 m);
internal Mat4x4F32 derotate_4x4f32(Mat4x4F32 mat);
internal Mat4x4F32 transpose_4x4f32(Mat4x4F32 mat);
////////////////////////////////
//~ rjf: Range Ops
@@ -651,15 +654,29 @@ internal Rng2F32 intersect_2f32(Rng2F32 a, Rng2F32 b);
internal Vec2F32 clamp_2f32(Rng2F32 r, Vec2F32 v);
////////////////////////////////
//~ rjf: Miscellaneous Ops
//~ rjf: Color Operations
//- rjf: hsv <-> rgb
internal Vec3F32 hsv_from_rgb(Vec3F32 rgb);
internal Vec3F32 rgb_from_hsv(Vec3F32 hsv);
internal Vec4F32 hsva_from_rgba(Vec4F32 rgba);
internal Vec4F32 rgba_from_hsva(Vec4F32 hsva);
internal Vec4F32 rgba_from_u32(U32 hex);
internal U32 u32_from_rgba(Vec4F32 rgba);
//- rjf: srgb <-> linear
internal Vec3F32 linear_from_srgb(Vec3F32 srgb);
internal Vec3F32 srgb_from_linear(Vec3F32 linear);
internal Vec4F32 linear_from_srgba(Vec4F32 srgba);
internal Vec4F32 srgba_from_linear(Vec4F32 linear);
//- rjf: oklab <-> linear
internal Vec3F32 oklab_from_linear(Vec3F32 linear);
internal Vec3F32 linear_from_oklab(Vec3F32 oklab);
internal Vec4F32 oklab_from_lineara(Vec4F32 lineara);
internal Vec4F32 lineara_from_oklab(Vec4F32 oklab);
//- rjf: rgba <-> u32
internal U32 u32_from_rgba(Vec4F32 rgba);
internal Vec4F32 rgba_from_u32(U32 hex);
#define rgba_from_u32_lit_comp(h) { (((h)&0xff000000)>>24)/255.f, (((h)&0x00ff0000)>>16)/255.f, (((h)&0x0000ff00)>> 8)/255.f, (((h)&0x000000ff)>> 0)/255.f }
////////////////////////////////
@@ -668,6 +685,7 @@ internal U32 u32_from_rgba(Vec4F32 rgba);
internal void rng1u64_list_push(Arena *arena, Rng1U64List *list, Rng1U64 rng);
internal void rng1u64_list_concat(Rng1U64List *list, Rng1U64List *to_concat);
internal Rng1U64Array rng1u64_array_from_list(Arena *arena, Rng1U64List *list);
internal U64 rng_1u64_array_bsearch(Rng1U64Array arr, U64 value);
internal void rng1s64_list_push(Arena *arena, Rng1S64List *list, Rng1S64 rng);
internal Rng1S64Array rng1s64_array_from_list(Arena *arena, Rng1S64List *list);
+15 -16
View File
@@ -44,8 +44,7 @@ typed_data_rebase_ptrs(Type *type, String8 data, void *base_ptr)
switch(t->type->kind)
{
default:{}break;
case TypeKind_Ptr:
if(!(t->type->flags & TypeFlag_IsExternal))
case TypeKind_Ptr:
{
*(U64 *)t->ptr = ((U64)(*(U8 **)t->ptr - (U8 *)base_ptr));
}break;
@@ -173,13 +172,13 @@ serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerialize
task->containing_type = t->containing_type;
task->containing_ptr = t->containing_ptr;
SLLQueuePush(first_task, last_task, task);
}
// rjf: catch-all: write pointer value
else
{
str8_serial_push_string(scratch.arena, &strings, str8(t->src, t->type->size*t->count));
}
}
// rjf: catch-all: write pointer value
else
{
str8_serial_push_string(scratch.arena, &strings, str8(t->src, t->type->size*t->count));
}
}break;
//- rjf: arrays -> descend to underlying type, + count
@@ -345,14 +344,14 @@ deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSeriali
task->containing_type = t->containing_type;
task->containing_ptr = t->containing_ptr;
SLLQueuePush(first_task, last_task, task);
}
// rjf: catch-all: read pointer value
else
{
}
// rjf: catch-all: read pointer value
else
{
MemoryCopy(t->dst, t_src, t->type->size*t->count);
read_off += t->type->size*t->count;
}
read_off += t->type->size*t->count;
}
}break;
//- rjf: arrays -> descend to underlying type, + count
+3 -4
View File
@@ -100,10 +100,9 @@ TypeKind;
typedef U32 TypeFlags;
enum
{
TypeFlag_IsExternal = (1<<0),
TypeFlag_IsPlainText = (1<<1),
TypeFlag_IsCodeText = (1<<2),
TypeFlag_IsPathText = (1<<3),
TypeFlag_IsPlainText = (1<<0),
TypeFlag_IsCodeText = (1<<1),
TypeFlag_IsPathText = (1<<2),
};
typedef U32 MemberFlags;
+18 -22
View File
@@ -11,10 +11,6 @@
# define PROFILE_TELEMETRY 0
#endif
#if !defined(MARKUP_LAYER_COLOR)
# define MARKUP_LAYER_COLOR 1.00f, 0.00f, 1.00f
#endif
////////////////////////////////
//~ rjf: Third Party Includes
@@ -44,25 +40,25 @@
# define ProfLockDrop(...) tmReleasedLock(0, __VA_ARGS__)
# define ProfColor(color) tmZoneColorSticky(color)
# define ProfBeginV(...) \
if (TM_API_PTR) { \
static tm_uint64 file_id = 0; TM_API_PTR->_tmStaticString(&file_id, __FILE__); \
Temp scratch = scratch_begin(0,0); \
String8 string = push_str8f(scratch.arena, __VA_ARGS__); \
tm_uint64 hash = TM_API_PTR->_tmHash((char*)string.str, string.size); \
hash = TM_API_PTR->_tmSendDynamicString(hash, (char*)string.str); \
TM_API_PTR->_tmEnterZoneFast_Core(0, 0, file_id, __LINE__, hash); \
scratch_end(scratch); \
}
if (TM_API_PTR) { \
static tm_uint64 file_id = 0; TM_API_PTR->_tmStaticString(&file_id, __FILE__); \
Temp scratch = scratch_begin(0,0); \
String8 string = push_str8f(scratch.arena, __VA_ARGS__); \
tm_uint64 hash = TM_API_PTR->_tmHash((char*)string.str, string.size); \
hash = TM_API_PTR->_tmSendDynamicString(hash, (char*)string.str); \
TM_API_PTR->_tmEnterZoneFast_Core(0, 0, file_id, __LINE__, hash); \
scratch_end(scratch); \
}
# define ProfNoteV(...) \
if (TM_API_PTR) { \
static tm_uint64 file_id = 0; TM_API_PTR->_tmStaticString(&file_id, __FILE__); \
Temp scratch = scratch_begin(0,0); \
String8 string = push_str8f(scratch.arena, __VA_ARGS__); \
tm_uint64 hash = TM_API_PTR->_tmHash((char*)string.str, string.size); \
hash = TM_API_PTR->_tmSendDynamicString(hash, (char*)string.str); \
TM_API_PTR->_tmMessageFast_Core(0, TMMF_ICON_NOTE, file_id, __LINE__, hash); \
scratch_end(scratch); \
}
if (TM_API_PTR) { \
static tm_uint64 file_id = 0; TM_API_PTR->_tmStaticString(&file_id, __FILE__); \
Temp scratch = scratch_begin(0,0); \
String8 string = push_str8f(scratch.arena, __VA_ARGS__); \
tm_uint64 hash = TM_API_PTR->_tmHash((char*)string.str, string.size); \
hash = TM_API_PTR->_tmSendDynamicString(hash, (char*)string.str); \
TM_API_PTR->_tmMessageFast_Core(0, TMMF_ICON_NOTE, file_id, __LINE__, hash); \
scratch_end(scratch); \
}
#endif
////////////////////////////////
+198 -158
View File
@@ -242,7 +242,7 @@ str8_cstring_capped_reverse(void *raw_start, void *raw_cap)
for(; ptr > start; )
{
ptr -= 1;
if (*ptr == '\0')
{
break;
@@ -427,23 +427,53 @@ str8_chop(String8 str, U64 amt){
}
internal String8
str8_skip_chop_whitespace(String8 string){
str8_skip_chop_whitespace(String8 string)
{
U8 *first = string.str;
U8 *opl = first + string.size;
for (;first < opl; first += 1){
if (!char_is_space(*first)){
for(;first < opl; first += 1)
{
if(!char_is_space(*first))
{
break;
}
}
for (;opl > first;){
for(;opl > first;)
{
opl -= 1;
if (!char_is_space(*opl)){
if(!char_is_space(*opl))
{
opl += 1;
break;
}
}
String8 result = str8_range(first, opl);
return(result);
return result;
}
internal String8
str8_skip_chop_slashes(String8 string)
{
U8 *first = string.str;
U8 *opl = first + string.size;
for(;first < opl; first += 1)
{
if(!char_is_slash(*first))
{
break;
}
}
for(;opl > first;)
{
opl -= 1;
if(!char_is_slash(*opl))
{
opl += 1;
break;
}
}
String8 result = str8_range(first, opl);
return result;
}
////////////////////////////////
@@ -573,44 +603,50 @@ s32_from_str8(String8 string, U32 radix)
}
internal B32
try_u64_from_str8_c_rules(String8 string, U64 *x){
try_u64_from_str8_c_rules(String8 string, U64 *x)
{
B32 is_integer = 0;
if (str8_is_integer(string, 10)){
if(str8_is_integer(string, 10) && !str8_match(str8_prefix(string, 1), str8_lit("0"), 0))
{
is_integer = 1;
*x = u64_from_str8(string, 10);
}
else{
else
{
String8 hex_string = str8_skip(string, 2);
if (str8_match(str8_prefix(string, 2), str8_lit("0x"), 0) &&
str8_is_integer(hex_string, 0x10)){
if(str8_match(str8_prefix(string, 2), str8_lit("0x"), 0) &&
str8_is_integer(hex_string, 0x10))
{
is_integer = 1;
*x = u64_from_str8(hex_string, 0x10);
}
else if (str8_match(str8_prefix(string, 2), str8_lit("0b"), 0) &&
str8_is_integer(hex_string, 2)){
else if(str8_match(str8_prefix(string, 2), str8_lit("0b"), 0) && str8_is_integer(hex_string, 2))
{
is_integer = 1;
*x = u64_from_str8(hex_string, 2);
}
else{
else
{
String8 oct_string = str8_skip(string, 1);
if (str8_match(str8_prefix(string, 1), str8_lit("0"), 0) &&
str8_is_integer(hex_string, 010)){
if(str8_match(str8_prefix(string, 1), str8_lit("0"), 0) && str8_is_integer(hex_string, 010))
{
is_integer = 1;
*x = u64_from_str8(oct_string, 010);
}
}
}
return(is_integer);
return is_integer;
}
internal B32
try_s64_from_str8_c_rules(String8 string, S64 *x){
try_s64_from_str8_c_rules(String8 string, S64 *x)
{
String8 string_tail = {0};
S64 sign = sign_from_str8(string, &string_tail);
U64 x_u64 = 0;
B32 is_integer = try_u64_from_str8_c_rules(string_tail, &x_u64);
*x = x_u64*sign;
return(is_integer);
return is_integer;
}
//- rjf: integer -> string
@@ -619,7 +655,7 @@ internal String8
str8_from_memory_size(Arena *arena, U64 size)
{
String8 result;
if(size < KB(1))
{
result = push_str8f(arena, "%llu Bytes", size);
@@ -640,7 +676,7 @@ str8_from_memory_size(Arena *arena, U64 size)
{
result = push_str8f(arena, "%llu.%02llu TiB", size / TB(1), ((size * 100) / TB(1)) % 100);
}
return result;
}
@@ -648,7 +684,7 @@ internal String8
str8_from_count(Arena *arena, U64 count)
{
String8 result;
if(count < 1 * 1000)
{
result = push_str8f(arena, "%llu", count);
@@ -689,7 +725,7 @@ str8_from_count(Arena *arena, U64 count)
result = push_str8f(arena, "%lluB", count / 1000000000, frac);
}
}
return result;
}
@@ -1114,6 +1150,13 @@ str8_list_from_flags(Arena *arena, String8List *list,
////////////////////////////////
//~ rjf; String Arrays
internal String8Array
str8_array_zero(void)
{
String8Array result = {0};
return result;
}
internal String8Array
str8_array_from_list(Arena *arena, String8List *list)
{
@@ -1137,44 +1180,103 @@ str8_array_reserve(Arena *arena, U64 count)
return arr;
}
internal String8Array
str8_array_copy(Arena *arena, String8Array array)
{
String8Array result = {0};
result.count = array.count;
result.v = push_array(arena, String8, result.count);
for EachIndex(idx, result.count)
{
result.v[idx] = push_str8_copy(arena, array.v[idx]);
}
return result;
}
////////////////////////////////
//~ rjf: String Version Helpers
internal U64
version_from_str8(String8 string)
{
U64 result = 0;
Temp scratch = scratch_begin(0, 0);
U64 version_major = 0;
U64 version_minor = 0;
U64 version_patch = 0;
String8List version_parts = str8_split(scratch.arena, string, (U8 *)".", 1, 0);
if(version_parts.first &&
version_parts.first->next &&
version_parts.first->next->next)
{
try_u64_from_str8_c_rules(version_parts.first->string, &version_major);
try_u64_from_str8_c_rules(version_parts.first->next->string, &version_minor);
try_u64_from_str8_c_rules(version_parts.first->next->next->string, &version_patch);
result = Version(version_major, version_minor, version_patch);
}
scratch_end(scratch);
return result;
}
internal String8
str8_from_version(Arena *arena, U64 version)
{
U64 version_major = MajorFromVersion(version);
U64 version_minor = MinorFromVersion(version);
U64 version_patch = PatchFromVersion(version);
String8 result = push_str8f(arena, "%I64d.%I64d.%I64d", version_major, version_minor, version_patch);
return result;
}
////////////////////////////////
//~ rjf: String Path Helpers
internal String8
str8_chop_last_slash(String8 string){
if (string.size > 0){
str8_chop_last_slash(String8 string)
{
if(string.size > 0)
{
U8 *ptr = string.str + string.size - 1;
for (;ptr >= string.str; ptr -= 1){
if (*ptr == '/' || *ptr == '\\'){
for(;ptr >= string.str; ptr -= 1)
{
if(*ptr == '/' || *ptr == '\\')
{
break;
}
}
if (ptr >= string.str){
if(ptr >= string.str)
{
string.size = (U64)(ptr - string.str);
}
else{
else
{
string.size = 0;
}
}
return(string);
return string;
}
internal String8
str8_skip_last_slash(String8 string){
if (string.size > 0){
str8_skip_last_slash(String8 string)
{
if(string.size > 0)
{
U8 *ptr = string.str + string.size - 1;
for (;ptr >= string.str; ptr -= 1){
if (*ptr == '/' || *ptr == '\\'){
for(;ptr >= string.str; ptr -= 1)
{
if(*ptr == '/' || *ptr == '\\')
{
break;
}
}
if (ptr >= string.str){
if(ptr >= string.str)
{
ptr += 1;
string.size = (U64)(string.str + string.size - ptr);
string.str = ptr;
}
}
return(string);
return string;
}
internal String8
@@ -1182,80 +1284,94 @@ str8_chop_last_dot(String8 string)
{
String8 result = string;
U64 p = string.size;
for (;p > 0;){
for(;p > 0;)
{
p -= 1;
if (string.str[p] == '.'){
if(string.str[p] == '.')
{
result = str8_prefix(string, p);
break;
}
}
return(result);
return result;
}
internal String8
str8_skip_last_dot(String8 string){
str8_skip_last_dot(String8 string)
{
String8 result = string;
U64 p = string.size;
for (;p > 0;){
for(;p > 0;)
{
p -= 1;
if (string.str[p] == '.'){
if(string.str[p] == '.')
{
result = str8_skip(string, p + 1);
break;
}
}
return(result);
return result;
}
internal PathStyle
path_style_from_str8(String8 string){
path_style_from_str8(String8 string)
{
PathStyle result = PathStyle_Relative;
if (string.size >= 1 && string.str[0] == '/'){
if(string.size >= 1 && string.str[0] == '/')
{
result = PathStyle_UnixAbsolute;
}
else if (string.size >= 2 &&
char_is_alpha(string.str[0]) &&
string.str[1] == ':'){
if (string.size == 2 ||
char_is_slash(string.str[2])){
else if(string.size >= 2 &&
char_is_alpha(string.str[0]) &&
string.str[1] == ':')
{
if(string.size == 2 || char_is_slash(string.str[2]))
{
result = PathStyle_WindowsAbsolute;
}
}
return(result);
return result;
}
internal String8List
str8_split_path(Arena *arena, String8 string){
str8_split_path(Arena *arena, String8 string)
{
String8List result = str8_split(arena, string, (U8*)"/\\", 2, 0);
return(result);
return result;
}
internal void
str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style){
str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style)
{
Temp scratch = scratch_begin(0, 0);
String8MetaNode *stack = 0;
String8MetaNode *free_meta_node = 0;
String8Node *first = path->first;
MemoryZeroStruct(path);
for (String8Node *node = first, *next = 0;
node != 0;
node = next){
for(String8Node *node = first, *next = 0;
node != 0;
node = next)
{
// save next now
next = node->next;
// cases:
if (node == first && style == PathStyle_WindowsAbsolute){
if(node == first && style == PathStyle_WindowsAbsolute)
{
goto save_without_stack;
}
if (node->string.size == 1 && node->string.str[0] == '.'){
if(node->string.size == 1 && node->string.str[0] == '.')
{
goto do_nothing;
}
if (node->string.size == 2 && node->string.str[0] == '.' && node->string.str[1] == '.'){
if (stack != 0){
if(node->string.size == 2 && node->string.str[0] == '.' && node->string.str[1] == '.')
{
if(stack != 0)
{
goto eliminate_stack_top;
}
else{
else
{
goto save_without_stack;
}
}
@@ -1266,24 +1382,23 @@ str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style){
save_with_stack:
{
str8_list_push_node(path, node);
String8MetaNode *stack_node = free_meta_node;
if (stack_node != 0){
if(stack_node != 0)
{
SLLStackPop(free_meta_node);
}
else{
else
{
stack_node = push_array_no_zero(scratch.arena, String8MetaNode, 1);
}
SLLStackPush(stack, stack_node);
stack_node->node = node;
continue;
}
save_without_stack:
{
str8_list_push_node(path, node);
continue;
}
@@ -1291,13 +1406,13 @@ str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style){
{
path->node_count -= 1;
path->total_size -= stack->node->string.size;
SLLStackPop(stack);
if (stack == 0){
if(stack == 0)
{
path->last = path->first;
}
else{
else
{
path->last = stack->node;
}
continue;
@@ -1402,7 +1517,7 @@ utf8_decode(U8 *str, U64 max){
}break;
case 2:
{
if (2 < max)
if (1 < max)
{
U8 cont_byte = str[1];
if (utf8_class[cont_byte >> 3] == 0)
@@ -1827,10 +1942,10 @@ try_guid_from_string(String8 string, Guid *guid_out)
String8 data4_hi_str = list.first->next->next->next->string;
String8 data4_lo_str = list.first->next->next->next->next->string;
if(str8_is_integer(data1_str, 16) &&
str8_is_integer(data2_str, 16) &&
str8_is_integer(data3_str, 16) &&
str8_is_integer(data4_hi_str, 16) &&
str8_is_integer(data4_lo_str, 16))
str8_is_integer(data2_str, 16) &&
str8_is_integer(data3_str, 16) &&
str8_is_integer(data4_hi_str, 16) &&
str8_is_integer(data4_lo_str, 16))
{
U64 data1 = u64_from_str8(data1_str, 16);
U64 data2 = u64_from_str8(data2_str, 16);
@@ -1838,10 +1953,10 @@ try_guid_from_string(String8 string, Guid *guid_out)
U64 data4_hi = u64_from_str8(data4_hi_str, 16);
U64 data4_lo = u64_from_str8(data4_lo_str, 16);
if(data1 <= max_U32 &&
data2 <= max_U16 &&
data3 <= max_U16 &&
data4_hi <= max_U16 &&
data4_lo <= 0xffffffffffff)
data2 <= max_U16 &&
data3 <= max_U16 &&
data4_hi <= max_U16 &&
data4_lo <= 0xffffffffffff)
{
guid_out->data1 = (U32)data1;
guid_out->data2 = (U16)data2;
@@ -1933,7 +2048,6 @@ escaped_from_raw_str8(Arena *arena, String8 string)
case '\v': {separator_replace = str8_lit("\\v");}break;
case '\\': {separator_replace = str8_lit("\\\\");}break;
case '"': {separator_replace = str8_lit("\\\"");}break;
case '?': {separator_replace = str8_lit("\\?");}break;
}
if(split)
{
@@ -2370,77 +2484,3 @@ str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out)
*block_out = str8_substr(string, range);
return block_out->size;
}
internal U64
str8_deserial_read_uleb128(String8 string, U64 off, U64 *value_out)
{
U64 value = 0;
U64 shift = 0;
U64 cursor = off;
for(;;)
{
U8 byte = 0;
U64 bytes_read = str8_deserial_read_struct(string, cursor, &byte);
if(bytes_read != sizeof(byte))
{
break;
}
U8 val = byte & 0x7fu;
value |= ((U64)val) << shift;
cursor += bytes_read;
shift += 7u;
if((byte & 0x80u) == 0)
{
break;
}
}
if(value_out != 0)
{
*value_out = value;
}
U64 bytes_read = cursor - off;
return bytes_read;
}
internal U64
str8_deserial_read_sleb128(String8 string, U64 off, S64 *value_out)
{
U64 value = 0;
U64 shift = 0;
U64 cursor = off;
for(;;)
{
U8 byte;
U64 bytes_read = str8_deserial_read_struct(string, cursor, &byte);
if(bytes_read != sizeof(byte))
{
break;
}
U8 val = byte & 0x7fu;
value |= ((U64)val) << shift;
cursor += bytes_read;
shift += 7u;
if((byte & 0x80u) == 0)
{
if(shift < sizeof(value) * 8 && (byte & 0x40u) != 0)
{
value |= -(S64)(1ull << shift);
}
break;
}
}
if(value_out != 0)
{
*value_out = value;
}
U64 bytes_read = cursor - off;
return bytes_read;
}
+24 -3
View File
@@ -96,7 +96,7 @@ typedef enum PathStyle
#elif OS_LINUX
PathStyle_SystemAbsolute = PathStyle_UnixAbsolute
#else
# error "absolute path style is undefined for this OS"
# error Absolute path style is undefined for this OS.
#endif
}
PathStyle;
@@ -223,6 +223,7 @@ internal String8 str8_skip(String8 str, U64 amt);
internal String8 str8_postfix(String8 str, U64 size);
internal String8 str8_chop(String8 str, U64 amt);
internal String8 str8_skip_chop_whitespace(String8 string);
internal String8 str8_skip_chop_slashes(String8 string);
////////////////////////////////
//~ rjf: String Formatting & Copying
@@ -287,12 +288,34 @@ internal void str8_list_from_flags(Arena *arena, String8List *list, U32
////////////////////////////////
//~ rjf; String Arrays
internal String8Array str8_array_zero(void);
internal String8Array str8_array_from_list(Arena *arena, String8List *list);
internal String8Array str8_array_reserve(Arena *arena, U64 count);
internal String8Array str8_array_copy(Arena *arena, String8Array array);
////////////////////////////////
//~ rjf: String Version Helpers
internal U64 version_from_str8(String8 string);
internal String8 str8_from_version(Arena *arena, U64 version);
////////////////////////////////
//~ rjf: String Path Helpers
global read_only struct
{
String8 string;
PathStyle path_style;
}
g_path_style_map[] =
{
{ str8_lit_comp(""), PathStyle_Null },
{ str8_lit_comp("relative"), PathStyle_Relative },
{ str8_lit_comp("windows"), PathStyle_WindowsAbsolute },
{ str8_lit_comp("unix"), PathStyle_UnixAbsolute },
{ str8_lit_comp("system"), PathStyle_SystemAbsolute },
};
internal String8 str8_chop_last_slash(String8 string);
internal String8 str8_skip_last_slash(String8 string);
internal String8 str8_chop_last_dot(String8 string);
@@ -407,8 +430,6 @@ internal void * str8_deserial_get_raw_ptr(String8 string, U64 off, U64 size);
internal U64 str8_deserial_read_cstr(String8 string, U64 off, String8 *cstr_out);
internal U64 str8_deserial_read_windows_utf16_string16(String8 string, U64 off, String16 *str_out);
internal U64 str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out);
internal U64 str8_deserial_read_uleb128(String8 string, U64 off, U64 *value_out);
internal U64 str8_deserial_read_sleb128(String8 string, U64 off, S64 *value_out);
#define str8_deserial_read_array(string, off, ptr, count) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr))*(count), sizeof(*(ptr)))
#define str8_deserial_read_struct(string, off, ptr) str8_deserial_read_array(string, off, ptr, 1)
+1 -1
View File
@@ -26,7 +26,7 @@ internal void tctx_init_and_equip(TCTX *tctx);
internal void tctx_release(void);
internal TCTX* tctx_get_equipped(void);
internal Arena* tctx_get_scratch(Arena **conflicts, U64 countt);
internal Arena* tctx_get_scratch(Arena **conflicts, U64 count);
internal void tctx_set_thread_name(String8 name);
internal String8 tctx_get_thread_name(void);
+24 -24
View File
@@ -14,30 +14,30 @@ cv_arch_from_coff_machine(COFF_MachineType machine)
CV_Arch arch = 0;
switch(machine)
{
case COFF_Machine_X64: arch = CV_Arch_X64; break;
case COFF_Machine_X86: arch = CV_Arch_8086; break;
case COFF_Machine_Am33: arch = CV_Arch_AM33; break;
case COFF_Machine_Arm: NotImplemented; break;
case COFF_Machine_Arm64: arch = CV_Arch_ARM64; break;
case COFF_Machine_ArmNt: arch = CV_Arch_ARMNT; break;
case COFF_Machine_Ebc: arch = CV_Arch_EBC; break;
case COFF_Machine_Ia64: arch = CV_Arch_IA64; break;
case COFF_Machine_M32R: arch = CV_Arch_M32R; break;
case COFF_Machine_Mips16: arch = CV_Arch_MIPS16; break;
case COFF_Machine_MipsFpu: NotImplemented; break;
case COFF_Machine_MipsFpu16: NotImplemented; break;
case COFF_Machine_PowerPc: NotImplemented; break;
case COFF_Machine_PowerPcFp: arch = CV_Arch_PPCFP; break;
case COFF_Machine_R4000: NotImplemented; break;
case COFF_Machine_RiscV32: NotImplemented; break;
case COFF_Machine_RiscV64: NotImplemented; break;
case COFF_Machine_RiscV128: NotImplemented; break;
case COFF_Machine_Sh3: arch = CV_Arch_SH3; break;
case COFF_Machine_Sh3Dsp: arch = CV_Arch_SH3DSP; break;
case COFF_Machine_Sh4: arch = CV_Arch_SH4; break;
case COFF_Machine_Sh5: NotImplemented; break;
case COFF_Machine_Thumb: arch = CV_Arch_THUMB; break;
case COFF_Machine_WceMipsV2: NotImplemented; break;
case COFF_MachineType_X64: arch = CV_Arch_X64; break;
case COFF_MachineType_X86: arch = CV_Arch_8086; break;
case COFF_MachineType_Am33: arch = CV_Arch_AM33; break;
case COFF_MachineType_Arm: NotImplemented; break;
case COFF_MachineType_Arm64: arch = CV_Arch_ARM64; break;
case COFF_MachineType_ArmNt: arch = CV_Arch_ARMNT; break;
case COFF_MachineType_Ebc: arch = CV_Arch_EBC; break;
case COFF_MachineType_Ia64: arch = CV_Arch_IA64; break;
case COFF_MachineType_M32R: arch = CV_Arch_M32R; break;
case COFF_MachineType_Mips16: arch = CV_Arch_MIPS16; break;
case COFF_MachineType_MipsFpu: NotImplemented; break;
case COFF_MachineType_MipsFpu16: NotImplemented; break;
case COFF_MachineType_PowerPc: NotImplemented; break;
case COFF_MachineType_PowerPcFp: arch = CV_Arch_PPCFP; break;
case COFF_MachineType_R4000: NotImplemented; break;
case COFF_MachineType_RiscV32: NotImplemented; break;
case COFF_MachineType_RiscV64: NotImplemented; break;
case COFF_MachineType_RiscV128: NotImplemented; break;
case COFF_MachineType_Sh3: arch = CV_Arch_SH3; break;
case COFF_MachineType_Sh3Dsp: arch = CV_Arch_SH3DSP; break;
case COFF_MachineType_Sh4: arch = CV_Arch_SH4; break;
case COFF_MachineType_Sh5: NotImplemented; break;
case COFF_MachineType_Thumb: arch = CV_Arch_THUMB; break;
case COFF_MachineType_WceMipsV2: NotImplemented; break;
}
return arch;
}
+33 -33
View File
@@ -395,48 +395,48 @@ CV_BasicTypeTable:
{FBASICSTR 0x06 "" }
{NOTTRANS 0x07 "" }
{HRESULT 0x08 "HRESULT" }
{CHAR 0x10 "char" }
{SHORT 0x11 "S16" }
{LONG 0x12 "S32" }
{QUAD 0x13 "S64" }
{OCT 0x14 "S128" }
{CHAR 0x10 "CHAR" }
{SHORT 0x11 "SHORT" }
{LONG 0x12 "LONG" }
{QUAD 0x13 "QUAD" }
{OCT 0x14 "OCT" }
{UCHAR 0x20 "UCHAR" }
{USHORT 0x21 "U16" }
{ULONG 0x22 "U32" }
{UQUAD 0x23 "U64" }
{UOCT 0x24 "U128" }
{BOOL8 0x30 "B8" }
{BOOL16 0x31 "B16" }
{BOOL32 0x32 "B32" }
{BOOL64 0x33 "B64" }
{FLOAT32 0x40 "F32" }
{FLOAT64 0x41 "F64" }
{FLOAT80 0x42 "F80" }
{FLOAT128 0x43 "F128" }
{FLOAT48 0x44 "F48" }
{FLOAT32PP 0x45 "F32PP" }
{FLOAT16 0x46 "F16" }
{USHORT 0x21 "USHORT" }
{ULONG 0x22 "ULONG" }
{UQUAD 0x23 "UQUAD" }
{UOCT 0x24 "UOCT" }
{BOOL8 0x30 "BOOL8" }
{BOOL16 0x31 "BOOL16" }
{BOOL32 0x32 "BOOL32" }
{BOOL64 0x33 "BOOL64" }
{FLOAT32 0x40 "FLOAT32" }
{FLOAT64 0x41 "FLOAT64" }
{FLOAT80 0x42 "FLOAT80" }
{FLOAT128 0x43 "FLOAT128" }
{FLOAT48 0x44 "FLOAT48" }
{FLOAT32PP 0x45 "FLOAT32PP" }
{FLOAT16 0x46 "FLOAT16" }
{COMPLEX32 0x50 "ComplexF32" }
{COMPLEX64 0x51 "ComplexF64" }
{COMPLEX80 0x52 "ComplexF80" }
{COMPLEX128 0x53 "ComplexF128" }
{BIT 0x60 "" }
{PASCHAR 0x61 "" }
{BOOL32FF 0x62 "B32FF" }
{INT8 0x68 "S8" }
{UINT8 0x69 "U8" }
{BOOL32FF 0x62 "BOOL32FF" }
{INT8 0x68 "int8" }
{UINT8 0x69 "uint8" }
{RCHAR 0x70 "char" }
{WCHAR 0x71 "WCHAR" }
{INT16 0x72 "S16" }
{UINT16 0x73 "U16" }
{INT32 0x74 "S32" }
{UINT32 0x75 "U32" }
{INT64 0x76 "S64" }
{UINT64 0x77 "U64" }
{INT128 0x78 "S128" }
{UINT128 0x79 "U128" }
{CHAR16 0x7a "CHAR16" }
{CHAR32 0x7b "CHAR32" }
{INT16 0x72 "int16" }
{UINT16 0x73 "uint16" }
{INT32 0x74 "int32" }
{UINT32 0x75 "uint32" }
{INT64 0x76 "int64" }
{UINT64 0x77 "uint64" }
{INT128 0x78 "int128" }
{UINT128 0x79 "uint128" }
{CHAR16 0x7a "char16" }
{CHAR32 0x7b "char32" }
{CHAR8 0x7c "char" }
{PTR 0xf0 "PTR" }
}
-9
View File
@@ -930,15 +930,6 @@ cv_string_from_itemid(Arena *arena, CV_ItemId itemid)
return result;
}
internal String8
cv_string_from_reg_off(Arena *arena, CV_Arch arch, U32 reg, U32 off)
{
Temp scratch = scratch_begin(&arena, 1);
String8 result = push_str8f(arena, "%S+%x", cv_string_from_reg_id(scratch.arena, arch, reg), off);
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_symbol_type(Arena *arena, CV_SymKind symbol_type)
{
-1
View File
@@ -41,7 +41,6 @@ internal String8 cv_string_from_defrange_register_rel_flags(Arena *arena, CV_Def
internal String8 cv_string_from_field_attribs(Arena *arena, CV_FieldAttribs attribs);
internal String8 cv_string_from_itype(Arena *arena, CV_TypeIndex min_itype, CV_TypeIndex itype);
internal String8 cv_string_from_itemid(Arena *arena, CV_ItemId itemid);
internal String8 cv_string_from_reg_off(Arena *arena, CV_Arch arch, U32 reg, U32 off);
internal String8 cv_string_from_symbol_type(Arena *arena, CV_SymKind symbol_type);
internal String8 cv_string_from_symbol_kind(Arena *arena, CV_SymKind kind);
internal String8 cv_string_from_leaf_name(Arena *arena, U32 leaf_type);
File diff suppressed because it is too large Load Diff
+33 -33
View File
@@ -392,48 +392,48 @@ case CV_BasicType_NBASICSTR:{result = str8_lit("");}break;
case CV_BasicType_FBASICSTR:{result = str8_lit("");}break;
case CV_BasicType_NOTTRANS:{result = str8_lit("");}break;
case CV_BasicType_HRESULT:{result = str8_lit("HRESULT");}break;
case CV_BasicType_CHAR:{result = str8_lit("char");}break;
case CV_BasicType_SHORT:{result = str8_lit("S16");}break;
case CV_BasicType_LONG:{result = str8_lit("S32");}break;
case CV_BasicType_QUAD:{result = str8_lit("S64");}break;
case CV_BasicType_OCT:{result = str8_lit("S128");}break;
case CV_BasicType_CHAR:{result = str8_lit("CHAR");}break;
case CV_BasicType_SHORT:{result = str8_lit("SHORT");}break;
case CV_BasicType_LONG:{result = str8_lit("LONG");}break;
case CV_BasicType_QUAD:{result = str8_lit("QUAD");}break;
case CV_BasicType_OCT:{result = str8_lit("OCT");}break;
case CV_BasicType_UCHAR:{result = str8_lit("UCHAR");}break;
case CV_BasicType_USHORT:{result = str8_lit("U16");}break;
case CV_BasicType_ULONG:{result = str8_lit("U32");}break;
case CV_BasicType_UQUAD:{result = str8_lit("U64");}break;
case CV_BasicType_UOCT:{result = str8_lit("U128");}break;
case CV_BasicType_BOOL8:{result = str8_lit("B8");}break;
case CV_BasicType_BOOL16:{result = str8_lit("B16");}break;
case CV_BasicType_BOOL32:{result = str8_lit("B32");}break;
case CV_BasicType_BOOL64:{result = str8_lit("B64");}break;
case CV_BasicType_FLOAT32:{result = str8_lit("F32");}break;
case CV_BasicType_FLOAT64:{result = str8_lit("F64");}break;
case CV_BasicType_FLOAT80:{result = str8_lit("F80");}break;
case CV_BasicType_FLOAT128:{result = str8_lit("F128");}break;
case CV_BasicType_FLOAT48:{result = str8_lit("F48");}break;
case CV_BasicType_FLOAT32PP:{result = str8_lit("F32PP");}break;
case CV_BasicType_FLOAT16:{result = str8_lit("F16");}break;
case CV_BasicType_USHORT:{result = str8_lit("USHORT");}break;
case CV_BasicType_ULONG:{result = str8_lit("ULONG");}break;
case CV_BasicType_UQUAD:{result = str8_lit("UQUAD");}break;
case CV_BasicType_UOCT:{result = str8_lit("UOCT");}break;
case CV_BasicType_BOOL8:{result = str8_lit("BOOL8");}break;
case CV_BasicType_BOOL16:{result = str8_lit("BOOL16");}break;
case CV_BasicType_BOOL32:{result = str8_lit("BOOL32");}break;
case CV_BasicType_BOOL64:{result = str8_lit("BOOL64");}break;
case CV_BasicType_FLOAT32:{result = str8_lit("FLOAT32");}break;
case CV_BasicType_FLOAT64:{result = str8_lit("FLOAT64");}break;
case CV_BasicType_FLOAT80:{result = str8_lit("FLOAT80");}break;
case CV_BasicType_FLOAT128:{result = str8_lit("FLOAT128");}break;
case CV_BasicType_FLOAT48:{result = str8_lit("FLOAT48");}break;
case CV_BasicType_FLOAT32PP:{result = str8_lit("FLOAT32PP");}break;
case CV_BasicType_FLOAT16:{result = str8_lit("FLOAT16");}break;
case CV_BasicType_COMPLEX32:{result = str8_lit("ComplexF32");}break;
case CV_BasicType_COMPLEX64:{result = str8_lit("ComplexF64");}break;
case CV_BasicType_COMPLEX80:{result = str8_lit("ComplexF80");}break;
case CV_BasicType_COMPLEX128:{result = str8_lit("ComplexF128");}break;
case CV_BasicType_BIT:{result = str8_lit("");}break;
case CV_BasicType_PASCHAR:{result = str8_lit("");}break;
case CV_BasicType_BOOL32FF:{result = str8_lit("B32FF");}break;
case CV_BasicType_INT8:{result = str8_lit("S8");}break;
case CV_BasicType_UINT8:{result = str8_lit("U8");}break;
case CV_BasicType_BOOL32FF:{result = str8_lit("BOOL32FF");}break;
case CV_BasicType_INT8:{result = str8_lit("int8");}break;
case CV_BasicType_UINT8:{result = str8_lit("uint8");}break;
case CV_BasicType_RCHAR:{result = str8_lit("char");}break;
case CV_BasicType_WCHAR:{result = str8_lit("WCHAR");}break;
case CV_BasicType_INT16:{result = str8_lit("S16");}break;
case CV_BasicType_UINT16:{result = str8_lit("U16");}break;
case CV_BasicType_INT32:{result = str8_lit("S32");}break;
case CV_BasicType_UINT32:{result = str8_lit("U32");}break;
case CV_BasicType_INT64:{result = str8_lit("S64");}break;
case CV_BasicType_UINT64:{result = str8_lit("U64");}break;
case CV_BasicType_INT128:{result = str8_lit("S128");}break;
case CV_BasicType_UINT128:{result = str8_lit("U128");}break;
case CV_BasicType_CHAR16:{result = str8_lit("CHAR16");}break;
case CV_BasicType_CHAR32:{result = str8_lit("CHAR32");}break;
case CV_BasicType_INT16:{result = str8_lit("int16");}break;
case CV_BasicType_UINT16:{result = str8_lit("uint16");}break;
case CV_BasicType_INT32:{result = str8_lit("int32");}break;
case CV_BasicType_UINT32:{result = str8_lit("uint32");}break;
case CV_BasicType_INT64:{result = str8_lit("int64");}break;
case CV_BasicType_UINT64:{result = str8_lit("uint64");}break;
case CV_BasicType_INT128:{result = str8_lit("int128");}break;
case CV_BasicType_UINT128:{result = str8_lit("uint128");}break;
case CV_BasicType_CHAR16:{result = str8_lit("char16");}break;
case CV_BasicType_CHAR32:{result = str8_lit("char32");}break;
case CV_BasicType_CHAR8:{result = str8_lit("char");}break;
case CV_BasicType_PTR:{result = str8_lit("PTR");}break;
}
+17 -19
View File
@@ -52,14 +52,13 @@ coff_section_flag_from_align_size(U64 align)
}
internal String8
coff_name_from_section_header(String8 raw_coff, COFF_SectionHeader *header, U64 string_table_off)
coff_name_from_section_header(String8 string_table, COFF_SectionHeader *header)
{
String8 name = str8_cstring_capped(header->name, header->name + sizeof(header->name));
if (name.str[0] == '/') {
String8 ascii_off = str8_skip(name, 1);
U64 name_rel_off = u64_from_str8(ascii_off, 10);
U64 name_off = name_rel_off + string_table_off;
name = str8_cstring_capped(raw_coff.str + name_off, raw_coff.str + raw_coff.size);
String8 name_off_str = str8_skip(name, 1);
U64 name_off = u64_from_str8(name_off_str, 10);
name = str8_cstring_capped(string_table.str + name_off, string_table.str+string_table.size);
}
return name;
}
@@ -94,12 +93,11 @@ coff_parse_section_name(String8 full_name, String8 *name_out, String8 *postfix_o
}
internal String8
coff_read_symbol_name(String8 raw_coff, U64 string_table_off, COFF_SymbolName *name)
coff_read_symbol_name(String8 string_table, COFF_SymbolName *name)
{
String8 name_str = str8_lit("");
if (name->long_name.zeroes == 0) {
U64 name_string_off = string_table_off + name->long_name.string_table_offset;
str8_deserial_read_cstr(raw_coff, name_string_off, &name_str);
str8_deserial_read_cstr(string_table, name->long_name.string_table_offset, &name_str);
} else {
U32 i;
for (i = 0; i < sizeof(name->short_name); ++i) {
@@ -174,8 +172,8 @@ internal U64
coff_apply_size_from_reloc(COFF_MachineType machine, COFF_RelocType x)
{
switch (machine) {
case COFF_Machine_X64: return coff_apply_size_from_reloc_x64(x);
case COFF_Machine_X86: return coff_apply_size_from_reloc_x86(x);
case COFF_MachineType_X64: return coff_apply_size_from_reloc_x64(x);
case COFF_MachineType_X86: return coff_apply_size_from_reloc_x86(x);
default: NotImplemented;
}
return 0;
@@ -221,7 +219,7 @@ coff_make_import_header_by_name(Arena *arena,
flags |= COFF_ImportBy_Name << COFF_ImportHeader_ImportByShift;
COFF_ImportHeader header = {0};
header.sig1 = COFF_Machine_Unknown;
header.sig1 = COFF_MachineType_Unknown;
header.sig2 = max_U16;
header.version = 0;
header.machine = machine;
@@ -264,7 +262,7 @@ coff_make_import_header_by_ordinal(Arena *arena,
flags |= COFF_ImportBy_Ordinal << COFF_ImportHeader_ImportByShift;
COFF_ImportHeader header = {0};
header.sig1 = COFF_Machine_Unknown;
header.sig1 = COFF_MachineType_Unknown;
header.sig2 = max_U16;
header.version = 0;
header.machine = machine;
@@ -298,8 +296,8 @@ coff_word_size_from_machine(COFF_MachineType machine)
{
U64 result = 0;
switch (machine) {
case COFF_Machine_X64: result = 8; break;
case COFF_Machine_X86: result = 4; break;
case COFF_MachineType_X64: result = 8; break;
case COFF_MachineType_X86: result = 4; break;
}
return result;
}
@@ -332,11 +330,11 @@ arch_from_coff_machine(COFF_MachineType machine)
{
Arch result = Arch_Null;
switch (machine) {
case COFF_Machine_Unknown: break;
case COFF_Machine_X86: result = Arch_x86; break;
case COFF_Machine_X64: result = Arch_x64; break;
case COFF_Machine_Arm: result = Arch_arm32; break;
case COFF_Machine_Arm64: result = Arch_arm64; break;
case COFF_MachineType_Unknown: break;
case COFF_MachineType_X86: result = Arch_x86; break;
case COFF_MachineType_X64: result = Arch_x64; break;
case COFF_MachineType_Arm: result = Arch_arm32; break;
case COFF_MachineType_Arm64: result = Arch_arm64; break;
}
return result;
}
+29 -29
View File
@@ -47,31 +47,31 @@ enum
typedef U16 COFF_MachineType;
enum
{
COFF_Machine_Unknown = 0x0,
COFF_Machine_X86 = 0x14c,
COFF_Machine_X64 = 0x8664,
COFF_Machine_Am33 = 0x1d3,
COFF_Machine_Arm = 0x1c0,
COFF_Machine_Arm64 = 0xaa64,
COFF_Machine_ArmNt = 0x1c4,
COFF_Machine_Ebc = 0xebc,
COFF_Machine_Ia64 = 0x200,
COFF_Machine_M32R = 0x9041,
COFF_Machine_Mips16 = 0x266,
COFF_Machine_MipsFpu = 0x366,
COFF_Machine_MipsFpu16 = 0x466,
COFF_Machine_PowerPc = 0x1f0,
COFF_Machine_PowerPcFp = 0x1f1,
COFF_Machine_R4000 = 0x166,
COFF_Machine_RiscV32 = 0x5032,
COFF_Machine_RiscV64 = 0x5064,
COFF_Machine_RiscV128 = 0x5128,
COFF_Machine_Sh3 = 0x1a2,
COFF_Machine_Sh3Dsp = 0x1a3,
COFF_Machine_Sh4 = 0x1a6,
COFF_Machine_Sh5 = 0x1a8,
COFF_Machine_Thumb = 0x1c2,
COFF_Machine_WceMipsV2 = 0x169
COFF_MachineType_Unknown = 0x0,
COFF_MachineType_X86 = 0x14c,
COFF_MachineType_X64 = 0x8664,
COFF_MachineType_Am33 = 0x1d3,
COFF_MachineType_Arm = 0x1c0,
COFF_MachineType_Arm64 = 0xaa64,
COFF_MachineType_ArmNt = 0x1c4,
COFF_MachineType_Ebc = 0xebc,
COFF_MachineType_Ia64 = 0x200,
COFF_MachineType_M32R = 0x9041,
COFF_MachineType_Mips16 = 0x266,
COFF_MachineType_MipsFpu = 0x366,
COFF_MachineType_MipsFpu16 = 0x466,
COFF_MachineType_PowerPc = 0x1f0,
COFF_MachineType_PowerPcFp = 0x1f1,
COFF_MachineType_R4000 = 0x166,
COFF_MachineType_RiscV32 = 0x5032,
COFF_MachineType_RiscV64 = 0x5064,
COFF_MachineType_RiscV128 = 0x5128,
COFF_MachineType_Sh3 = 0x1a2,
COFF_MachineType_Sh3Dsp = 0x1a3,
COFF_MachineType_Sh4 = 0x1a6,
COFF_MachineType_Sh5 = 0x1a8,
COFF_MachineType_Thumb = 0x1c2,
COFF_MachineType_WceMipsV2 = 0x169
};
typedef struct COFF_FileHeader
@@ -87,7 +87,7 @@ typedef struct COFF_FileHeader
typedef struct COFF_BigObjHeader
{
U16 sig1; // COFF_Machine_Unknown
U16 sig1; // COFF_MachineType_Unknown
U16 sig2; // max_U16
U16 version; // 2
COFF_MachineType machine;
@@ -547,7 +547,7 @@ enum
typedef struct COFF_ImportHeader
{
U16 sig1; // COFF_Machine_Unknown
U16 sig1; // COFF_MachineType_Unknown
U16 sig2; // max_U16
U16 version; // 0
COFF_MachineType machine;
@@ -567,13 +567,13 @@ typedef struct COFF_ImportHeader
internal U64 coff_align_size_from_section_flags(COFF_SectionFlags flags);
internal COFF_SectionFlags coff_section_flag_from_align_size (U64 align);
internal String8 coff_name_from_section_header(String8 raw_coff, COFF_SectionHeader *header, U64 string_table_off);
internal String8 coff_name_from_section_header(String8 string_table, COFF_SectionHeader *header);
internal void coff_parse_section_name (String8 full_name, String8 *name_out, String8 *postfix_out);
////////////////////////////////
// Symbol
internal String8 coff_read_symbol_name(String8 raw_coff, U64 string_table_off, COFF_SymbolName *name);
internal String8 coff_read_symbol_name(String8 string_table, COFF_SymbolName *name);
////////////////////////////////
// Reloc
+30 -30
View File
@@ -21,31 +21,31 @@ read_only struct
String8 string;
COFF_MachineType machine;
} g_coff_machine_map[] = {
{ str8_lit_comp(""), COFF_Machine_Unknown },
{ str8_lit_comp("X86"), COFF_Machine_X86 },
{ str8_lit_comp("Amd64"), COFF_Machine_X64 },
{ str8_lit_comp("X64"), COFF_Machine_X64 },
{ str8_lit_comp("Am33"), COFF_Machine_Am33 },
{ str8_lit_comp("Arm"), COFF_Machine_Arm },
{ str8_lit_comp("Arm64"), COFF_Machine_Arm64 },
{ str8_lit_comp("ArmNt"), COFF_Machine_ArmNt },
{ str8_lit_comp("Ebc"), COFF_Machine_Ebc },
{ str8_lit_comp("Ia64"), COFF_Machine_Ia64 },
{ str8_lit_comp("M32r"), COFF_Machine_M32R },
{ str8_lit_comp("Mips16"), COFF_Machine_Mips16 },
{ str8_lit_comp("MipsFpu"), COFF_Machine_MipsFpu },
{ str8_lit_comp("MipsFpu16"), COFF_Machine_MipsFpu16 },
{ str8_lit_comp("PowerPc"), COFF_Machine_PowerPc },
{ str8_lit_comp("PowerPcFp"), COFF_Machine_PowerPcFp },
{ str8_lit_comp("R4000"), COFF_Machine_R4000 },
{ str8_lit_comp("RiscV32"), COFF_Machine_RiscV32 },
{ str8_lit_comp("RiscV64"), COFF_Machine_RiscV64 },
{ str8_lit_comp("Sh3"), COFF_Machine_Sh3 },
{ str8_lit_comp("Sh3Dsp"), COFF_Machine_Sh3Dsp },
{ str8_lit_comp("Sh4"), COFF_Machine_Sh4 },
{ str8_lit_comp("Sh5"), COFF_Machine_Sh5 },
{ str8_lit_comp("Thumb"), COFF_Machine_Thumb },
{ str8_lit_comp("WceMipsV2"), COFF_Machine_WceMipsV2 },
{ str8_lit_comp(""), COFF_MachineType_Unknown },
{ str8_lit_comp("X86"), COFF_MachineType_X86 },
{ str8_lit_comp("Amd64"), COFF_MachineType_X64 },
{ str8_lit_comp("X64"), COFF_MachineType_X64 },
{ str8_lit_comp("Am33"), COFF_MachineType_Am33 },
{ str8_lit_comp("Arm"), COFF_MachineType_Arm },
{ str8_lit_comp("Arm64"), COFF_MachineType_Arm64 },
{ str8_lit_comp("ArmNt"), COFF_MachineType_ArmNt },
{ str8_lit_comp("Ebc"), COFF_MachineType_Ebc },
{ str8_lit_comp("Ia64"), COFF_MachineType_Ia64 },
{ str8_lit_comp("M32r"), COFF_MachineType_M32R },
{ str8_lit_comp("Mips16"), COFF_MachineType_Mips16 },
{ str8_lit_comp("MipsFpu"), COFF_MachineType_MipsFpu },
{ str8_lit_comp("MipsFpu16"), COFF_MachineType_MipsFpu16 },
{ str8_lit_comp("PowerPc"), COFF_MachineType_PowerPc },
{ str8_lit_comp("PowerPcFp"), COFF_MachineType_PowerPcFp },
{ str8_lit_comp("R4000"), COFF_MachineType_R4000 },
{ str8_lit_comp("RiscV32"), COFF_MachineType_RiscV32 },
{ str8_lit_comp("RiscV64"), COFF_MachineType_RiscV64 },
{ str8_lit_comp("Sh3"), COFF_MachineType_Sh3 },
{ str8_lit_comp("Sh3Dsp"), COFF_MachineType_Sh3Dsp },
{ str8_lit_comp("Sh4"), COFF_MachineType_Sh4 },
{ str8_lit_comp("Sh5"), COFF_MachineType_Sh5 },
{ str8_lit_comp("Thumb"), COFF_MachineType_Thumb },
{ str8_lit_comp("WceMipsV2"), COFF_MachineType_WceMipsV2 },
};
read_only static struct {
@@ -446,10 +446,10 @@ internal String8
coff_string_from_reloc(COFF_MachineType machine, COFF_RelocType x)
{
switch (machine) {
case COFF_Machine_X86: return coff_string_from_reloc_x86(x);
case COFF_Machine_X64: return coff_string_from_reloc_x64(x);
case COFF_Machine_Arm: return coff_string_from_reloc_arm(x);
case COFF_Machine_Arm64: return coff_string_from_reloc_arm64(x);
case COFF_MachineType_X86: return coff_string_from_reloc_x86(x);
case COFF_MachineType_X64: return coff_string_from_reloc_x64(x);
case COFF_MachineType_Arm: return coff_string_from_reloc_arm(x);
case COFF_MachineType_Arm64: return coff_string_from_reloc_arm64(x);
}
return str8_zero();
}
@@ -462,7 +462,7 @@ coff_machine_from_string(String8 string)
return g_coff_machine_map[i].machine;
}
}
return COFF_Machine_Unknown;
return COFF_MachineType_Unknown;
}
internal COFF_ImportType
+90 -90
View File
@@ -7,10 +7,10 @@ coff_is_big_obj(String8 raw_coff)
B32 is_big_obj = 0;
if (raw_coff.size >= sizeof(COFF_BigObjHeader)) {
COFF_BigObjHeader *file_header32 = (COFF_BigObjHeader*)(raw_coff.str);
is_big_obj = file_header32->sig1 == COFF_Machine_Unknown &&
file_header32->sig2 == max_U16 &&
file_header32->version >= 2 &&
MemoryCompare(file_header32->magic, g_coff_big_header_magic, sizeof(file_header32->magic)) == 0;
is_big_obj = file_header32->sig1 == COFF_MachineType_Unknown &&
file_header32->sig2 == max_U16 &&
file_header32->version >= 2 &&
MemoryCompare(file_header32->magic, g_coff_big_header_magic, sizeof(file_header32->magic)) == 0;
}
return is_big_obj;
}
@@ -26,19 +26,19 @@ coff_is_obj(String8 raw_coff)
// validate machine
B32 is_machine_type_valid = 0;
switch (header->machine) {
case COFF_Machine_Unknown:
case COFF_Machine_X86: case COFF_Machine_X64:
case COFF_Machine_Am33: case COFF_Machine_Arm:
case COFF_Machine_Arm64: case COFF_Machine_ArmNt:
case COFF_Machine_Ebc: case COFF_Machine_Ia64:
case COFF_Machine_M32R: case COFF_Machine_Mips16:
case COFF_Machine_MipsFpu:case COFF_Machine_MipsFpu16:
case COFF_Machine_PowerPc:case COFF_Machine_PowerPcFp:
case COFF_Machine_R4000: case COFF_Machine_RiscV32:
case COFF_Machine_RiscV64:case COFF_Machine_RiscV128:
case COFF_Machine_Sh3: case COFF_Machine_Sh3Dsp:
case COFF_Machine_Sh4: case COFF_Machine_Sh5:
case COFF_Machine_Thumb: case COFF_Machine_WceMipsV2:
case COFF_MachineType_Unknown:
case COFF_MachineType_X86: case COFF_MachineType_X64:
case COFF_MachineType_Am33: case COFF_MachineType_Arm:
case COFF_MachineType_Arm64: case COFF_MachineType_ArmNt:
case COFF_MachineType_Ebc: case COFF_MachineType_Ia64:
case COFF_MachineType_M32R: case COFF_MachineType_Mips16:
case COFF_MachineType_MipsFpu:case COFF_MachineType_MipsFpu16:
case COFF_MachineType_PowerPc:case COFF_MachineType_PowerPcFp:
case COFF_MachineType_R4000: case COFF_MachineType_RiscV32:
case COFF_MachineType_RiscV64:case COFF_MachineType_RiscV128:
case COFF_MachineType_Sh3: case COFF_MachineType_Sh3Dsp:
case COFF_MachineType_Sh4: case COFF_MachineType_Sh5:
case COFF_MachineType_Thumb: case COFF_MachineType_WceMipsV2:
{
is_machine_type_valid = 1;
}break;
@@ -99,33 +99,33 @@ coff_file_header_info_from_data(String8 raw_coff)
COFF_BigObjHeader *header32 = (COFF_BigObjHeader*)raw_coff.str;
info.is_big_obj = 1;
info.machine = header32->machine;
info.header_size = sizeof(COFF_BigObjHeader);
info.section_array_off = sizeof(COFF_BigObjHeader);
info.section_count_no_null = header32->section_count;
info.string_table_off = header32->symbol_table_foff + sizeof(COFF_Symbol32) * header32->symbol_count;
info.symbol_size = sizeof(COFF_Symbol32);
info.symbol_off = header32->symbol_table_foff;
info.symbol_count = header32->symbol_count;
info.symbol_size = sizeof(COFF_Symbol32);
info.header_range = rng_1u64(0, sizeof(COFF_BigObjHeader));
info.section_table_range = rng_1u64(info.header_range.max, info.header_range.max + sizeof(COFF_SectionHeader) * header32->section_count);
info.symbol_table_range = rng_1u64(header32->symbol_table_foff, header32->symbol_table_foff + sizeof(COFF_Symbol32) * header32->symbol_count);
info.string_table_range = rng_1u64(info.symbol_table_range.max, raw_coff.size);
} else if (coff_is_obj(raw_coff)) {
COFF_FileHeader *header16 = (COFF_FileHeader*)raw_coff.str;
info.is_big_obj = 0;
info.machine = header16->machine;
info.header_size = sizeof(COFF_FileHeader);
info.section_array_off = sizeof(COFF_FileHeader);
info.section_count_no_null = header16->section_count;
info.string_table_off = header16->symbol_table_foff + sizeof(COFF_Symbol16) * header16->symbol_count;
info.symbol_size = sizeof(COFF_Symbol16);
info.symbol_off = header16->symbol_table_foff;
info.symbol_count = header16->symbol_count;
info.symbol_size = sizeof(COFF_Symbol16);
info.header_range = rng_1u64(0, sizeof(COFF_FileHeader));
info.section_table_range = rng_1u64(info.header_range.max, info.header_range.max + sizeof(COFF_SectionHeader) * header16->section_count);
info.symbol_table_range = rng_1u64(header16->symbol_table_foff, header16->symbol_table_foff + sizeof(COFF_Symbol16) * header16->symbol_count);
info.string_table_range = rng_1u64(info.symbol_table_range.max, raw_coff.size);
}
return info;
}
internal COFF_ParsedSymbol
coff_parse_symbol32(String8 raw_coff, U64 string_table_off, COFF_Symbol32 *sym32)
coff_parse_symbol32(String8 string_table, COFF_Symbol32 *sym32)
{
COFF_ParsedSymbol result = {0};
result.name = coff_read_symbol_name(raw_coff, string_table_off, &sym32->name);
result.name = coff_read_symbol_name(string_table, &sym32->name);
result.value = sym32->value;
result.section_number = sym32->section_number;
result.type = sym32->type;
@@ -135,10 +135,10 @@ coff_parse_symbol32(String8 raw_coff, U64 string_table_off, COFF_Symbol32 *sym32
}
internal COFF_ParsedSymbol
coff_parse_symbol16(String8 raw_coff, U64 string_table_off, COFF_Symbol16 *sym16)
coff_parse_symbol16(String8 string_table, COFF_Symbol16 *sym16)
{
COFF_ParsedSymbol result = {0};
result.name = coff_read_symbol_name(raw_coff, string_table_off, &sym16->name);
result.name = coff_read_symbol_name(string_table, &sym16->name);
result.value = sym16->value;
if (sym16->section_number == COFF_Symbol_DebugSection16) {
result.section_number = COFF_Symbol_DebugSection32;
@@ -163,11 +163,11 @@ coff_symbol_array_from_data_16(Arena *arena, String8 raw_coff, U64 symbol_array_
Rng1U64 sym16_arr_range = rng_1u64(symbol_array_off, symbol_array_off + sizeof(COFF_Symbol16) * symbol_count);
String8 raw_sym16_arr = str8_substr(raw_coff, sym16_arr_range);
COFF_Symbol16 *sym16_arr = (COFF_Symbol16 *)raw_sym16_arr.str;
for (U64 isymbol = 0, count = raw_sym16_arr.size / sizeof(COFF_Symbol16); isymbol < count; isymbol += 1) {
COFF_Symbol16 *sym16 = &sym16_arr[isymbol];
COFF_Symbol32 *sym32 = &result.v[isymbol];
sym32->name = sym16->name;
sym32->value = sym16->value;
if (sym16->section_number == COFF_Symbol_DebugSection16) {
@@ -185,7 +185,7 @@ coff_symbol_array_from_data_16(Arena *arena, String8 raw_coff, U64 symbol_array_
for (U64 iaux = isymbol+1, iaux_hi = Min(count, iaux+sym16->aux_symbol_count); iaux < iaux_hi; iaux += 1) {
COFF_Symbol16 *aux16 = sym16_arr + iaux;
COFF_Symbol32 *aux32 = result.v + iaux;
// 32bit COFF uses 16bit aux symbols
MemoryCopy(aux32, aux16, sizeof(COFF_Symbol16));
MemoryZero((U8 *)aux32 + sizeof(COFF_Symbol16), sizeof(COFF_Symbol32)-sizeof(COFF_Symbol16));
@@ -286,11 +286,11 @@ coff_resource_string_from_str16(Arena *arena, String16 string)
{
AssertAlways(string.size <= max_U16);
U16 size16 = (U16)string.size;
U16 *buffer = push_array_no_zero(arena, U16, size16 + 1);
MemoryCopy(buffer + 0, &size16, sizeof(size16));
MemoryCopy(buffer + 1, string.str, size16 * sizeof(string.str[0]));
return str8_array(buffer, size16 + 1);
}
@@ -358,14 +358,14 @@ coff_read_resource(Arena *arena, String8 raw_res, U64 off, COFF_ParsedResource *
{
String8 raw_header = str8_skip(raw_res, off);
U64 header_cursor = 0;
// prefix
COFF_ResourceHeaderPrefix prefix = {0};
header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &prefix);
Assert(prefix.header_size >= sizeof(COFF_ResourceHeaderPrefix));
raw_header = str8_prefix(raw_header, prefix.header_size);
// header
COFF_ResourceID16 type_16 = {0};
COFF_ResourceID16 name_16 = {0};
@@ -377,11 +377,11 @@ coff_read_resource(Arena *arena, String8 raw_res, U64 off, COFF_ParsedResource *
header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->version);
header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->characteristics);
Assert(prefix.header_size == header_cursor);
// convert utf-16 resource ids to utf-8
res_out->type = coff_utf8_resource_id_from_utf16(arena, &type_16);
res_out->name = coff_utf8_resource_id_from_utf16(arena, &name_16);
// read data
U64 data_read_size = str8_deserial_read_block(raw_res, off + prefix.header_size, prefix.data_size, &res_out->data);
Assert(prefix.data_size == data_read_size);
@@ -411,14 +411,14 @@ coff_write_resource_id(Arena *arena, COFF_ResourceID id)
{
String8 result = str8_zero();
switch (id.type) {
case COFF_ResourceIDType_Null: break;
case COFF_ResourceIDType_Number: {
result = coff_resource_number_from_u16(arena, id.u.number);
} break;
case COFF_ResourceIDType_String: {
result = coff_resource_string_from_str8(arena, id.u.string);
} break;
default: InvalidPath;
case COFF_ResourceIDType_Null: break;
case COFF_ResourceIDType_Number: {
result = coff_resource_number_from_u16(arena, id.u.number);
} break;
case COFF_ResourceIDType_String: {
result = coff_resource_string_from_str8(arena, id.u.string);
} break;
default: InvalidPath;
}
return result;
}
@@ -435,13 +435,13 @@ coff_write_resource(Arena *arena,
String8 data)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
COFF_ResourceHeaderPrefix *prefix = push_array(scratch.arena, COFF_ResourceHeaderPrefix, 1);
String8 packed_type = coff_write_resource_id(scratch.arena, type);
String8 packed_name = coff_write_resource_id(scratch.arena, name);
// prefix + header
str8_list_push(scratch.arena, &list, str8_struct(prefix));
str8_list_push(scratch.arena, &list, packed_type);
@@ -451,24 +451,24 @@ coff_write_resource(Arena *arena,
str8_list_push(scratch.arena, &list, str8_struct(&language_id));
str8_list_push(scratch.arena, &list, str8_struct(&version));
str8_list_push(scratch.arena, &list, str8_struct(&characteristics));
prefix->data_size = safe_cast_u32(data.size);
prefix->header_size = safe_cast_u32(list.total_size);
// data
str8_list_push(scratch.arena, &list, data);
// magic
str8_list_push_front(scratch.arena, &list, str8_array_fixed(g_coff_res_magic));
// align
U64 align_size = AlignPow2(list.total_size, COFF_ResourceAlign) - list.total_size;
U8 *align = push_array(scratch.arena, U8, align_size);
str8_list_push(scratch.arena, &list, str8(align, align_size));
// join
String8 res = str8_list_join(arena, &list, 0);
scratch_end(scratch);
return res;
}
@@ -476,15 +476,15 @@ coff_write_resource(Arena *arena,
internal int
coff_resource_id_compar(void *raw_a, void *raw_b)
{
int cmp = 0;
int cmp;
COFF_ResourceID *a = raw_a;
COFF_ResourceID *b = raw_b;
if (a->type == b->type) {
switch (a->type) {
case COFF_ResourceIDType_Null: cmp = 0; break;
case COFF_ResourceIDType_Number: cmp = MemoryCompare(&a->u.number, &b->u.number, sizeof(a->u.number)); break;
case COFF_ResourceIDType_String: cmp = strncmp((char *)a->u.string.str, (char *)b->u.string.str, Min(a->u.string.size, b->u.string.size)); break;
default: InvalidPath; break;
default:
case COFF_ResourceIDType_Null: cmp = 0; break;
case COFF_ResourceIDType_Number: cmp = MemoryCompare(&a->u.number, &b->u.number, sizeof(a->u.number)); break;
case COFF_ResourceIDType_String: cmp = strncmp((char *)a->u.string.str, (char *)b->u.string.str, Min(a->u.string.size, b->u.string.size)); break;
}
} else {
cmp = a->type < b->type ? -1 : a->type > b->type ? +1 : 0;
@@ -499,7 +499,7 @@ coff_is_import(String8 raw_archive_member)
if (raw_archive_member.size >= sizeof(U16)*2) {
U16 *sig1 = (U16*)raw_archive_member.str;
U16 *sig2 = sig1 + 1;
is_import = *sig1 == COFF_Machine_Unknown && *sig2 == 0xffff;
is_import = *sig1 == COFF_MachineType_Unknown && *sig2 == 0xffff;
}
return is_import;
}
@@ -563,10 +563,10 @@ coff_parse_archive_member_header(String8 raw_archive, U64 offset, COFF_ParsedArc
String8 mode = str8_skip_chop_whitespace(str8_cstring_capped(header->mode, header->mode + sizeof(header->mode) ));
String8 size = str8_skip_chop_whitespace(str8_cstring_capped(header->size, header->size + sizeof(header->size) ));
String8 end = str8_cstring_capped(header->end, header->end + sizeof(header->end));
U32 data_size = u32_from_str8(size, 10);
U64 data_off = offset + sizeof(COFF_ArchiveMemberHeader);
header_out->name = name;
header_out->time_stamp = u32_from_str8(date, 10);
header_out->user_id = u32_from_str8(user_id, 10);
@@ -574,7 +574,7 @@ coff_parse_archive_member_header(String8 raw_archive, U64 offset, COFF_ParsedArc
header_out->mode = mode;
header_out->is_end_correct = str8_match_lit("`\n", end, 0);
header_out->data_range = rng_1u64(data_off, data_off + data_size);
return sizeof(*header);
}
return 0;
@@ -584,7 +584,7 @@ internal COFF_ArchiveFirstMember
coff_parse_first_archive_member(COFF_ArchiveMember *member)
{
Assert(str8_match_lit("/", member->header.name, 0));
U64 cursor = 0;
U32 symbol_count = 0;
@@ -597,17 +597,17 @@ coff_parse_first_archive_member(COFF_ArchiveMember *member)
Rng1U64 string_table_range = rng_1u64(cursor, member->data.size);
cursor += dim_1u64(string_table_range);
String8 raw_member_offsets = str8_substr(member->data, member_offsets_range);
U32 *member_offsets = (U32 *)raw_member_offsets.str;
U64 member_offset_count = raw_member_offsets.size / sizeof(member_offsets[0]);
COFF_ArchiveFirstMember result = {0};
result.symbol_count = symbol_count;
result.member_offset_count = member_offset_count;
result.member_offsets = member_offsets;
result.string_table = str8_substr(member->data, string_table_range);
return result;
}
@@ -615,7 +615,7 @@ internal COFF_ArchiveSecondMember
coff_parse_second_archive_member(COFF_ArchiveMember *member)
{
COFF_ArchiveSecondMember result = {0};
if (str8_match_lit("/", member->header.name, 0)) {
U64 cursor = 0;
@@ -632,13 +632,13 @@ coff_parse_second_archive_member(COFF_ArchiveMember *member)
cursor += dim_1u64(symbol_indices_range);
Rng1U64 string_table_range = rng_1u64(cursor, member->data.size);
String8 raw_member_offsets = str8_substr(member->data, member_offsets_range);
String8 raw_indices = str8_substr(member->data, symbol_indices_range);
U32 *member_offsets = (U32 *)raw_member_offsets.str;
U64 member_offset_count = raw_member_offsets.size / sizeof(member_offsets[0]);
U16 *symbol_indices = (U16 *)raw_indices.str;
U64 symbol_index_count = raw_indices.size / sizeof(symbol_indices[0]);
@@ -650,7 +650,7 @@ coff_parse_second_archive_member(COFF_ArchiveMember *member)
result.symbol_index_count = symbol_index_count;
result.string_table = str8_substr(member->data, string_table_range);
}
return result;
}
@@ -683,7 +683,7 @@ coff_parse_import(String8 raw_archive_member, U64 offset, COFF_ParsedArchiveImpo
Rng1U64 data_range = rng_1u64(offset + sizeof(*header), offset + sizeof(*header) + header->data_size);
String8 raw_data = str8_substr(raw_archive_member, data_range);
U64 data_cursor = 0;
header_out->version = header->version;
header_out->machine = header->machine;
header_out->time_stamp = header->time_stamp;
@@ -744,7 +744,7 @@ coff_regular_archive_member_iter_next(String8 raw_archive, U64 *offset, COFF_Arc
if (member_out->header.is_end_correct) {
member_out->offset = *offset;
member_out->data = str8_substr(raw_archive, member_out->header.data_range);
U64 read_size = AlignPow2(header_size + dim_1u64(member_out->header.data_range), COFF_Archive_MemberAlign);
*offset += read_size;
@@ -771,19 +771,19 @@ coff_thin_archive_member_iter_next(String8 raw_archive, U64 *offset, COFF_Archiv
member_out->header.is_end_correct = 0;
U64 header_size = coff_parse_archive_member_header(raw_archive, *offset, &member_out->header);
if (member_out->header.is_end_correct) {
Rng1U64 data_in_archive_range = {0};
if (str8_match_lit("/", member_out->header.name, 0) || str8_match_lit("//", member_out->header.name, 0)) {
data_in_archive_range = member_out->header.data_range;
}
member_out->offset = *offset;
member_out->data = str8_substr(raw_archive, data_in_archive_range);
U64 read_size = AlignPow2(header_size + dim_1u64(data_in_archive_range), COFF_Archive_MemberAlign);
*offset += read_size;
is_parsed = 1;
}
@@ -806,9 +806,9 @@ coff_archive_parse_from_member_list(COFF_ArchiveMemberList member_list)
COFF_ArchiveMember first_header = {0};
COFF_ArchiveMember second_header = {0};
COFF_ArchiveMember long_names_member = {0};
COFF_ArchiveMemberNode *ptr = member_list.first;
if (ptr) {
if (str8_match_lit("/", ptr->data.header.name, 0)) {
if (ptr->data.header.is_end_correct) {
@@ -821,7 +821,7 @@ coff_archive_parse_from_member_list(COFF_ArchiveMemberList member_list)
} else {
error = str8_lit("missing first header");
}
if (!error.size && ptr) {
if (str8_match_lit("/", ptr->data.header.name, 0)) {
if (ptr->data.header.is_end_correct) {
@@ -833,7 +833,7 @@ coff_archive_parse_from_member_list(COFF_ArchiveMemberList member_list)
}
}
}
if (!error.size && ptr) {
if (str8_match_lit("//", ptr->data.header.name, 0)) {
if (ptr->data.header.is_end_correct) {
@@ -853,7 +853,7 @@ coff_archive_parse_from_member_list(COFF_ArchiveMemberList member_list)
parse.second_member = coff_parse_second_archive_member(&second_header);
parse.long_names = long_names_member.data;
parse.error = error;
return parse;
}
@@ -894,9 +894,9 @@ coff_archive_parse_from_data(String8 raw_archive)
{
COFF_ArchiveType type = coff_archive_type_from_data(raw_archive);
switch (type) {
case COFF_Archive_Null: break;
case COFF_Archive_Regular: return coff_regular_archive_parse_from_data(raw_archive);
case COFF_Archive_Thin: return coff_thin_archive_parse_from_data(raw_archive);
case COFF_Archive_Null: break;
case COFF_Archive_Regular: return coff_regular_archive_parse_from_data(raw_archive);
case COFF_Archive_Thin: return coff_thin_archive_parse_from_data(raw_archive);
}
COFF_ArchiveParse null_parse = {0};
return null_parse;
+6 -5
View File
@@ -9,12 +9,13 @@ typedef struct COFF_FileHeaderInfo
B32 is_big_obj;
COFF_MachineType machine;
U64 header_size;
U64 section_array_off;
U64 section_count_no_null;
U64 string_table_off;
U64 symbol_size;
U64 symbol_off;
U64 symbol_count;
Rng1U64 header_range;
Rng1U64 section_table_range;
Rng1U64 symbol_table_range;
Rng1U64 string_table_range;
} COFF_FileHeaderInfo;
////////////////////////////////
@@ -249,8 +250,8 @@ internal COFF_FileHeaderInfo coff_file_header_info_from_data(String8 raw_coff);
////////////////////////////////
// Symbol
internal COFF_ParsedSymbol coff_parse_symbol32(String8 raw_coff, U64 string_table_off, COFF_Symbol32 *sym32);
internal COFF_ParsedSymbol coff_parse_symbol16(String8 raw_coff, U64 string_table_off, COFF_Symbol16 *sym16);
internal COFF_ParsedSymbol coff_parse_symbol32(String8 string_table, COFF_Symbol32 *sym32);
internal COFF_ParsedSymbol coff_parse_symbol16(String8 string_table, COFF_Symbol16 *sym16);
internal COFF_Symbol32Array coff_symbol_array_from_data_16(Arena *arena, String8 data, U64 symbol_array_off, U64 symbol_count);
internal COFF_Symbol32Array coff_symbol_array_from_data_32(Arena *arena, String8 data, U64 symbol_array_off, U64 symbol_count);
+17 -9
View File
@@ -4,17 +4,19 @@
////////////////////////////////
//~ rjf: Entity Kinds
@table(name display_string)
@table(name code_name display_string)
CTRL_EntityKindTable:
{
{Root "Root" }
{Machine "Machine" }
{Process "Process" }
{Thread "Thread" }
{Module "Module" }
{EntryPoint "Entry Point" }
{DebugInfoPath "Debug Info Path" }
{PendingThreadName "Pending Thread Name" }
{Root root "Root" }
{Machine machine "Machine" }
{Process process "Process" }
{Thread thread "Thread" }
{Module module "Module" }
{EntryPoint entry_point "Entry Point" }
{DebugInfoPath debug_info_path "Debug Info Path" }
{PendingThreadName pending_thread_name "Pending Thread Name" }
{PendingThreadColor pending_thread_color "Pending Thread Color" }
{Breakpoint breakpoint "Breakpoint" }
}
@enum CTRL_EntityKind:
@@ -24,6 +26,12 @@ CTRL_EntityKindTable:
COUNT,
}
@data(String8) ctrl_entity_kind_code_name_table:
{
`{0}`,
@expand(CTRL_EntityKindTable a) `str8_lit_comp("$(a.code_name)")`
}
@data(String8) ctrl_entity_kind_display_string_table:
{
`{0}`,
+1773 -908
View File
File diff suppressed because it is too large Load Diff
+271 -327
View File
@@ -13,227 +13,51 @@ typedef U64 CTRL_MachineID;
#define CTRL_MachineID_Local (1)
////////////////////////////////
//~ rjf: Meta Evaluation Types
//~ rjf: User Breakpoint Types
//- rjf: auto-checkbox b32s
typedef struct CTRL_CheckB32 CTRL_CheckB32;
struct CTRL_CheckB32
typedef U32 CTRL_UserBreakpointFlags;
enum
{
B32 b32;
CTRL_UserBreakpointFlag_BreakOnWrite = (1<<0),
CTRL_UserBreakpointFlag_BreakOnRead = (1<<1),
CTRL_UserBreakpointFlag_BreakOnExecute = (1<<2),
};
struct_members(CTRL_CheckB32)
typedef enum CTRL_UserBreakpointKind
{
member_lit_comp(CTRL_CheckB32, type(B32), b32),
};
struct_type(CTRL_CheckB32);
CTRL_UserBreakpointKind_Null,
CTRL_UserBreakpointKind_FileNameAndLineColNumber,
CTRL_UserBreakpointKind_Expression,
CTRL_UserBreakpointKind_COUNT
}
CTRL_UserBreakpointKind;
//- rjf: styled string types
ptr_type(CTRL_PlainString8__str_ptr_type, type(U8), .flags = TypeFlag_IsPlainText,.count_delimiter_name = str8_lit_comp("size"));
ptr_type(CTRL_CodeString8__str_ptr_type, type(U8), .flags = TypeFlag_IsCodeText, .count_delimiter_name = str8_lit_comp("size"));
ptr_type(CTRL_PathString8__str_ptr_type, type(U8), .flags = TypeFlag_IsPathText, .count_delimiter_name = str8_lit_comp("size"));
Member CTRL_PlainString8__members[] =
typedef struct CTRL_UserBreakpoint CTRL_UserBreakpoint;
struct CTRL_UserBreakpoint
{
member_lit_comp(String8, &CTRL_PlainString8__str_ptr_type, str, .pretty_name = str8_lit_comp("Contents")),
member_lit_comp(String8, type(U64), size, .pretty_name = str8_lit_comp("Size")),
};
Member CTRL_CodeString8__members[] =
{
member_lit_comp(String8, &CTRL_CodeString8__str_ptr_type, str, .pretty_name = str8_lit_comp("Contents")),
member_lit_comp(String8, type(U64), size, .pretty_name = str8_lit_comp("Size")),
};
Member CTRL_PathString8__members[] =
{
member_lit_comp(String8, &CTRL_PathString8__str_ptr_type, str, .pretty_name = str8_lit_comp("Contents")),
member_lit_comp(String8, type(U64), size, .pretty_name = str8_lit_comp("Size")),
};
named_struct_type(CTRL_PlainString8, String8, .name = str8_lit_comp("string"));
named_struct_type(CTRL_CodeString8, String8, .name = str8_lit_comp("string"));
named_struct_type(CTRL_PathString8, String8, .name = str8_lit_comp("string"));
//- rjf: meta evaluation callstack types
typedef struct CTRL_MetaEvalFrame CTRL_MetaEvalFrame;
struct CTRL_MetaEvalFrame
{
U64 vaddr;
U64 inline_depth;
};
ptr_type(CTRL_MetaEvalFrame__vaddr_type, type(void), .flags = TypeFlag_IsExternal, .size = sizeof(U64));
struct_members(CTRL_MetaEvalFrame)
{
member_lit_comp(CTRL_MetaEvalFrame, &CTRL_MetaEvalFrame__vaddr_type, vaddr),
member_lit_comp(CTRL_MetaEvalFrame, type(U64), inline_depth),
};
struct_type(CTRL_MetaEvalFrame, .name = str8_lit_comp("callstack_frame"));
typedef struct CTRL_MetaEvalFrameArray CTRL_MetaEvalFrameArray;
struct CTRL_MetaEvalFrameArray
{
U64 count;
CTRL_MetaEvalFrame *v;
};
ptr_type(CTRL_MetaEvalFrameArray__v_ptr_type, type(CTRL_MetaEvalFrame), .count_delimiter_name = str8_lit_comp("count"));
struct_members(CTRL_MetaEvalFrameArray)
{
member_lit_comp(CTRL_MetaEvalFrameArray, type(U64), count, .pretty_name = str8_lit_comp("Frame Count")),
{str8_lit_comp("v"), str8_lit_comp("Frame Addresses"), &CTRL_MetaEvalFrameArray__v_ptr_type, OffsetOf(CTRL_MetaEvalFrameArray, v)},
};
struct_type(CTRL_MetaEvalFrameArray, .name = str8_lit_comp("callstack_frames"));
//- rjf: meta evaluation instance types
typedef struct CTRL_MetaEval CTRL_MetaEval;
struct CTRL_MetaEval
{
#define CTRL_MetaEval_MemberXList \
X(B32, enabled, "Enabled")\
X(B32, frozen, "Frozen")\
X(U64, hit_count, "Hit Count")\
X(U64, id, "ID")\
X(Rng1U64, vaddr_range, "Address Range")\
X(U32, color, "Color")\
X(CTRL_CheckB32, debug_subprocesses,"Debug Subprocesses")\
Y(String8, type(CTRL_CodeString8), label, "Label")\
Y(String8, type(CTRL_PathString8), exe, "Executable Path")\
Y(String8, type(CTRL_PathString8), dbg, "Debug Info Path")\
Y(String8, type(CTRL_PlainString8), args, "Arguments")\
Y(String8, type(CTRL_PathString8), working_directory, "Working Directory")\
Y(String8, type(CTRL_CodeString8), entry_point, "Custom Entry Point")\
Y(String8, type(CTRL_PathString8), stdout_path, "Standard Output Path")\
Y(String8, type(CTRL_PathString8), stderr_path, "Standard Error Path")\
Y(String8, type(CTRL_PathString8), stdin_path, "Standard Input Path")\
Y(String8, type(CTRL_PathString8), source_location, "Source Location")\
Y(String8, type(CTRL_CodeString8), function_location, "Function Location")\
Y(String8, type(CTRL_CodeString8), address_location, "Address Location")\
Y(String8, type(CTRL_PathString8), source_path, "Source Path")\
Y(String8, type(CTRL_PathString8), destination_path, "Destination Path")\
Y(String8, type(CTRL_CodeString8), type, "Type")\
Y(String8, type(CTRL_CodeString8), view_rule, "View Rule")\
Y(String8, type(CTRL_CodeString8), condition, "Condition")\
X(CTRL_MetaEvalFrameArray, callstack, "Call Stack")
#define X(T, name, pretty_name) T name;
#define Y(T, ti, name, pretty_name) T name;
CTRL_MetaEval_MemberXList
#undef X
#undef Y
};
struct_members(CTRL_MetaEval)
{
#define X(T, name, pretty_name_) member_lit_comp(CTRL_MetaEval, type(T), name, .pretty_name = str8_lit_comp(pretty_name_)),
#define Y(T, ti, name, pretty_name_) member_lit_comp(CTRL_MetaEval, (ti), name, .pretty_name = str8_lit_comp(pretty_name_)),
CTRL_MetaEval_MemberXList
#undef X
#undef Y
};
struct_type(CTRL_MetaEval);
//- rjf: filters on main meta evaluation bundle
struct_members(CTRL_BreakpointMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(B32), enabled, .pretty_name = str8_lit_comp("Enabled")),
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
member_lit_comp(CTRL_MetaEval, type(U64), hit_count, .pretty_name = str8_lit_comp("Hit Count")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Label")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), condition, .pretty_name = str8_lit_comp("Condition")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), source_location, .pretty_name = str8_lit_comp("Source Location")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), function_location, .pretty_name = str8_lit_comp("Function Location")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), address_location, .pretty_name = str8_lit_comp("Address Location")),
CTRL_UserBreakpointKind kind;
CTRL_UserBreakpointFlags flags;
U64 id;
String8 string;
TxtPt pt;
U64 size;
String8 condition;
};
struct_members(CTRL_TargetMetaEval)
typedef struct CTRL_UserBreakpointNode CTRL_UserBreakpointNode;
struct CTRL_UserBreakpointNode
{
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Label")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), exe, .pretty_name = str8_lit_comp("Executable")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PlainString8),args, .pretty_name = str8_lit_comp("Arguments")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), working_directory, .pretty_name = str8_lit_comp("Working Directory")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), entry_point, .pretty_name = str8_lit_comp("Custom Entry Point")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), stdout_path, .pretty_name = str8_lit_comp("Standard Output Path")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), stderr_path, .pretty_name = str8_lit_comp("Standard Error Path")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), stdin_path, .pretty_name = str8_lit_comp("Standard Input Path")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CheckB32), debug_subprocesses, .pretty_name = str8_lit_comp("Debug Subprocesses")),
CTRL_UserBreakpointNode *next;
CTRL_UserBreakpoint v;
};
struct_members(CTRL_PinMetaEval)
typedef struct CTRL_UserBreakpointList CTRL_UserBreakpointList;
struct CTRL_UserBreakpointList
{
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Expression")),
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), source_location, .pretty_name = str8_lit_comp("Source Location")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), address_location, .pretty_name = str8_lit_comp("Address Location")),
};
struct_members(CTRL_FilePathMapMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), source_path, .pretty_name = str8_lit_comp("Source Path")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), destination_path, .pretty_name = str8_lit_comp("Destination Path")),
};
struct_members(CTRL_AutoViewRuleMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), type, .pretty_name = str8_lit_comp("Type")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), view_rule, .pretty_name = str8_lit_comp("View Rule")),
};
struct_members(CTRL_MachineMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(B32), frozen, .pretty_name = str8_lit_comp("Frozen")),
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Name")),
};
struct_members(CTRL_ProcessMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(B32), frozen, .pretty_name = str8_lit_comp("Frozen")),
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Name")),
member_lit_comp(CTRL_MetaEval, type(U64), id, .pretty_name = str8_lit_comp("ID")),
};
struct_members(CTRL_ModuleMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Name")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), exe, .pretty_name = str8_lit_comp("Executable Path")),
member_lit_comp(CTRL_MetaEval, type(CTRL_PathString8), dbg, .pretty_name = str8_lit_comp("Debug Info Path")),
member_lit_comp(CTRL_MetaEval, type(Rng1U64), vaddr_range, .pretty_name = str8_lit_comp("Address Range")),
};
struct_members(CTRL_ThreadMetaEval)
{
member_lit_comp(CTRL_MetaEval, type(B32), frozen, .pretty_name = str8_lit_comp("Frozen")),
member_lit_comp(CTRL_MetaEval, type(U32), color, .pretty_name = str8_lit_comp("Color")),
member_lit_comp(CTRL_MetaEval, type(CTRL_CodeString8), label, .pretty_name = str8_lit_comp("Name")),
member_lit_comp(CTRL_MetaEval, type(U64), id, .pretty_name = str8_lit_comp("ID")),
member_lit_comp(CTRL_MetaEval, type(CTRL_MetaEvalFrameArray), callstack, .pretty_name = str8_lit_comp("Call Stack")),
};
named_struct_type(CTRL_BreakpointMetaEval, CTRL_MetaEval, .name = str8_lit_comp("breakpoint"));
named_struct_type(CTRL_TargetMetaEval, CTRL_MetaEval, .name = str8_lit_comp("target"));
named_struct_type(CTRL_PinMetaEval, CTRL_MetaEval, .name = str8_lit_comp("pin"));
named_struct_type(CTRL_FilePathMapMetaEval, CTRL_MetaEval, .name = str8_lit_comp("file_path_map"));
named_struct_type(CTRL_AutoViewRuleMetaEval,CTRL_MetaEval, .name = str8_lit_comp("auto_view_rule"));
named_struct_type(CTRL_MachineMetaEval, CTRL_MetaEval, .name = str8_lit_comp("machine"));
named_struct_type(CTRL_ProcessMetaEval, CTRL_MetaEval, .name = str8_lit_comp("process"));
named_struct_type(CTRL_ModuleMetaEval, CTRL_MetaEval, .name = str8_lit_comp("module"));
named_struct_type(CTRL_ThreadMetaEval, CTRL_MetaEval, .name = str8_lit_comp("thread"));
//- rjf: meta evaluation array
typedef struct CTRL_MetaEvalArray CTRL_MetaEvalArray;
struct CTRL_MetaEvalArray
{
CTRL_MetaEval *v;
CTRL_UserBreakpointNode *first;
CTRL_UserBreakpointNode *last;
U64 count;
};
ptr_type(CTRL_MetaEvalArray__v_ptr_type, type(CTRL_BreakpointMetaEval), .count_delimiter_name = str8_lit_comp("count"));
struct_members(CTRL_MetaEvalArray)
{
{str8_lit_comp("v"), {0}, &CTRL_MetaEvalArray__v_ptr_type, OffsetOf(CTRL_MetaEvalArray, v)},
member_lit_comp(CTRL_MetaEvalArray, type(U64), count),
};
struct_type(CTRL_MetaEvalArray);
////////////////////////////////
//~ rjf: Entity Handle Types
@@ -279,12 +103,14 @@ struct CTRL_Entity
CTRL_EntityKind kind;
Arch arch;
B32 is_frozen;
B32 is_soloed;
U32 rgba;
CTRL_Handle handle;
U64 id;
Rng1U64 vaddr_range;
U64 stack_base;
U64 timestamp;
CTRL_UserBreakpointFlags bp_flags;
String8 string;
};
@@ -340,21 +166,45 @@ struct CTRL_EntityStringChunkNode
U64 size;
};
typedef struct CTRL_EntityStore CTRL_EntityStore;
struct CTRL_EntityStore
read_only global U64 ctrl_entity_string_bucket_chunk_sizes[] =
{
16,
64,
256,
1024,
4096,
16384,
65536,
0xffffffffffffffffull,
};
typedef struct CTRL_EntityCtx CTRL_EntityCtx;
struct CTRL_EntityCtx
{
CTRL_Entity *root;
U64 hash_slots_count;
CTRL_EntityHashSlot *hash_slots;
U64 entity_kind_counts[CTRL_EntityKind_COUNT];
U64 entity_kind_alloc_gens[CTRL_EntityKind_COUNT];
};
typedef struct CTRL_EntityCtxRWStore CTRL_EntityCtxRWStore;
struct CTRL_EntityCtxRWStore
{
Arena *arena;
CTRL_Entity *root;
CTRL_EntityCtx ctx;
CTRL_Entity *free;
CTRL_EntityHashSlot *hash_slots;
CTRL_EntityHashNode *hash_node_free;
U64 hash_slots_count;
CTRL_EntityStringChunkNode *free_string_chunks[8];
U64 entity_kind_counts[CTRL_EntityKind_COUNT];
Arena *entity_kind_lists_arenas[CTRL_EntityKind_COUNT];
U64 entity_kind_lists_gens[CTRL_EntityKind_COUNT];
U64 entity_kind_alloc_gens[CTRL_EntityKind_COUNT];
CTRL_EntityList entity_kind_lists[CTRL_EntityKind_COUNT];
CTRL_EntityStringChunkNode *free_string_chunks[ArrayCount(ctrl_entity_string_bucket_chunk_sizes)];
};
typedef struct CTRL_EntityCtxLookupAccel CTRL_EntityCtxLookupAccel;
struct CTRL_EntityCtxLookupAccel
{
Arena *arena;
Arena *entity_kind_arrays_arenas[CTRL_EntityKind_COUNT];
CTRL_EntityArray entity_kind_arrays[CTRL_EntityKind_COUNT];
U64 entity_kind_arrays_gens[CTRL_EntityKind_COUNT];
};
////////////////////////////////
@@ -404,32 +254,21 @@ struct CTRL_Unwind
////////////////////////////////
//~ rjf: Call Stack Types
typedef struct CTRL_CallStackInlineFrame CTRL_CallStackInlineFrame;
struct CTRL_CallStackInlineFrame
{
CTRL_CallStackInlineFrame *next;
CTRL_CallStackInlineFrame *prev;
RDI_InlineSite *inline_site;
};
typedef struct CTRL_CallStackFrame CTRL_CallStackFrame;
struct CTRL_CallStackFrame
{
CTRL_CallStackInlineFrame *first_inline_frame;
CTRL_CallStackInlineFrame *last_inline_frame;
U64 inline_frame_count;
U64 unwind_count;
U64 inline_depth;
void *regs;
RDI_Parsed *rdi;
RDI_Procedure *procedure;
};
typedef struct CTRL_CallStack CTRL_CallStack;
struct CTRL_CallStack
{
CTRL_CallStackFrame *frames;
U64 concrete_frame_count;
U64 inline_frame_count;
U64 total_frame_count;
U64 frames_count;
CTRL_CallStackFrame **concrete_frames;
U64 concrete_frames_count;
};
////////////////////////////////
@@ -476,44 +315,6 @@ struct CTRL_Spoof
U64 new_ip_value;
};
////////////////////////////////
//~ rjf: User Breakpoint Types
typedef enum CTRL_UserBreakpointKind
{
CTRL_UserBreakpointKind_Null,
CTRL_UserBreakpointKind_FileNameAndLineColNumber,
CTRL_UserBreakpointKind_SymbolNameAndOffset,
CTRL_UserBreakpointKind_VirtualAddress,
CTRL_UserBreakpointKind_COUNT
}
CTRL_UserBreakpointKind;
typedef struct CTRL_UserBreakpoint CTRL_UserBreakpoint;
struct CTRL_UserBreakpoint
{
CTRL_UserBreakpointKind kind;
String8 string;
TxtPt pt;
U64 u64;
String8 condition;
};
typedef struct CTRL_UserBreakpointNode CTRL_UserBreakpointNode;
struct CTRL_UserBreakpointNode
{
CTRL_UserBreakpointNode *next;
CTRL_UserBreakpoint v;
};
typedef struct CTRL_UserBreakpointList CTRL_UserBreakpointList;
struct CTRL_UserBreakpointList
{
CTRL_UserBreakpointNode *first;
CTRL_UserBreakpointNode *last;
U64 count;
};
////////////////////////////////
//~ rjf: Evaluation Spaces
@@ -573,7 +374,6 @@ struct CTRL_Msg
String8 stdin_path;
CTRL_TrapList traps;
CTRL_UserBreakpointList user_bps;
CTRL_MetaEvalArray meta_evals;
};
typedef struct CTRL_MsgNode CTRL_MsgNode;
@@ -618,10 +418,12 @@ typedef enum CTRL_EventKind
//- rjf: debug info changes
CTRL_EventKind_ModuleDebugInfoPathChange,
//- rjf: debug strings / decorations
//- rjf: debug strings / decorations / markup
CTRL_EventKind_DebugString,
CTRL_EventKind_ThreadName,
CTRL_EventKind_ThreadColor,
CTRL_EventKind_SetBreakpoint,
CTRL_EventKind_UnsetBreakpoint,
//- rjf: memory
CTRL_EventKind_MemReserve,
@@ -677,6 +479,7 @@ struct CTRL_Event
U64 timestamp;
U32 exception_code;
U32 rgba;
CTRL_UserBreakpointFlags bp_flags;
String8 string;
};
@@ -702,13 +505,19 @@ typedef struct CTRL_ProcessMemoryRangeHashNode CTRL_ProcessMemoryRangeHashNode;
struct CTRL_ProcessMemoryRangeHashNode
{
CTRL_ProcessMemoryRangeHashNode *next;
// rjf: key
Rng1U64 vaddr_range;
B32 zero_terminated;
Rng1U64 vaddr_range_clamped;
U128 hash;
HS_ID id;
// rjf: staleness info
U64 mem_gen;
// rjf: metadata
U64 working_count;
U64 last_time_requested_us;
B32 is_taken;
U64 last_user_clock_idx_touched;
};
typedef struct CTRL_ProcessMemoryRangeHashSlot CTRL_ProcessMemoryRangeHashSlot;
@@ -725,6 +534,7 @@ struct CTRL_ProcessMemoryCacheNode
CTRL_ProcessMemoryCacheNode *prev;
Arena *arena;
CTRL_Handle handle;
HS_Root root;
U64 range_hash_slots_count;
CTRL_ProcessMemoryRangeHashSlot *range_hash_slots;
};
@@ -800,6 +610,53 @@ struct CTRL_ThreadRegCache
CTRL_ThreadRegCacheStripe *stripes;
};
////////////////////////////////
//~ rjf: Call Stack Cache Types
typedef struct CTRL_CallStackCacheNode CTRL_CallStackCacheNode;
struct CTRL_CallStackCacheNode
{
CTRL_CallStackCacheNode *next;
CTRL_CallStackCacheNode *prev;
// rjf: key
CTRL_Handle thread;
U64 reg_gen;
U64 mem_gen;
// rjf: counters
U64 scope_touch_count;
U64 working_count;
// rjf: value
Arena *arena;
CTRL_CallStack call_stack;
};
typedef struct CTRL_CallStackCacheSlot CTRL_CallStackCacheSlot;
struct CTRL_CallStackCacheSlot
{
CTRL_CallStackCacheNode *first;
CTRL_CallStackCacheNode *last;
};
typedef struct CTRL_CallStackCacheStripe CTRL_CallStackCacheStripe;
struct CTRL_CallStackCacheStripe
{
Arena *arena;
OS_Handle rw_mutex;
OS_Handle cv;
};
typedef struct CTRL_CallStackCache CTRL_CallStackCache;
struct CTRL_CallStackCache
{
U64 slots_count;
CTRL_CallStackCacheSlot *slots;
U64 stripes_count;
CTRL_CallStackCacheStripe *stripes;
};
////////////////////////////////
//~ rjf: Module Image Info Cache Types
@@ -815,6 +672,8 @@ struct CTRL_ModuleImageInfoCacheNode
U64 entry_point_voff;
Rng1U64 tls_vaddr_range;
String8 initial_debug_info_path;
Rng1U64 raddbg_section_voff_range;
String8 raddbg_data;
};
typedef struct CTRL_ModuleImageInfoCacheSlot CTRL_ModuleImageInfoCacheSlot;
@@ -857,6 +716,45 @@ struct CTRL_DbgDirNode
U64 module_direct_count;
};
////////////////////////////////
//~ rjf: Control Thread Evaluation Scopes
typedef struct CTRL_EvalScope CTRL_EvalScope;
struct CTRL_EvalScope
{
DI_Scope *di_scope;
E_BaseCtx base_ctx;
E_IRCtx ir_ctx;
E_InterpretCtx interpret_ctx;
};
////////////////////////////////
//~ rjf: Control Cache Accessing Scopes
typedef struct CTRL_ScopeCallStackTouch CTRL_ScopeCallStackTouch;
struct CTRL_ScopeCallStackTouch
{
CTRL_ScopeCallStackTouch *next;
CTRL_CallStackCacheStripe *stripe;
CTRL_CallStackCacheNode *node;
};
typedef struct CTRL_Scope CTRL_Scope;
struct CTRL_Scope
{
CTRL_Scope *next;
CTRL_ScopeCallStackTouch *first_call_stack_touch;
CTRL_ScopeCallStackTouch *last_call_stack_touch;
};
typedef struct CTRL_TCTX CTRL_TCTX;
struct CTRL_TCTX
{
Arena *arena;
CTRL_Scope *free_scope;
CTRL_ScopeCallStackTouch *free_call_stack_touch;
};
////////////////////////////////
//~ rjf: Wakeup Hook Function Types
@@ -879,6 +777,7 @@ struct CTRL_State
// rjf: caches
CTRL_ProcessMemoryCache process_memory_cache;
CTRL_ThreadRegCache thread_reg_cache;
CTRL_CallStackCache call_stack_cache;
CTRL_ModuleImageInfoCache module_image_info_cache;
// rjf: user -> ctrl msg ring buffer
@@ -899,18 +798,19 @@ struct CTRL_State
OS_Handle c2u_ring_cv;
// rjf: ctrl thread state
U64 ctrl_thread_run_state;
String8 ctrl_thread_log_path;
OS_Handle ctrl_thread;
Log *ctrl_thread_log;
CTRL_EntityStore *ctrl_thread_entity_store;
OS_Handle ctrl_thread_entity_ctx_rw_mutex;
CTRL_EntityCtxRWStore *ctrl_thread_entity_store;
E_Cache *ctrl_thread_eval_cache;
Arena *dmn_event_arena;
DMN_EventNode *first_dmn_event_node;
DMN_EventNode *last_dmn_event_node;
DMN_EventNode *free_dmn_event_node;
Arena *user_entry_point_arena;
String8List user_entry_points;
Arena *user_meta_eval_arena;
CTRL_MetaEvalArray user_meta_evals;
U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64];
U64 process_counter;
Arena *dbg_dir_arena;
@@ -923,6 +823,14 @@ struct CTRL_State
U64 u2ms_ring_read_pos;
OS_Handle u2ms_ring_mutex;
OS_Handle u2ms_ring_cv;
// rjf: user -> call stack builder ring buffer
U64 u2csb_ring_size;
U8 *u2csb_ring_base;
U64 u2csb_ring_write_pos;
U64 u2csb_ring_read_pos;
OS_Handle u2csb_ring_mutex;
OS_Handle u2csb_ring_cv;
};
////////////////////////////////
@@ -937,6 +845,8 @@ read_only global CTRL_Entity ctrl_entity_nil =
&ctrl_entity_nil,
&ctrl_entity_nil,
};
thread_static CTRL_TCTX *ctrl_tctx = 0;
thread_static CTRL_EntityCtxLookupAccel *ctrl_entity_ctx_lookup_accel = 0;
////////////////////////////////
//~ rjf: Logging Markup
@@ -949,8 +859,12 @@ read_only global CTRL_Entity ctrl_entity_nil =
internal U64 ctrl_hash_from_string(String8 string);
internal U64 ctrl_hash_from_handle(CTRL_Handle handle);
internal CTRL_EventCause ctrl_event_cause_from_dmn_event_kind(DMN_EventKind event_kind);
internal CTRL_ExceptionKind ctrl_exception_kind_from_dmn(DMN_ExceptionKind kind);
internal String8 ctrl_string_from_event_kind(CTRL_EventKind kind);
internal String8 ctrl_string_from_msg_kind(CTRL_MsgKind kind);
internal CTRL_EntityKind ctrl_entity_kind_from_string(String8 string);
internal DMN_TrapFlags ctrl_dmn_trap_flags_from_user_breakpoint_flags(CTRL_UserBreakpointFlags flags);
internal CTRL_UserBreakpointFlags ctrl_user_breakpoint_flags_from_dmn_trap_flags(DMN_TrapFlags flags);
////////////////////////////////
//~ rjf: Handle Type Functions
@@ -960,6 +874,8 @@ internal CTRL_Handle ctrl_handle_make(CTRL_MachineID machine_id, DMN_Handle dmn_
internal B32 ctrl_handle_match(CTRL_Handle a, CTRL_Handle b);
internal void ctrl_handle_list_push(Arena *arena, CTRL_HandleList *list, CTRL_Handle *pair);
internal CTRL_HandleList ctrl_handle_list_copy(Arena *arena, CTRL_HandleList *src);
internal String8 ctrl_string_from_handle(Arena *arena, CTRL_Handle handle);
internal CTRL_Handle ctrl_handle_from_string(String8 string);
////////////////////////////////
//~ rjf: Trap Type Functions
@@ -1004,38 +920,21 @@ internal CTRL_Event ctrl_event_from_serialized_string(Arena *arena, String8 stri
//- rjf: entity list data structures
internal void ctrl_entity_list_push(Arena *arena, CTRL_EntityList *list, CTRL_Entity *entity);
internal CTRL_EntityList ctrl_entity_list_from_handle_list(Arena *arena, CTRL_EntityStore *store, CTRL_HandleList *list);
internal CTRL_EntityList ctrl_entity_list_from_handle_list(Arena *arena, CTRL_EntityCtx *ctx, CTRL_HandleList *list);
#define ctrl_entity_list_first(list) ((list)->first ? (list)->first->v : &ctrl_entity_nil)
//- rjf: entity array data structure
internal CTRL_EntityArray ctrl_entity_array_from_list(Arena *arena, CTRL_EntityList *list);
#define ctrl_entity_array_first(array) ((array)->count != 0 ? (array)->v[0] : &ctrl_entity_nil)
//- rjf: cache creation/destruction
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);
//- rjf: entity construction/deletion
internal CTRL_Entity *ctrl_entity_alloc(CTRL_EntityStore *store, CTRL_Entity *parent, CTRL_EntityKind kind, Arch arch, CTRL_Handle handle, U64 id);
internal void ctrl_entity_release(CTRL_EntityStore *store, CTRL_Entity *entity);
//- rjf: entity equipment
internal void ctrl_entity_equip_string(CTRL_EntityStore *store, CTRL_Entity *entity, String8 string);
//- rjf: entity store lookups
internal CTRL_Entity *ctrl_entity_from_handle(CTRL_EntityStore *store, CTRL_Handle handle);
//- rjf: entity context (entity group read-only) functions
internal CTRL_Entity *ctrl_entity_from_handle(CTRL_EntityCtx *ctx, CTRL_Handle handle);
internal CTRL_Entity *ctrl_entity_child_from_kind(CTRL_Entity *parent, CTRL_EntityKind kind);
internal CTRL_Entity *ctrl_entity_ancestor_from_kind(CTRL_Entity *entity, CTRL_EntityKind kind);
internal CTRL_Entity *ctrl_process_from_entity(CTRL_Entity *entity);
internal CTRL_Entity *ctrl_module_from_process_vaddr(CTRL_Entity *process, U64 vaddr);
internal DI_Key ctrl_dbgi_key_from_module(CTRL_Entity *module);
internal CTRL_EntityList ctrl_modules_from_dbgi_key(Arena *arena, CTRL_EntityStore *store, DI_Key *dbgi_key);
internal CTRL_Entity *ctrl_module_from_thread_candidates(CTRL_EntityStore *store, CTRL_Entity *thread, CTRL_EntityList *candidates);
internal CTRL_EntityList ctrl_entity_list_from_kind(CTRL_EntityStore *store, CTRL_EntityKind kind);
internal CTRL_Entity *ctrl_module_from_thread_candidates(CTRL_EntityCtx *ctx, CTRL_Entity *thread, CTRL_EntityList *candidates);
internal U64 ctrl_vaddr_from_voff(CTRL_Entity *module, U64 voff);
internal U64 ctrl_voff_from_vaddr(CTRL_Entity *module, U64 vaddr);
internal Rng1U64 ctrl_vaddr_range_from_voff_range(CTRL_Entity *module, Rng1U64 voff_range);
@@ -1047,8 +946,37 @@ internal CTRL_EntityRec ctrl_entity_rec_depth_first(CTRL_Entity *entity, CTRL_En
#define ctrl_entity_rec_depth_first_pre(entity, subtree_root) ctrl_entity_rec_depth_first((entity), (subtree_root), OffsetOf(CTRL_Entity, next), OffsetOf(CTRL_Entity, first))
#define ctrl_entity_rec_depth_first_post(entity, subtree_root) ctrl_entity_rec_depth_first((entity), (subtree_root), OffsetOf(CTRL_Entity, prev), OffsetOf(CTRL_Entity, last))
//- rjf: entity ctx r/w store state functions
internal CTRL_EntityCtxRWStore *ctrl_entity_ctx_rw_store_alloc(void);
internal void ctrl_entity_ctx_rw_store_release(CTRL_EntityCtxRWStore *store);
//- rjf: string allocation/deletion
internal U64 ctrl_name_bucket_num_from_string_size(U64 size);
internal String8 ctrl_entity_string_alloc(CTRL_EntityCtxRWStore *store, String8 string);
internal void ctrl_entity_string_release(CTRL_EntityCtxRWStore *store, String8 string);
//- rjf: entity construction/deletion
internal CTRL_Entity *ctrl_entity_alloc(CTRL_EntityCtxRWStore *store, CTRL_Entity *parent, CTRL_EntityKind kind, Arch arch, CTRL_Handle handle, U64 id);
internal void ctrl_entity_release(CTRL_EntityCtxRWStore *store, CTRL_Entity *entity);
//- rjf: entity equipment
internal void ctrl_entity_equip_string(CTRL_EntityCtxRWStore *store, CTRL_Entity *entity, String8 string);
//- rjf: accelerated entity context lookups
internal CTRL_EntityCtxLookupAccel *ctrl_thread_entity_ctx_lookup_accel(void);
internal CTRL_EntityArray ctrl_entity_array_from_kind(CTRL_EntityCtx *ctx, CTRL_EntityKind kind);
internal CTRL_EntityList ctrl_modules_from_dbgi_key(Arena *arena, CTRL_EntityCtx *ctx, DI_Key *dbgi_key);
internal CTRL_Entity *ctrl_thread_from_id(CTRL_EntityCtx *ctx, U64 id);
//- rjf: applying events to entity caches
internal void ctrl_entity_store_apply_events(CTRL_EntityStore *store, CTRL_EventList *list);
internal void ctrl_entity_store_apply_events(CTRL_EntityCtxRWStore *store, CTRL_EventList *list);
////////////////////////////////
//~ rjf: Cache Accessing Scopes
internal CTRL_Scope *ctrl_scope_open(void);
internal void ctrl_scope_close(CTRL_Scope *scope);
internal void ctrl_scope_touch_call_stack_node__stripe_r_guarded(CTRL_Scope *scope, CTRL_CallStackCacheStripe *stripe, CTRL_CallStackCacheNode *node);
////////////////////////////////
//~ rjf: Main Layer Initialization
@@ -1063,18 +991,13 @@ internal void ctrl_set_wakeup_hook(CTRL_WakeupFunctionType *wakeup_hook);
////////////////////////////////
//~ rjf: Process Memory Functions
//- rjf: process memory cache interaction
internal U128 ctrl_calc_hash_store_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B32 zero_terminated);
internal U128 ctrl_stored_hash_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B32 zero_terminated, B32 *out_is_stale, U64 endt_us);
//- rjf: bundled key/stream helper
internal U128 ctrl_hash_store_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 range, B32 zero_terminated);
//- rjf: process memory cache key reading
internal HS_Key ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, U64 endt_us, B32 *out_is_stale);
//- rjf: process memory cache reading helpers
internal CTRL_ProcessMemorySlice ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_Handle process, Rng1U64 range, U64 endt_us);
internal CTRL_ProcessMemorySlice ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_Handle process, U64 vaddr, U64 limit, U64 element_size, U64 endt_us);
internal B32 ctrl_read_cached_process_memory(CTRL_Handle process, Rng1U64 range, B32 *is_stale_out, void *out, U64 endt_us);
#define ctrl_read_cached_process_memory_struct(process, vaddr, is_stale_out, ptr, endt_us) ctrl_read_cached_process_memory((process), r1u64((vaddr), (vaddr)+(sizeof(*(ptr)))), (is_stale_out), (ptr), (endt_us))
internal CTRL_ProcessMemorySlice ctrl_process_memory_slice_from_vaddr_range(Arena *arena, CTRL_Handle process, Rng1U64 range, U64 endt_us);
internal B32 ctrl_process_memory_read(CTRL_Handle process, Rng1U64 range, B32 *is_stale_out, void *out, U64 endt_us);
#define ctrl_process_memory_read_struct(process, vaddr, is_stale_out, ptr, endt_us) ctrl_process_memory_read((process), r1u64((vaddr), (vaddr)+(sizeof(*(ptr)))), (is_stale_out), (ptr), (endt_us))
//- rjf: process memory writing
internal B32 ctrl_process_write(CTRL_Handle process, Rng1U64 range, void *src);
@@ -1083,10 +1006,10 @@ internal B32 ctrl_process_write(CTRL_Handle process, Rng1U64 range, void *src);
//~ rjf: Thread Register Functions
//- rjf: thread register cache reading
internal void *ctrl_query_cached_reg_block_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_Handle handle);
internal U64 ctrl_query_cached_tls_root_vaddr_from_thread(CTRL_EntityStore *store, CTRL_Handle handle);
internal U64 ctrl_query_cached_rip_from_thread(CTRL_EntityStore *store, CTRL_Handle handle);
internal U64 ctrl_query_cached_rsp_from_thread(CTRL_EntityStore *store, CTRL_Handle handle);
internal void *ctrl_reg_block_from_thread(Arena *arena, CTRL_EntityCtx *ctx, CTRL_Handle handle);
internal U64 ctrl_tls_root_vaddr_from_thread(CTRL_EntityCtx *ctx, CTRL_Handle handle);
internal U64 ctrl_rip_from_thread(CTRL_EntityCtx *ctx, CTRL_Handle handle);
internal U64 ctrl_rsp_from_thread(CTRL_EntityCtx *ctx, CTRL_Handle handle);
//- rjf: thread register writing
internal B32 ctrl_thread_write_reg_block(CTRL_Handle thread, void *block);
@@ -1099,6 +1022,7 @@ internal PE_IntelPdata *ctrl_intel_pdata_from_module_voff(Arena *arena, CTRL_Han
internal U64 ctrl_entry_point_voff_from_module(CTRL_Handle module_handle);
internal Rng1U64 ctrl_tls_vaddr_range_from_module(CTRL_Handle module_handle);
internal String8 ctrl_initial_debug_info_path_from_module(Arena *arena, CTRL_Handle module_handle);
internal String8 ctrl_raddbg_data_from_module(Arena *arena, CTRL_Handle module_handle);
////////////////////////////////
//~ rjf: Unwinding Functions
@@ -1108,18 +1032,24 @@ internal CTRL_Unwind ctrl_unwind_deep_copy(Arena *arena, Arch arch, CTRL_Unwind
//- 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_Handle process_handle, CTRL_Handle module_handle, REGS_RegBlockX64 *regs, U64 endt_us);
internal CTRL_UnwindStepResult ctrl_unwind_step__pe_x64(CTRL_Handle process_handle, CTRL_Handle module_handle, U64 module_base_vaddr, REGS_RegBlockX64 *regs, U64 endt_us);
//- rjf: abstracted unwind step
internal CTRL_UnwindStepResult ctrl_unwind_step(CTRL_EntityStore *store, CTRL_Handle process, CTRL_Handle module, Arch arch, void *reg_block, U64 endt_us);
internal CTRL_UnwindStepResult ctrl_unwind_step(CTRL_Handle process, CTRL_Handle module, U64 module_base_vaddr, Arch arch, void *reg_block, U64 endt_us);
//- rjf: abstracted full unwind
internal CTRL_Unwind ctrl_unwind_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_Handle thread, U64 endt_us);
internal CTRL_Unwind ctrl_unwind_from_thread(Arena *arena, CTRL_EntityCtx *ctx, CTRL_Handle thread, U64 endt_us);
////////////////////////////////
//~ rjf: Call Stack Building Functions
internal CTRL_CallStack ctrl_call_stack_from_unwind(Arena *arena, DI_Scope *di_scope, CTRL_Entity *process, CTRL_Unwind *base_unwind);
internal CTRL_CallStack ctrl_call_stack_from_unwind(Arena *arena, CTRL_Entity *process, CTRL_Unwind *base_unwind);
internal CTRL_CallStackFrame *ctrl_call_stack_frame_from_unwind_and_inline_depth(CTRL_CallStack *call_stack, U64 unwind_count, U64 inline_depth);
////////////////////////////////
//~ rjf: Call Stack Cache Functions
internal CTRL_CallStack ctrl_call_stack_from_thread(CTRL_Scope *scope, CTRL_EntityCtx *entity_ctx, CTRL_Entity *thread, B32 high_priority, U64 endt_us);
////////////////////////////////
//~ rjf: Halting All Attached Processes
@@ -1153,12 +1083,13 @@ internal CTRL_EventList ctrl_c2u_pop_events(Arena *arena);
internal void ctrl_thread__entry_point(void *p);
//- rjf: breakpoint resolution
internal void ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_Handle process, CTRL_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
internal void ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
internal void ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_EvalScope *eval_scope, CTRL_Handle process, CTRL_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
internal void ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_EvalScope *eval_scope, CTRL_Handle process, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out);
internal void ctrl_thread__append_program_defined_bp_traps(Arena *arena, CTRL_Entity *bp, DMN_TrapChunkList *traps_out);
//- rjf: module lifetime open/close work
internal void ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_range, String8 path);
internal void ctrl_thread__module_close(CTRL_Handle module);
internal void ctrl_thread__module_close(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_range);
//- 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);
@@ -1166,6 +1097,10 @@ internal DMN_Event *ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_
//- rjf: eval helpers
internal B32 ctrl_eval_space_read(void *u, E_Space space, void *out, Rng1U64 vaddr_range);
//- rjf: control thread eval scopes
internal CTRL_EvalScope *ctrl_thread__eval_scope_begin(Arena *arena, CTRL_Entity *thread);
internal void ctrl_thread__eval_scope_end(CTRL_EvalScope *scope);
//- rjf: log flusher
internal void ctrl_thread__flush_info_log(String8 string);
internal void ctrl_thread__end_and_flush_info_log(void);
@@ -1180,14 +1115,23 @@ internal void ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
internal void ctrl_thread__single_step(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
////////////////////////////////
//~ rjf: Memory-Stream Thread Functions
//~ rjf: Asynchronous Memory Streaming Functions
//- rjf: user -> memory stream communication
internal B32 ctrl_u2ms_enqueue_req(CTRL_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, U64 endt_us);
internal void ctrl_u2ms_dequeue_req(CTRL_Handle *out_process, Rng1U64 *out_vaddr_range, B32 *out_zero_terminated);
internal B32 ctrl_u2ms_enqueue_req(HS_Key key, CTRL_Handle process, Rng1U64 vaddr_range, B32 zero_terminated, U64 endt_us);
internal void ctrl_u2ms_dequeue_req(HS_Key *out_key, CTRL_Handle *out_process, Rng1U64 *out_vaddr_range, B32 *out_zero_terminated);
//- rjf: entry point
ASYNC_WORK_DEF(ctrl_mem_stream_work);
internal void ctrl_mem_stream_thread__entry_point(void *p);
////////////////////////////////
//~ rjf: Asynchronous Call Stack Building Functions
//- rjf: user -> memory stream communication
internal B32 ctrl_u2csb_enqueue_req(CTRL_Handle thread, U64 endt_us);
internal void ctrl_u2csb_dequeue_req(CTRL_Handle *out_thread);
//- rjf: entry point
ASYNC_WORK_DEF(ctrl_call_stack_build_work);
#endif // CTRL_CORE_H
+3
View File
@@ -1,4 +1,7 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#undef LAYER_COLOR
#define LAYER_COLOR 0x969696ff
#include "ctrl_core.c"
+18 -1
View File
@@ -4,7 +4,22 @@
//- GENERATED CODE
C_LINKAGE_BEGIN
String8 ctrl_entity_kind_display_string_table[9] =
String8 ctrl_entity_kind_code_name_table[11] =
{
{0},
str8_lit_comp("root"),
str8_lit_comp("machine"),
str8_lit_comp("process"),
str8_lit_comp("thread"),
str8_lit_comp("module"),
str8_lit_comp("entry_point"),
str8_lit_comp("debug_info_path"),
str8_lit_comp("pending_thread_name"),
str8_lit_comp("pending_thread_color"),
str8_lit_comp("breakpoint"),
};
String8 ctrl_entity_kind_display_string_table[11] =
{
{0},
str8_lit_comp("Root"),
@@ -15,6 +30,8 @@ str8_lit_comp("Module"),
str8_lit_comp("EntryPoint"),
str8_lit_comp("DebugInfoPath"),
str8_lit_comp("PendingThreadName"),
str8_lit_comp("PendingThreadColor"),
str8_lit_comp("Breakpoint"),
};
U32 ctrl_exception_code_kind_code_table[38] =
+4 -1
View File
@@ -17,6 +17,8 @@ CTRL_EntityKind_Module,
CTRL_EntityKind_EntryPoint,
CTRL_EntityKind_DebugInfoPath,
CTRL_EntityKind_PendingThreadName,
CTRL_EntityKind_PendingThreadColor,
CTRL_EntityKind_Breakpoint,
CTRL_EntityKind_COUNT,
} CTRL_EntityKind;
@@ -64,7 +66,8 @@ CTRL_ExceptionCodeKind_COUNT,
} CTRL_ExceptionCodeKind;
C_LINKAGE_BEGIN
extern String8 ctrl_entity_kind_display_string_table[9];
extern String8 ctrl_entity_kind_code_name_table[11];
extern String8 ctrl_entity_kind_display_string_table[11];
extern U32 ctrl_exception_code_kind_code_table[38];
extern String8 ctrl_exception_code_kind_display_string_table[38];
extern String8 ctrl_exception_code_kind_lowercase_code_string_table[38];
+46 -72
View File
@@ -1,6 +1,9 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#undef LAYER_COLOR
#define LAYER_COLOR 0xe34cd4ff
////////////////////////////////
//~ rjf: Instruction Decoding/Disassembling Type Functions
@@ -342,10 +345,13 @@ dasm_info_from_hash_params(DASM_Scope *scope, U128 hash, DASM_Params *params)
DASM_Info info = {0};
if(!u128_match(hash, u128_zero()))
{
//- rjf: unpack hash
U64 slot_idx = hash.u64[1]%dasm_shared->slots_count;
U64 stripe_idx = slot_idx%dasm_shared->stripes_count;
DASM_Slot *slot = &dasm_shared->slots[slot_idx];
DASM_Stripe *stripe = &dasm_shared->stripes[stripe_idx];
//- rjf: try to get existing results
B32 found = 0;
OS_MutexScopeR(stripe->rw_mutex)
{
@@ -360,9 +366,13 @@ dasm_info_from_hash_params(DASM_Scope *scope, U128 hash, DASM_Params *params)
}
}
}
B32 node_is_new = 0;
//- rjf: miss -> kick off work to fill cache
if(!found)
{
B32 node_is_new = 0;
U64 *node_working_count = 0;
HS_Root root = {0};
OS_MutexScopeW(stripe->rw_mutex)
{
DASM_Node *node = 0;
@@ -376,16 +386,7 @@ dasm_info_from_hash_params(DASM_Scope *scope, U128 hash, DASM_Params *params)
}
if(node == 0)
{
LogInfoNamedBlockF("dasm_new_node")
{
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_arch(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);
}
// rjf: allocate node
node = stripe->free_node;
if(node)
{
@@ -396,26 +397,34 @@ dasm_info_from_hash_params(DASM_Scope *scope, U128 hash, DASM_Params *params)
node = push_array_no_zero(stripe->arena, DASM_Node, 1);
}
MemoryZeroStruct(node);
// rjf: fill node
DLLPushBack(slot->first, slot->last, node);
node->hash = hash;
MemoryCopyStruct(&node->params, params);
node->root = hs_root_alloc();
// TODO(rjf): need to make this releasable - currently all exe_paths just leak
node->params.dbgi_key = di_key_copy(stripe->arena, &node->params.dbgi_key);
// rjf: gather work kickoff params
node_is_new = 1;
ins_atomic_u64_inc_eval(&node->working_count);
node_working_count = &node->working_count;
root = node->root;
}
}
}
if(node_is_new)
{
dasm_u2p_enqueue_req(hash, params, max_U64);
async_push_work(dasm_parse_work);
if(node_is_new)
{
dasm_u2p_enqueue_req(root, hash, params, max_U64);
async_push_work(dasm_parse_work, .working_counter = node_working_count);
}
}
}
return info;
}
internal DASM_Info
dasm_info_from_key_params(DASM_Scope *scope, U128 key, DASM_Params *params, U128 *hash_out)
dasm_info_from_key_params(DASM_Scope *scope, HS_Key key, DASM_Params *params, U128 *hash_out)
{
DASM_Info result = {0};
for(U64 rewind_idx = 0; rewind_idx < HS_KEY_HASH_HISTORY_COUNT; rewind_idx += 1)
@@ -438,16 +447,17 @@ dasm_info_from_key_params(DASM_Scope *scope, U128 key, DASM_Params *params, U128
//~ rjf: Parse Threads
internal B32
dasm_u2p_enqueue_req(U128 hash, DASM_Params *params, U64 endt_us)
dasm_u2p_enqueue_req(HS_Root root, U128 hash, DASM_Params *params, U64 endt_us)
{
B32 good = 0;
OS_MutexScope(dasm_shared->u2p_ring_mutex) for(;;)
{
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(Arch)+sizeof(DASM_StyleFlags)+sizeof(DASM_Syntax)+sizeof(U64)+sizeof(U64)+params->dbgi_key.path.size+sizeof(U64))
if(available_size >= sizeof(root)+sizeof(hash)+sizeof(U64)+sizeof(Arch)+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, &root);
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);
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->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->arch);
@@ -473,13 +483,14 @@ dasm_u2p_enqueue_req(U128 hash, DASM_Params *params, U64 endt_us)
}
internal void
dasm_u2p_dequeue_req(Arena *arena, U128 *hash_out, DASM_Params *params_out)
dasm_u2p_dequeue_req(Arena *arena, HS_Root *root_out, 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(Arch)+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, root_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, 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);
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->arch);
@@ -506,9 +517,10 @@ ASYNC_WORK_DEF(dasm_parse_work)
TXT_Scope *txt_scope = txt_scope_open();
//- rjf: get next request
HS_Root root = {0};
U128 hash = {0};
DASM_Params params = {0};
dasm_u2p_dequeue_req(scratch.arena, &hash, &params);
dasm_u2p_dequeue_req(scratch.arena, &root, &hash, &params);
U64 change_gen = fs_change_gen();
//- rjf: unpack hash
@@ -517,38 +529,19 @@ ASYNC_WORK_DEF(dasm_parse_work)
DASM_Slot *slot = &dasm_shared->slots[slot_idx];
DASM_Stripe *stripe = &dasm_shared->stripes[stripe_idx];
//- rjf: take task
B32 got_task = 0;
OS_MutexScopeR(stripe->rw_mutex)
{
for(DASM_Node *n = slot->first; n != 0; n = n->next)
{
if(u128_match(n->hash, hash) && dasm_params_match(&n->params, &params))
{
got_task = !ins_atomic_u32_eval_cond_assign(&n->is_working, 1, 0);
break;
}
}
}
//- rjf: get dbg info
RDI_Parsed *rdi = &di_rdi_parsed_nil;
if(got_task && params.dbgi_key.path.size != 0)
RDI_Parsed *rdi = &rdi_parsed_nil;
if(params.dbgi_key.path.size != 0)
{
rdi = di_rdi_from_key(di_scope, &params.dbgi_key, max_U64);
}
//- rjf: hash -> data
String8 data = {0};
if(got_task)
{
data = hs_data_from_hash(hs_scope, hash);
}
String8 data = hs_data_from_hash(hs_scope, hash);
//- rjf: data * arch * addr * dbg -> decode artifacts
DASM_LineChunkList line_list = {0};
String8List inst_strings = {0};
if(got_task)
{
switch(params.arch)
{
@@ -573,7 +566,7 @@ ASYNC_WORK_DEF(dasm_parse_work)
// rjf: push strings derived from voff -> line info
if(params.style_flags & (DASM_StyleFlag_SourceFilesNames|DASM_StyleFlag_SourceLines))
{
if(rdi != &di_rdi_parsed_nil)
if(rdi != &rdi_parsed_nil)
{
U64 voff = (params.vaddr+off) - params.base_vaddr;
U32 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, voff);
@@ -618,7 +611,7 @@ ASYNC_WORK_DEF(dasm_parse_work)
{
// TODO(rjf): need redirection path - this may map to a different path on the local machine,
// need frontend to communicate path remapping info to this layer
U128 key = fs_key_from_path_range(file_normalized_full_path, r1u64(0, max_U64));
HS_Key key = fs_key_from_path_range(file_normalized_full_path, r1u64(0, max_U64), 0);
TXT_LangKind lang_kind = txt_lang_kind_from_extension(file_normalized_full_path);
U64 endt_us = max_U64;
U128 hash = {0};
@@ -655,7 +648,7 @@ ASYNC_WORK_DEF(dasm_parse_work)
String8 addr_part = {0};
if(params.style_flags & DASM_StyleFlag_Addresses)
{
addr_part = push_str8f(scratch.arena, "%s0x%016I64x ", rdi != &di_rdi_parsed_nil ? " " : "", params.vaddr+off);
addr_part = push_str8f(scratch.arena, "%s0x%016I64x ", rdi != &rdi_parsed_nil ? " " : "", params.vaddr+off);
}
String8 code_bytes_part = {0};
if(params.style_flags & DASM_StyleFlag_CodeBytes)
@@ -677,7 +670,7 @@ ASYNC_WORK_DEF(dasm_parse_work)
code_bytes_part = str8_list_join(scratch.arena, &code_bytes_strings, 0);
}
String8 symbol_part = {0};
if(inst.jump_dest_vaddr != 0 && rdi != &di_rdi_parsed_nil && params.style_flags & DASM_StyleFlag_SymbolNames)
if(inst.jump_dest_vaddr != 0 && rdi != &rdi_parsed_nil && params.style_flags & DASM_StyleFlag_SymbolNames)
{
RDI_U32 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, inst.jump_dest_vaddr-params.base_vaddr);
if(scope_idx != 0)
@@ -709,7 +702,6 @@ ASYNC_WORK_DEF(dasm_parse_work)
//- rjf: artifacts -> value bundle
Arena *info_arena = 0;
DASM_Info info = {0};
if(got_task)
{
//- rjf: produce joined text
Arena *text_arena = arena_alloc();
@@ -718,21 +710,7 @@ ASYNC_WORK_DEF(dasm_parse_work)
String8 text = str8_list_join(text_arena, &inst_strings, &text_join);
//- rjf: produce unique key for this disassembly's text
U128 text_key = {0};
{
U64 hash_data[] =
{
hash.u64[0],
hash.u64[1],
params.vaddr,
(U64)params.arch,
(U64)params.style_flags,
(U64)params.syntax,
(U64)rdi,
0x4d534144,
};
text_key = hs_hash_from_data(str8((U8 *)hash_data, sizeof(hash_data)));
}
HS_Key text_key = hs_key_make(root, hs_id_make(0, 0));
//- rjf: submit text data to hash store
U128 text_hash = hs_submit_data(text_key, &text_arena, text);
@@ -744,7 +722,7 @@ ASYNC_WORK_DEF(dasm_parse_work)
}
//- rjf: commit results to cache
if(got_task) OS_MutexScopeW(stripe->rw_mutex)
OS_MutexScopeW(stripe->rw_mutex)
{
for(DASM_Node *n = slot->first; n != 0; n = n->next)
{
@@ -752,7 +730,7 @@ ASYNC_WORK_DEF(dasm_parse_work)
{
n->info_arena = info_arena;
MemoryCopyStruct(&n->info, &info);
if(rdi != &di_rdi_parsed_nil && params.style_flags & (DASM_StyleFlag_SourceLines|DASM_StyleFlag_SourceFilesNames))
if(rdi != &rdi_parsed_nil && params.style_flags & (DASM_StyleFlag_SourceLines|DASM_StyleFlag_SourceFilesNames))
{
n->change_gen = change_gen;
}
@@ -760,8 +738,6 @@ ASYNC_WORK_DEF(dasm_parse_work)
{
n->change_gen = 0;
}
ins_atomic_u32_eval_assign(&n->is_working, 0);
ins_atomic_u64_inc_eval(&n->load_count);
break;
}
}
@@ -804,8 +780,7 @@ dasm_evictor_detector_thread__entry_point(void *p)
if(n->scope_ref_count == 0 &&
n->last_time_touched_us+evict_threshold_us <= check_time_us &&
n->last_user_clock_idx_touched+evict_threshold_user_clocks <= check_time_user_clocks &&
n->load_count != 0 &&
n->is_working == 0)
ins_atomic_u64_eval(&n->working_count) == 0)
{
slot_has_work = 1;
break;
@@ -827,8 +802,7 @@ dasm_evictor_detector_thread__entry_point(void *p)
if(n->scope_ref_count == 0 &&
n->last_time_touched_us+evict_threshold_us <= check_time_us &&
n->last_user_clock_idx_touched+evict_threshold_user_clocks <= check_time_user_clocks &&
n->load_count != 0 &&
n->is_working == 0)
ins_atomic_u64_eval(&n->working_count) == 0)
{
DLLRemove(slot->first, slot->last, n);
if(n->info_arena != 0)
@@ -841,7 +815,7 @@ dasm_evictor_detector_thread__entry_point(void *p)
n->last_time_requested_us+retry_threshold_us <= check_time_us &&
n->last_user_clock_idx_requested+retry_threshold_user_clocks <= check_time_user_clocks)
{
if(dasm_u2p_enqueue_req(n->hash, &n->params, max_U64))
if(dasm_u2p_enqueue_req(n->root, n->hash, &n->params, max_U64))
{
async_push_work(dasm_parse_work);
n->last_time_requested_us = os_now_microseconds();
+8 -6
View File
@@ -159,7 +159,7 @@ struct DASM_Result
typedef struct DASM_Info DASM_Info;
struct DASM_Info
{
U128 text_key;
HS_Key text_key;
DASM_LineArray lines;
};
@@ -177,6 +177,9 @@ struct DASM_Node
U128 hash;
DASM_Params params;
// rjf: root
HS_Root root;
// rjf: generations
U64 change_gen;
@@ -185,11 +188,10 @@ struct DASM_Node
DASM_Info info;
// rjf: metadata
B32 is_working;
U64 working_count;
U64 scope_ref_count;
U64 last_time_touched_us;
U64 last_user_clock_idx_touched;
U64 load_count;
U64 last_time_requested_us;
U64 last_user_clock_idx_requested;
};
@@ -309,13 +311,13 @@ internal void dasm_scope_touch_node__stripe_r_guarded(DASM_Scope *scope, DASM_No
//~ rjf: Cache Lookups
internal DASM_Info dasm_info_from_hash_params(DASM_Scope *scope, U128 hash, DASM_Params *params);
internal DASM_Info dasm_info_from_key_params(DASM_Scope *scope, U128 key, DASM_Params *params, U128 *hash_out);
internal DASM_Info dasm_info_from_key_params(DASM_Scope *scope, HS_Key key, DASM_Params *params, U128 *hash_out);
////////////////////////////////
//~ rjf: Parse Threads
internal B32 dasm_u2p_enqueue_req(U128 hash, DASM_Params *params, U64 endt_us);
internal void dasm_u2p_dequeue_req(Arena *arena, U128 *hash_out, DASM_Params *params_out);
internal B32 dasm_u2p_enqueue_req(HS_Root root, U128 hash, DASM_Params *params, U64 endt_us);
internal void dasm_u2p_dequeue_req(Arena *arena, HS_Root *root_out, U128 *hash_out, DASM_Params *params_out);
ASYNC_WORK_DEF(dasm_parse_work);
////////////////////////////////
+36 -79
View File
@@ -4,53 +4,52 @@
////////////////////////////////
//~ rjf: Built-In Command Tables
@table(name ui_vis ipc_docs_vis q_slot q_view q_ent_kind q_ctrl_ent_kind q_allow_files q_allow_folders q_keep_oi q_select_oi q_is_code q_required canonical_icon string display_name desc search_tags )
// / | | | \___ _________________________________/ | | | | |
// / | | | \ / | | | | |
D_CmdTable: // | | | | | | | | | |
@table(name ui_vis ipc_docs_vis text_pt_vis text_rng_vis q_expr q_slot q_view q_ent_kind q_ctrl_ent_kind q_allow_files q_allow_folders q_keep_oi q_select_oi q_is_code q_floating q_required canonical_icon string display_name desc search_tags ctx_filter)
// / | | | | | | \___ _________________________________/ | | | | | |
// / | | | | | | \ / | | | | | |
D_CmdTable: // | | | | | | | | | | | | | |
{
//- rjf: low-level target control operations
{LaunchAndRun 1 1 Entity null Target Null 0 0 0 0 0 1 Play "launch_and_run" "Launch and Run" "Starts debugging a new instance of a target, then runs." "launch,start,run,target" }
{LaunchAndInit 1 1 Entity null Target Null 0 0 0 0 0 1 PlayStepForward "launch_and_init" "Launch and Initialize" "Starts debugging a new instance of a target, then stops at the program's entry point." "launch,start,entry,point" }
{Kill 1 1 Process null Nil Process 0 0 0 0 0 1 X "kill" "Kill" "Kills the specified existing attached process(es)." "stop,kill" }
{KillAll 1 1 Null null Nil Null 0 0 0 0 0 0 Stop "kill_all" "Kill All" "Kills all attached processes." "stop,kill,all" }
{Detach 1 1 Process null Nil Process 0 0 0 0 0 1 Null "detach" "Detach" "Detaches the specified attached process(es)." "detach" }
{Continue 1 1 Null null Nil Null 0 0 0 0 0 0 Play "continue" "Continue" "Continues executing all attached processes." "" }
{StepIntoInst 1 1 Null null Nil Null 0 0 0 0 0 0 StepInto "step_into_inst" "Step Into (Assembly)" "Performs a step that goes into calls, at the instruction level." "single,step,thread" }
{StepOverInst 1 1 Null null Nil Null 0 0 0 0 0 0 StepOver "step_over_inst" "Step Over (Assembly)" "Performs a step that skips calls, at the instruction level." "single,step,thread" }
{StepIntoLine 1 1 Null null Nil Null 0 0 0 0 0 0 StepInto "step_into_line" "Step Into (Line)" "Performs a step that goes into calls, at the source code line level." "step,thread" }
{StepOverLine 1 1 Null null Nil Null 0 0 0 0 0 0 StepOver "step_over_line" "Step Over (Line)" "Performs a step that skips calls, at the source code line level." "step,thread" }
{StepOut 1 1 Null null Nil Null 0 0 0 0 0 0 StepOut "step_out" "Step Out" "Runs to the end of the current function and exits it." "" }
{Halt 1 1 Null null Nil Null 0 0 0 0 0 0 Pause "halt" "Halt" "Halts all attached processes." "pause" }
{SoftHaltRefresh 1 1 Null null Nil Null 0 0 0 0 0 0 Refresh "soft_halt_refresh" "Soft Halt Refresh" "Interrupts all attached processes to collect data, and then resumes them." "" }
{SetThreadIP 0 1 Vaddr null Nil Null 0 0 0 0 1 1 Null "set_thread_ip" "Set Thread IP" "Sets the specified thread's instruction pointer at the specified address." "" }
{LaunchAndRun 1 1 0 0 "query:targets" Cfg null Target Null 0 0 0 0 0 1 1 Play "launch_and_run" "Launch and Run" "Starts debugging a new instance of a target, then runs." "launch,start,run,target" "" }
{LaunchAndStepInto 1 1 0 0 "query:targets" Cfg null Target Null 0 0 0 0 0 1 1 PlayStepForward "launch_and_step_into" "Launch and Step Into" "Starts debugging a new instance of a target, then stops at the program's entry point." "launch,start,entry,point" "" }
{Kill 1 1 0 0 "query:processes" Process null Nil Process 0 0 0 0 0 1 1 X "kill" "Kill" "Kills the specified existing attached process(es)." "stop,kill" "" }
{KillAll 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Stop "kill_all" "Kill All" "Kills all attached processes." "stop,kill,all" "" }
{Detach 1 1 0 0 "query:processes" Process null Nil Process 0 0 0 0 0 1 1 Null "detach" "Detach" "Detaches the specified attached process(es)." "detach" "" }
{Continue 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Play "continue" "Continue" "Continues executing all attached processes." "" "" }
{StepIntoInst 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepInto "step_into_inst" "Step Into (Assembly)" "Performs a step that goes into calls, at the instruction level." "single,step,thread" "" }
{StepOverInst 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepOver "step_over_inst" "Step Over (Assembly)" "Performs a step that skips calls, at the instruction level." "single,step,thread" "" }
{StepIntoLine 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepInto "step_into_line" "Step Into (Line)" "Performs a step that goes into calls, at the source code line level." "step,thread" "" }
{StepOverLine 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepOver "step_over_line" "Step Over (Line)" "Performs a step that skips calls, at the source code line level." "step,thread" "" }
{StepOut 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepOut "step_out" "Step Out" "Runs to the end of the current function and exits it." "" "" }
{Halt 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Pause "halt" "Halt" "Halts all attached processes." "pause" "" }
{SoftHaltRefresh 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Refresh "soft_halt_refresh" "Soft Halt Refresh" "Interrupts all attached processes to collect data, and then resumes them." "" "" }
{SetThreadIP 0 1 0 0 "" Vaddr null Nil Null 0 0 0 0 1 1 1 Null "set_thread_ip" "Set Thread IP" "Sets the specified thread's instruction pointer at the specified address." "" "" }
//- rjf: high-level composite target control operations
{RunToLine 0 1 Null null Nil Null 0 0 0 0 0 0 Play "run_to_line" "Run To Line" "Runs until a particular source line is hit." "" }
{RunToAddress 1 1 Vaddr null Nil Null 0 0 0 0 1 1 PlayStepForward "run_to_address" "Run To Address" "Runs until a particular address is hit." "" }
{Run 1 1 Null null Nil Null 0 0 0 0 0 0 Play "run" "Run" "Runs all targets after starting them if they have not been started yet." "play" }
{Restart 1 1 Null null Nil Null 0 0 0 0 0 0 Redo "restart" "Restart" "Kills all attached processes, then launches all active targets." "restart,retry" }
{StepInto 1 1 Null null Nil Null 0 0 0 0 0 0 StepInto "step_into" "Step Into" "Steps once, possibly into function calls, for either source lines or instructions (whichever is selected)." "" }
{StepOver 1 1 Null null Nil Null 0 0 0 0 0 0 StepOver "step_over" "Step Over" "Steps once, always over function calls, for either source lines or instructions." "" }
{RunToLine 1 1 1 0 "" Null null Nil Null 0 0 0 0 0 0 0 Play "run_to_line" "Run To Line" "Runs until a particular source line is hit." "" "$text_pt," }
{Run 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Play "run" "Run" "Runs all targets after starting them if they have not been started yet." "play" "" }
{Restart 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Redo "restart" "Restart" "Kills all attached processes, then launches all active targets." "restart,retry" "" }
{StepInto 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepInto "step_into" "Step Into" "Steps once, possibly into function calls, for either source lines or instructions (whichever is selected)." "" "" }
{StepOver 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 StepOver "step_over" "Step Over" "Steps once, always over function calls, for either source lines or instructions." "" "" }
//- rjf: debug control context management operations
{FreezeThread 1 1 Thread null Nil Thread 0 0 0 0 0 1 Locked "freeze_thread" "Freeze Thread" "Freezes the passed thread." "callstack,unwind" }
{ThawThread 1 1 Thread null Nil Thread 0 0 0 0 0 1 Unlocked "thaw_thread" "Thaw Thread" "Thaws the passed thread." "" }
{FreezeProcess 1 1 Process null Nil Process 0 0 0 0 0 1 Locked "freeze_process" "Freeze Process" "Freezes the passed process." "" }
{ThawProcess 1 1 Process null Nil Process 0 0 0 0 0 1 Unlocked "thaw_process" "Thaw Process" "Thaws the passed process." "" }
{FreezeMachine 0 1 Machine null Nil Machine 0 0 0 0 0 1 Locked "freeze_machine" "Freeze Machine" "Freezes the passed machine." "" }
{ThawMachine 0 1 Machine null Nil Machine 0 0 0 0 0 1 Unlocked "thaw_machine" "Thaw Machine" "Thaws the passed machine." "" }
{FreezeLocalMachine 1 1 Null null Nil Null 0 0 0 0 0 0 Machine "freeze_local_machine" "Freeze Local Machine" "Freezes the local machine." "" }
{ThawLocalMachine 1 1 Null null Nil Null 0 0 0 0 0 0 Machine "thaw_local_machine" "Thaw Local Machine" "Thaws the local machine." "" }
{FreezeEntity 0 0 Null null Nil Null 0 0 0 0 0 0 Null "freeze_entity" "Freeze Entity" "Freezes an entity." "" }
{ThawEntity 0 0 Null null Nil Null 0 0 0 0 0 0 Null "thaw_entity" "Thaw Entity" "Thaws an entity." "" }
{FreezeThread 1 1 0 0 "query:threads" Thread null Nil Thread 0 0 0 0 0 1 1 Locked "freeze_thread" "Freeze Thread" "Freezes the passed thread." "callstack,unwind" "" }
{ThawThread 1 1 0 0 "query:threads" Thread null Nil Thread 0 0 0 0 0 1 1 Unlocked "thaw_thread" "Thaw Thread" "Thaws the passed thread." "" "" }
{FreezeProcess 1 1 0 0 "query:processes" Process null Nil Process 0 0 0 0 0 1 1 Locked "freeze_process" "Freeze Process" "Freezes the passed process." "" "" }
{ThawProcess 1 1 0 0 "query:processes" Process null Nil Process 0 0 0 0 0 1 1 Unlocked "thaw_process" "Thaw Process" "Thaws the passed process." "" "" }
{FreezeMachine 0 1 0 0 "query:machines" Machine null Nil Machine 0 0 0 0 0 1 1 Locked "freeze_machine" "Freeze Machine" "Freezes the passed machine." "" "" }
{ThawMachine 0 1 0 0 "query:machines" Machine null Nil Machine 0 0 0 0 0 1 1 Unlocked "thaw_machine" "Thaw Machine" "Thaws the passed machine." "" "" }
{FreezeLocalMachine 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Machine "freeze_local_machine" "Freeze Local Machine" "Freezes the local machine." "" "" }
{ThawLocalMachine 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Machine "thaw_local_machine" "Thaw Local Machine" "Thaws the local machine." "" "" }
{FreezeEntity 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Unlocked "freeze_entity" "Freeze Entity" "Freezes an entity." "" "" }
{ThawEntity 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Locked "thaw_entity" "Thaw Entity" "Thaws an entity." "" "" }
//- rjf: entity decoration
{SetEntityColor 0 0 Null null Nil Null 0 0 0 0 0 0 Null "set_entity_color" "Set Entity Color" "Sets the passed entity's color." "" }
{SetEntityName 0 0 Null null Nil Null 0 0 0 0 0 0 Null "set_entity_name" "Set Entity Name" "Sets the passed entity's name." "" }
{SetEntityColor 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "set_entity_color" "Set Entity Color" "Sets the passed entity's color." "" "" }
{SetEntityName 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "set_entity_name" "Set Entity Name" "Sets the passed entity's name." "" "" }
//- rjf: attaching
{Attach 1 1 PID null Nil Null 0 0 0 0 0 1 Null "attach" "Attach" "Attaches to a process that is already running on the local machine." "" }
{Attach 1 1 0 0 "query:unattached_processes" PID null Nil Null 0 0 0 0 0 1 1 Null "attach" "Attach" "Attaches to a process that is already running on the local machine." "" "" }
}
@enum D_CmdKind:
@@ -60,47 +59,6 @@ D_CmdTable: // | | | |
COUNT,
}
////////////////////////////////
//~ rjf: Built-In VieNull w Rules
@table(coverage_check name name_lower string ih ex xp vb display_name docs schema description)
D_ViewRuleTable:
{
{x Default default "default" - - - x "Default" - "" "" }
{x Array array "array" - - x - "Array" x "x:{expr}" "Specifies that a pointer points to N elements, rather than only 1." }
{x Slice slice "slice" - - x - "Slice" x "" "Specifies that a pointer within a struct, also containing an integer, points to the number of elements encoded by the integer." }
{- List list "list" - - - x "List" - "x:{member}" "Specifies that some struct, union, or class forms the top of a linked list, and the member which points at the following element in the list." }
{x ByteSwap bswap "bswap" x - x - "Byte Swap" x "" "Specifies that all integral evaluations should be byte-swapped, such that their endianness is reversed." }
{x Cast cast "cast" - - x - "Cast" x "x:{type}" "Specifies that the expression to which the view rule is applied should be casted to the provided type." }
{- BaseDec base_dec "dec" x - - - "Decimal Base (Base 10)" x "" "Specifies that all integral evaluations should appear in base-10 form." }
{- BaseBin base_bin "bin" x - - - "Binary Base (Base 2)" x "" "Specifies that all integral evaluations should appear in base-2 form." }
{- BaseOct base_oct "oct" x - - - "Octal Base (Base 8)" x "" "Specifies that all integral evaluations should appear in base-8 form." }
{- BaseHex base_hex "hex" x - - - "Hexadecimal Base (Base 16)" x "" "Specifies that all integral evaluations should appear in base-16 form." }
{- Only only "only" x - - x "Only Specified Members" x "x:{member}" "Specifies that only the specified members should appear in struct, union, or class evaluations." }
{- Omit omit "omit" x - - x "Omit Specified Members" x "x:{member}" "Omits a list of member names from appearing in struct, union, or class evaluations." }
{- NoAddr no_addr "no_addr" x - - - "Disable Address Values" x "" "Displays only what pointers point to, if possible, without the pointer's address value." }
{x Checkbox checkbox "checkbox" - - - - "Checkbox" x "" "Displays simple integer values as checkboxes, encoding zero or nonzero values." }
{- ColorRGBA color_rgba "color_rgba" - x - x "Color (RGBA)" x "" "Displays as a color, interpreting the data as encoding R, G, B, and A values." }
{x Text text "text" - x - x "Text" x "x:{'lang':lang, 'size':expr}" "Displays as text." }
{x Disasm disasm "disasm" - x - x "Disassembly" x "x:{'arch':arch, 'size':expr}" "Displays as disassembled instructions, interpreting the data as raw machine code." }
{x Memory memory "memory" - x - x "Memory" x "x:{'size':expr}" "Displays as a raw memory grid." }
{- Graph graph "graph" - x - x "Graph" x "" "Displays as a pointer graph, visualizing nodes and edges formed by pointers directly." }
{x Bitmap bitmap "bitmap" - x - x "Bitmap" x "x:{'w':expr, 'h':expr, 'fmt':tex2dformat}" "Displays as a bitmap, interpreting the data as raw pixel data." }
{- Geo3D geo3d "geo3d" - x - x "Geometry (3D)" x "x:{'count':expr, 'vtx':expr, 'vtx_size':expr}" "Displays as geometry, interpreting the data as index or vertex data." }
}
@enum D_ViewRuleKind:
{
@expand(D_ViewRuleTable a) `$(a.name)`,
COUNT,
}
@data(D_ViewRuleSpecInfo) @c_file d_core_view_rule_spec_info_table:
{
@expand(D_ViewRuleTable a)
```{str8_lit_comp("$(a.string)"), str8_lit_comp("$(a.display_name)"), str8_lit_comp("$(a.schema)"), str8_lit_comp("$(a.description)"), (D_ViewRuleSpecInfoFlag_Inherited*$(a.ih == "x"))|(D_ViewRuleSpecInfoFlag_Expandable*$(a.ex == "x"))|(D_ViewRuleSpecInfoFlag_ExprResolution*$(a.xp == "x"))|(D_ViewRuleSpecInfoFlag_VizBlockProd*$(a.vb == "x")), }```;
}
////////////////////////////////
//~ rjf: Developer Toggles
@@ -114,7 +72,6 @@ D_DevToggleTable:
{eval_compiler_tooltips}
{eval_watch_key_tooltips}
{cmd_context_tooltips}
{scratch_mouse_draw}
{updating_indicator}
}
+125 -377
View File
@@ -1,8 +1,8 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#undef MARKUP_LAYER_COLOR
#define MARKUP_LAYER_COLOR 0.70f, 0.50f, 0.25f
#undef LAYER_COLOR
#define LAYER_COLOR 0x4d9ae3ff
////////////////////////////////
//~ rjf: Generated Code
@@ -12,14 +12,16 @@
////////////////////////////////
//~ rjf: Basic Helpers
#if !defined(XXH_IMPLEMENTATION)
# define XXH_IMPLEMENTATION
# define XXH_STATIC_LINKING_ONLY
# include "third_party/xxHash/xxhash.h"
#endif
internal U64
d_hash_from_seed_string(U64 seed, String8 string)
{
U64 result = seed;
for(U64 i = 0; i < string.size; i += 1)
{
result = ((result << 5) + result) + string.str[i];
}
U64 result = XXH3_64bits_withSeed(string.str, string.size, seed);
return result;
}
@@ -59,7 +61,7 @@ d_breakpoint_array_copy(Arena *arena, D_BreakpointArray *src)
for(U64 idx = 0; idx < dst.count; idx += 1)
{
dst.v[idx].file_path = push_str8_copy(arena, dst.v[idx].file_path);
dst.v[idx].symbol_name = push_str8_copy(arena, dst.v[idx].symbol_name);
dst.v[idx].vaddr_expr = push_str8_copy(arena, dst.v[idx].vaddr_expr);
dst.v[idx].condition = push_str8_copy(arena, dst.v[idx].condition);
}
return dst;
@@ -194,59 +196,6 @@ d_cmd_list_push_new(Arena *arena, D_CmdList *cmds, D_CmdKind kind, D_CmdParams *
cmds->count += 1;
}
////////////////////////////////
//~ rjf: View Rule Spec Stateful Functions
internal void
d_register_view_rule_specs(D_ViewRuleSpecInfoArray specs)
{
for(U64 idx = 0; idx < specs.count; idx += 1)
{
// rjf: extract info from array slot
D_ViewRuleSpecInfo *info = &specs.v[idx];
// rjf: skip empties
if(info->string.size == 0)
{
continue;
}
// rjf: determine hash/slot
U64 hash = d_hash_from_string(info->string);
U64 slot_idx = hash%d_state->view_rule_spec_table_size;
// rjf: allocate node & push
D_ViewRuleSpec *spec = push_array(d_state->arena, D_ViewRuleSpec, 1);
SLLStackPush_N(d_state->view_rule_spec_table[slot_idx], spec, hash_next);
// rjf: fill node
D_ViewRuleSpecInfo *info_copy = &spec->info;
MemoryCopyStruct(info_copy, info);
info_copy->string = push_str8_copy(d_state->arena, info->string);
info_copy->display_string = push_str8_copy(d_state->arena, info->display_string);
info_copy->description = push_str8_copy(d_state->arena, info->description);
}
}
internal D_ViewRuleSpec *
d_view_rule_spec_from_string(String8 string)
{
D_ViewRuleSpec *spec = &d_nil_core_view_rule_spec;
{
U64 hash = d_hash_from_string(string);
U64 slot_idx = hash%d_state->view_rule_spec_table_size;
for(D_ViewRuleSpec *s = d_state->view_rule_spec_table[slot_idx]; s != 0; s = s->hash_next)
{
if(str8_match(string, s->info.string, 0))
{
spec = s;
break;
}
}
}
return spec;
}
////////////////////////////////
//~ rjf: Stepping "Trap Net" Builders
@@ -351,13 +300,13 @@ d_trap_net_from_thread__step_over_inst(Arena *arena, CTRL_Entity *thread)
// rjf: thread => unpacked info
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process);
Arch arch = thread->arch;
U64 ip_vaddr = ctrl_query_cached_rip_from_thread(d_state->ctrl_entity_store, thread->handle);
U64 ip_vaddr = ctrl_rip_from_thread(&d_state->ctrl_entity_store->ctx, thread->handle);
// rjf: ip => machine code
String8 machine_code = {0};
{
Rng1U64 rng = r1u64(ip_vaddr, ip_vaddr+max_instruction_size_from_arch(arch));
CTRL_ProcessMemorySlice machine_code_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->handle, rng, os_now_microseconds()+5000);
CTRL_ProcessMemorySlice machine_code_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, rng, os_now_microseconds()+5000);
machine_code = machine_code_slice.data;
}
@@ -388,7 +337,7 @@ d_trap_net_from_thread__step_over_line(Arena *arena, CTRL_Entity *thread)
// rjf: thread => info
Arch arch = thread->arch;
U64 ip_vaddr = ctrl_query_cached_rip_from_thread(d_state->ctrl_entity_store, thread->handle);
U64 ip_vaddr = ctrl_rip_from_thread(&d_state->ctrl_entity_store->ctx, thread->handle);
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process);
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, ip_vaddr);
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module);
@@ -431,7 +380,7 @@ d_trap_net_from_thread__step_over_line(Arena *arena, CTRL_Entity *thread)
String8 machine_code = {0};
if(good_line_info)
{
CTRL_ProcessMemorySlice machine_code_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->handle, line_vaddr_rng, os_now_microseconds()+50000);
CTRL_ProcessMemorySlice machine_code_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, line_vaddr_rng, os_now_microseconds()+50000);
machine_code = machine_code_slice.data;
LogInfoNamedBlockF("machine_code_slice")
{
@@ -549,7 +498,7 @@ d_trap_net_from_thread__step_into_line(Arena *arena, CTRL_Entity *thread)
// rjf: thread => info
Arch arch = thread->arch;
U64 ip_vaddr = ctrl_query_cached_rip_from_thread(d_state->ctrl_entity_store, thread->handle);
U64 ip_vaddr = ctrl_rip_from_thread(&d_state->ctrl_entity_store->ctx, thread->handle);
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process);
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, ip_vaddr);
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module);
@@ -587,7 +536,7 @@ d_trap_net_from_thread__step_into_line(Arena *arena, CTRL_Entity *thread)
String8 machine_code = {0};
if(good_line_info)
{
CTRL_ProcessMemorySlice machine_code_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->handle, line_vaddr_rng, os_now_microseconds()+5000);
CTRL_ProcessMemorySlice machine_code_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, line_vaddr_rng, os_now_microseconds()+5000);
machine_code = machine_code_slice.data;
}
@@ -606,6 +555,16 @@ d_trap_net_from_thread__step_into_line(Arena *arena, CTRL_Entity *thread)
machine_code);
}
// rjf: determine last
DASM_CtrlFlowPoint *last_call_point = 0;
if(good_line_info) for(DASM_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next)
{
if(n->v.inst_flags & DASM_InstFlag_Call)
{
last_call_point = &n->v;
}
}
// rjf: push traps for all exit points
if(good_line_info) for(DASM_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next)
{
@@ -614,6 +573,23 @@ d_trap_net_from_thread__step_into_line(Arena *arena, CTRL_Entity *thread)
B32 add = 1;
U64 trap_addr = point->vaddr;
// rjf: if this is not the last call instruction in the control flow,
// and if we have no line info for this address, then do not add.
if(point != last_call_point &&
point->inst_flags & DASM_InstFlag_Call &&
point->jump_dest_vaddr != 0)
{
U64 jump_dest_vaddr = point->jump_dest_vaddr;
CTRL_Entity *jump_dest_module = ctrl_module_from_process_vaddr(process, jump_dest_vaddr);
U64 jump_dest_voff = ctrl_voff_from_vaddr(jump_dest_module, jump_dest_vaddr);
DI_Key jump_dest_dbgi_key = ctrl_dbgi_key_from_module(jump_dest_module);
D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, &jump_dest_dbgi_key, jump_dest_voff);
if(lines.count == 0)
{
add = 0;
}
}
// rjf: branches/jumps/returns => single-step & end, OR trap @ destination.
if(point->inst_flags & (DASM_InstFlag_Call|
DASM_InstFlag_Branch|
@@ -664,67 +640,6 @@ d_trap_net_from_thread__step_into_line(Arena *arena, CTRL_Entity *thread)
////////////////////////////////
//~ rjf: Debug Info Lookups
//- rjf: symbol lookups
internal String8
d_symbol_name_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff, B32 decorated)
{
String8 result = {0};
{
Temp scratch = scratch_begin(&arena, 1);
DI_Scope *scope = di_scope_open();
RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 0);
if(result.size == 0)
{
U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff);
RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx);
U64 proc_idx = scope->proc_idx;
RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx);
E_TypeKey type = e_type_key_ext(E_TypeKind_Function, procedure->type_idx, e_parse_ctx_module_idx_from_rdi(rdi));
String8 name = {0};
name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &name.size);
if(decorated && procedure->type_idx != 0)
{
String8List list = {0};
e_type_lhs_string_from_key(scratch.arena, type, &list, 0, 0);
str8_list_push(scratch.arena, &list, name);
e_type_rhs_string_from_key(scratch.arena, type, &list, 0);
result = str8_list_join(arena, &list, 0);
}
else
{
result = push_str8_copy(arena, name);
}
}
if(result.size == 0)
{
U64 global_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_GlobalVMap, voff);
RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, global_idx);
U64 name_size = 0;
U8 *name_ptr = rdi_string_from_idx(rdi, global_var->name_string_idx, &name_size);
result = push_str8_copy(arena, str8(name_ptr, name_size));
}
di_scope_close(scope);
scratch_end(scratch);
}
return result;
}
internal String8
d_symbol_name_from_process_vaddr(Arena *arena, CTRL_Entity *process, U64 vaddr, B32 decorated)
{
ProfBeginFunction();
String8 result = {0};
{
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, vaddr);
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module);
U64 voff = ctrl_voff_from_vaddr(module, vaddr);
result = d_symbol_name_from_dbgi_key_voff(arena, &dbgi_key, voff, decorated);
}
ProfEnd();
return result;
}
//- rjf: symbol -> voff lookups
internal U64
@@ -741,7 +656,7 @@ d_voff_from_dbgi_key_symbol_name(DI_Key *dbgi_key, String8 symbol_name)
RDI_NameMapKind_GlobalVariables,
RDI_NameMapKind_Procedures,
};
if(rdi != &di_rdi_parsed_nil)
if(rdi != &rdi_parsed_nil)
{
for(U64 name_map_kind_idx = 0;
name_map_kind_idx < ArrayCount(name_map_kinds);
@@ -808,45 +723,6 @@ d_voff_from_dbgi_key_symbol_name(DI_Key *dbgi_key, String8 symbol_name)
return result;
}
internal U64
d_type_num_from_dbgi_key_name(DI_Key *dbgi_key, String8 name)
{
ProfBeginFunction();
DI_Scope *scope = di_scope_open();
U64 result = 0;
{
RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 0);
RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Types);
RDI_ParsedNameMap parsed_name_map = {0};
rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map);
RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, name.str, name.size);
U64 entity_num = 0;
if(node != 0)
{
switch(node->match_count)
{
case 1:
{
entity_num = node->match_idx_or_idx_run_first + 1;
}break;
default:
{
U32 num = 0;
U32 *run = rdi_matches_from_map_node(rdi, node, &num);
if(num != 0)
{
entity_num = run[0]+1;
}
}break;
}
}
result = entity_num;
}
di_scope_close(scope);
ProfEnd();
return result;
}
//- rjf: voff -> line info
internal D_LineList
@@ -968,7 +844,7 @@ d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key,
// rjf: file_path_normalized * rdi -> src_id
B32 good_src_id = 0;
U32 src_id = 0;
if(rdi != &di_rdi_parsed_nil) ProfScope("file_path_normalized * rdi -> src_id")
if(rdi != &rdi_parsed_nil) ProfScope("file_path_normalized * rdi -> src_id")
{
RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths);
RDI_ParsedNameMap map = {0};
@@ -1066,7 +942,7 @@ d_lines_array_from_file_path_line_range(Arena *arena, String8 file_path, Rng1S64
// rjf: file_path_normalized * rdi -> src_id
B32 good_src_id = 0;
U32 src_id = 0;
if(rdi != &di_rdi_parsed_nil) ProfScope("file_path_normalized * rdi -> src_id")
if(rdi != &rdi_parsed_nil) ProfScope("file_path_normalized * rdi -> src_id")
{
RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths);
RDI_ParsedNameMap map = {0};
@@ -1185,7 +1061,7 @@ d_tls_base_vaddr_from_process_root_rip(CTRL_Entity *process, U64 root_vaddr, U64
U64 tls_index = 0;
if(addr_size != 0)
{
CTRL_ProcessMemorySlice tls_index_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->handle, tls_vaddr_range, 0);
CTRL_ProcessMemorySlice tls_index_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, tls_vaddr_range, 0);
if(tls_index_slice.data.size >= addr_size)
{
tls_index = *(U64 *)tls_index_slice.data.str;
@@ -1198,13 +1074,13 @@ d_tls_base_vaddr_from_process_root_rip(CTRL_Entity *process, U64 root_vaddr, U64
U64 thread_info_addr = root_vaddr;
U64 tls_addr_off = tls_index*addr_size;
U64 tls_addr_array = 0;
CTRL_ProcessMemorySlice tls_addr_array_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->handle, r1u64(thread_info_addr, thread_info_addr+addr_size), 0);
CTRL_ProcessMemorySlice tls_addr_array_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, r1u64(thread_info_addr, thread_info_addr+addr_size), 0);
String8 tls_addr_array_data = tls_addr_array_slice.data;
if(tls_addr_array_data.size >= 8)
{
MemoryCopy(&tls_addr_array, tls_addr_array_data.str, sizeof(U64));
}
CTRL_ProcessMemorySlice result_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->handle, r1u64(tls_addr_array + tls_addr_off, tls_addr_array + tls_addr_off + addr_size), 0);
CTRL_ProcessMemorySlice result_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, r1u64(tls_addr_array + tls_addr_off, tls_addr_array + tls_addr_off + addr_size), 0);
String8 result_data = result_slice.data;
if(result_data.size >= 8)
{
@@ -1299,10 +1175,10 @@ internal DI_KeyList
d_push_active_dbgi_key_list(Arena *arena)
{
DI_KeyList dbgis = {0};
CTRL_EntityList modules = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Module);
for(CTRL_EntityNode *n = modules.first; n != 0; n = n->next)
CTRL_EntityArray modules = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Module);
for EachIndex(idx, modules.count)
{
CTRL_Entity *module = n->v;
CTRL_Entity *module = modules.v[idx];
DI_Key key = ctrl_dbgi_key_from_module(module);
di_key_list_push(arena, &dbgis, &key);
}
@@ -1311,61 +1187,6 @@ d_push_active_dbgi_key_list(Arena *arena)
//- rjf: per-run caches
internal CTRL_Unwind
d_query_cached_unwind_from_thread(CTRL_Entity *thread)
{
Temp scratch = scratch_begin(0, 0);
CTRL_Unwind result = {0};
if(thread->kind == CTRL_EntityKind_Thread)
{
U64 reg_gen = ctrl_reg_gen();
U64 mem_gen = ctrl_mem_gen();
D_UnwindCache *cache = &d_state->unwind_cache;
CTRL_Handle handle = thread->handle;
U64 hash = d_hash_from_string(str8_struct(&handle));
U64 slot_idx = hash%cache->slots_count;
D_UnwindCacheSlot *slot = &cache->slots[slot_idx];
D_UnwindCacheNode *node = 0;
for(D_UnwindCacheNode *n = slot->first; n != 0; n = n->next)
{
if(ctrl_handle_match(handle, n->thread))
{
node = n;
break;
}
}
if(node == 0)
{
node = cache->free_node;
if(node != 0)
{
SLLStackPop(cache->free_node);
}
else
{
node = push_array_no_zero(d_state->arena, D_UnwindCacheNode, 1);
}
MemoryZeroStruct(node);
DLLPushBack(slot->first, slot->last, node);
node->arena = arena_alloc();
node->thread = handle;
}
if(!d_state->ctrl_is_running && (node->reggen != reg_gen || node->memgen != mem_gen))
{
CTRL_Unwind new_unwind = ctrl_unwind_from_thread(scratch.arena, d_state->ctrl_entity_store, thread->handle, os_now_microseconds()+100);
if(!(new_unwind.flags & (CTRL_UnwindFlag_Error|CTRL_UnwindFlag_Stale)) && new_unwind.frames.count != 0)
{
node->unwind = ctrl_unwind_deep_copy(node->arena, thread->arch, &new_unwind);
node->reggen = reg_gen;
node->memgen = mem_gen;
}
}
result = node->unwind;
}
scratch_end(scratch);
return result;
}
internal U64
d_query_cached_rip_from_thread(CTRL_Entity *thread)
{
@@ -1379,15 +1200,17 @@ d_query_cached_rip_from_thread_unwind(CTRL_Entity *thread, U64 unwind_count)
U64 result = 0;
if(unwind_count == 0)
{
result = ctrl_query_cached_rip_from_thread(d_state->ctrl_entity_store, thread->handle);
result = ctrl_rip_from_thread(&d_state->ctrl_entity_store->ctx, thread->handle);
}
else
{
CTRL_Unwind unwind = d_query_cached_unwind_from_thread(thread);
if(unwind.frames.count != 0)
CTRL_Scope *ctrl_scope = ctrl_scope_open();
CTRL_CallStack callstack = ctrl_call_stack_from_thread(ctrl_scope, &d_state->ctrl_entity_store->ctx, thread, 1, 0);
if(callstack.concrete_frames_count != 0)
{
result = regs_rip_from_arch_block(thread->arch, unwind.frames.v[unwind_count%unwind.frames.count].regs);
result = regs_rip_from_arch_block(thread->arch, callstack.concrete_frames[unwind_count%callstack.concrete_frames_count]->regs);
}
ctrl_scope_close(ctrl_scope);
}
return result;
}
@@ -1594,22 +1417,13 @@ d_init(void)
d_state = push_array(arena, D_State, 1);
d_state->arena = arena;
d_state->cmds_arena = arena_alloc();
d_state->output_log_key = hs_hash_from_data(str8_lit("output_log_key"));
d_state->ctrl_entity_store = ctrl_entity_store_alloc();
d_state->output_log_key = hs_key_make(hs_root_alloc(), hs_id_make(0, 0));
hs_submit_data(d_state->output_log_key, 0, str8_zero());
d_state->ctrl_entity_store = ctrl_entity_ctx_rw_store_alloc();
d_state->ctrl_stop_arena = arena_alloc();
d_state->view_rule_spec_table_size = 1024;
d_state->view_rule_spec_table = push_array(arena, D_ViewRuleSpec *, d_state->view_rule_spec_table_size);
d_state->ctrl_msg_arena = arena_alloc();
// rjf: register core view rules
{
D_ViewRuleSpecInfoArray array = {d_core_view_rule_spec_info_table, ArrayCount(d_core_view_rule_spec_info_table)};
d_register_view_rule_specs(array);
}
// rjf: set up caches
d_state->unwind_cache.slots_count = 1024;
d_state->unwind_cache.slots = push_array(arena, D_UnwindCacheSlot, d_state->unwind_cache.slots_count);
for(U64 idx = 0; idx < ArrayCount(d_state->tls_base_caches); idx += 1)
{
d_state->tls_base_caches[idx].arena = arena_alloc();
@@ -1628,13 +1442,12 @@ d_init(void)
}
internal D_EventList
d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_PathMapArray *path_maps, U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64], CTRL_MetaEvalArray *meta_evals)
d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_PathMapArray *path_maps, U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64])
{
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
D_EventList result = {0};
d_state->frame_index += 1;
d_state->frame_eval_memread_endt_us = os_now_microseconds() + 1000;
//////////////////////////////
//- rjf: sync with ctrl thread
@@ -1699,7 +1512,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
// rjf: push stop event to caller, if this is not a soft-halt
if(should_snap)
{
CTRL_Entity *thread = ctrl_entity_from_handle(d_state->ctrl_entity_store, event->entity);
CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, event->entity);
D_EventCause cause = D_EventCause_Null;
switch(event->cause)
{
@@ -1725,6 +1538,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
evt->cause = cause;
evt->thread = thread->kind == CTRL_EntityKind_Thread ? thread->handle : ctrl_handle_zero();
evt->vaddr = event->rip_vaddr;
evt->id = event->u64_code;
}
}break;
@@ -1733,7 +1547,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
case CTRL_EventKind_NewProc:
{
// rjf: the first process? -> clear session output
CTRL_EntityList existing_processes = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Process);
CTRL_EntityArray existing_processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process);
if(existing_processes.count == 1)
{
MTX_Op op = {r1u64(0, 0xffffffffffffffffull), str8_lit("[new session]\n")};
@@ -1816,10 +1630,10 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
// rjf: build data strings of all param data
String8List strings = {0};
{
CTRL_EntityList threads = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Thread);
for(CTRL_EntityNode *n = threads.first; n != 0; n = n->next)
CTRL_EntityArray threads = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Thread);
for EachIndex(idx, threads.count)
{
CTRL_Entity *thread = n->v;
CTRL_Entity *thread = threads.v[idx];
if(thread->is_frozen)
{
str8_list_push(scratch.arena, &strings, str8_struct(&thread->id));
@@ -1831,8 +1645,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
D_Breakpoint *bp = &breakpoints->v[idx];
str8_list_push(scratch.arena, &strings, bp->file_path);
str8_list_push(scratch.arena, &strings, str8_struct(&bp->pt));
str8_list_push(scratch.arena, &strings, bp->symbol_name);
str8_list_push(scratch.arena, &strings, str8_struct(&bp->vaddr));
str8_list_push(scratch.arena, &strings, bp->vaddr_expr);
str8_list_push(scratch.arena, &strings, bp->condition);
}
}
@@ -1854,53 +1667,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
d_cmd(D_CmdKind_SoftHaltRefresh);
}
//////////////////////////////
//- rjf: garbage collect eliminated thread unwinds
//
for(U64 slot_idx = 0; slot_idx < d_state->unwind_cache.slots_count; slot_idx += 1)
{
D_UnwindCacheSlot *slot = &d_state->unwind_cache.slots[slot_idx];
for(D_UnwindCacheNode *n = slot->first, *next = 0; n != 0; n = next)
{
next = n->next;
if(ctrl_entity_from_handle(d_state->ctrl_entity_store, n->thread) == &ctrl_entity_nil)
{
DLLRemove(slot->first, slot->last, n);
arena_release(n->arena);
SLLStackPush(d_state->unwind_cache.free_node, n);
}
}
}
//////////////////////////////
//- rjf: sync with di parsers
//
ProfScope("sync with di parsers")
{
DI_EventList events = di_p2u_pop_events(scratch.arena, 0);
for(DI_EventNode *n = events.first; n != 0; n = n->next)
{
DI_Event *event = &n->v;
switch(event->kind)
{
default:{}break;
case DI_EventKind_ConversionStarted:
{
RD_Entity *task = rd_entity_alloc(rd_entity_root(), RD_EntityKind_ConversionTask);
rd_entity_equip_name(task, event->string);
}break;
case DI_EventKind_ConversionEnded:
{
RD_Entity *task = rd_entity_from_name_and_kind(event->string, RD_EntityKind_ConversionTask);
if(!rd_entity_is_nil(task))
{
rd_entity_mark_for_deletion(task);
}
}break;
}
}
}
//////////////////////////////
//- rjf: process top-level commands
//
@@ -1927,7 +1693,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
//- rjf: low-level target control operations
case D_CmdKind_LaunchAndRun:
case D_CmdKind_LaunchAndInit:
case D_CmdKind_LaunchAndStepInto:
{
// rjf: get list of targets to launch
D_TargetArray *targets_to_launch = &params->targets;
@@ -1998,7 +1764,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
msg->debug_subprocesses = target->debug_subprocesses;
msg->env_inherit = 1;
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
MemoryCopyStruct(&msg->meta_evals, meta_evals);
str8_list_push(scratch.arena, &msg->entry_points, custom_entry_point_name);
msg->env_string_list = env;
}
@@ -2008,7 +1773,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
need_run = 1;
run_kind = D_RunKind_Run;
run_thread = &ctrl_entity_nil;
run_flags = (cmd->kind == D_CmdKind_LaunchAndInit) ? CTRL_RunFlag_StopOnEntryPoint : 0;
run_flags = (cmd->kind == D_CmdKind_LaunchAndStepInto) ? CTRL_RunFlag_StopOnEntryPoint : 0;
}
// rjf: no targets -> error
@@ -2019,7 +1784,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
}break;
case D_CmdKind_Kill:
{
CTRL_Entity *process = ctrl_entity_from_handle(d_state->ctrl_entity_store, params->process);
CTRL_Entity *process = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->process);
if(process == &ctrl_entity_nil)
{
log_user_error(str8_lit("Cannot kill; no process was specified."));
@@ -2031,7 +1796,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
msg->exit_code = 1;
msg->entity = process->handle;
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
MemoryCopyStruct(&msg->meta_evals, meta_evals);
}
}break;
case D_CmdKind_KillAll:
@@ -2040,11 +1804,10 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
msg->kind = CTRL_MsgKind_KillAll;
msg->exit_code = 1;
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
MemoryCopyStruct(&msg->meta_evals, meta_evals);
}break;
case D_CmdKind_Detach:
{
CTRL_Entity *process = ctrl_entity_from_handle(d_state->ctrl_entity_store, params->process);
CTRL_Entity *process = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->process);
if(process == &ctrl_entity_nil)
{
log_user_error(str8_lit("Cannot detach; no process specified."));
@@ -2055,18 +1818,18 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
msg->kind = CTRL_MsgKind_Detach;
msg->entity = process->handle;
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
MemoryCopyStruct(&msg->meta_evals, meta_evals);
}
}break;
case D_CmdKind_Continue:
{
B32 good_to_run = 0;
CTRL_EntityList threads = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Thread);
CTRL_EntityArray threads = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Thread);
if(threads.count > 0)
{
for(CTRL_EntityNode *n = threads.first; n != 0; n = n->next)
for EachIndex(idx, threads.count)
{
if(!n->v->is_frozen)
CTRL_Entity *thread = threads.v[idx];
if(!thread->is_frozen)
{
good_to_run = 1;
break;
@@ -2090,7 +1853,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
case D_CmdKind_StepOverLine:
case D_CmdKind_StepOut:
{
CTRL_Entity *thread = ctrl_entity_from_handle(d_state->ctrl_entity_store, params->thread);
CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->thread);
if(thread == &ctrl_entity_nil)
{
log_user_error(str8_lit("Must have a selected thread to step."));
@@ -2119,13 +1882,15 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
case D_CmdKind_StepOverLine: {traps = d_trap_net_from_thread__step_over_line(scratch.arena, thread);}break;
case D_CmdKind_StepOut:
{
// rjf: thread => full unwind
CTRL_Unwind unwind = ctrl_unwind_from_thread(scratch.arena, d_state->ctrl_entity_store, thread->handle, os_now_microseconds()+10000);
CTRL_Scope *ctrl_scope = ctrl_scope_open();
// rjf: thread => call stack
CTRL_CallStack callstack = ctrl_call_stack_from_thread(ctrl_scope, &d_state->ctrl_entity_store->ctx, thread, 1, os_now_microseconds()+10000);
// rjf: use first unwind frame to generate trap
if(unwind.flags == 0 && unwind.frames.count > 1)
if(callstack.concrete_frames_count > 1)
{
U64 vaddr = regs_rip_from_arch_block(thread->arch, unwind.frames.v[1].regs);
U64 vaddr = regs_rip_from_arch_block(thread->arch, callstack.concrete_frames[1]->regs);
CTRL_Trap trap = {CTRL_TrapFlag_EndStepping|CTRL_TrapFlag_IgnoreStackPointerCheck, vaddr};
ctrl_trap_list_push(scratch.arena, &traps, &trap);
}
@@ -2134,6 +1899,8 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
log_user_error(str8_lit("Could not find the return address of the current callstack frame successfully."));
good = 0;
}
ctrl_scope_close(ctrl_scope);
}break;
}
if(good && traps.count != 0)
@@ -2164,38 +1931,18 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
{
need_run = 1;
run_kind = d_state->ctrl_last_run_kind;
run_thread = ctrl_entity_from_handle(d_state->ctrl_entity_store, d_state->ctrl_last_run_thread_handle);
run_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, d_state->ctrl_last_run_thread_handle);
run_flags = d_state->ctrl_last_run_flags;
run_traps = d_state->ctrl_last_run_traps;
}break;
case D_CmdKind_SetThreadIP:
{
CTRL_Entity *thread = ctrl_entity_from_handle(d_state->ctrl_entity_store, params->thread);
CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->thread);
U64 vaddr = params->vaddr;
void *block = ctrl_query_cached_reg_block_from_thread(scratch.arena, d_state->ctrl_entity_store, thread->handle);
void *block = ctrl_reg_block_from_thread(scratch.arena, &d_state->ctrl_entity_store->ctx, thread->handle);
regs_arch_block_write_rip(thread->arch, block, vaddr);
B32 result = ctrl_thread_write_reg_block(thread->handle, block);
// rjf: early mutation of unwind cache for immediate frontend effect
if(result)
{
D_UnwindCache *cache = &d_state->unwind_cache;
if(cache->slots_count != 0)
{
CTRL_Handle thread_handle = thread->handle;
U64 hash = d_hash_from_string(str8_struct(&thread_handle));
U64 slot_idx = hash%cache->slots_count;
D_UnwindCacheSlot *slot = &cache->slots[slot_idx];
for(D_UnwindCacheNode *n = slot->first; n != 0; n = n->next)
{
if(ctrl_handle_match(n->thread, thread_handle) && n->unwind.frames.count != 0)
{
regs_arch_block_write_rip(thread->arch, n->unwind.frames.v[0].regs, vaddr);
break;
}
}
}
}
(void)result;
}break;
//- rjf: high-level composite target control operations
@@ -2203,20 +1950,20 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
{
run_extra_bps.count = 1;
run_extra_bps.v = push_array(scratch.arena, D_Breakpoint, 1);
run_extra_bps.v[0].file_path = params->file_path;
run_extra_bps.v[0].pt = params->cursor;
d_cmd(D_CmdKind_Run);
}break;
case D_CmdKind_RunToAddress:
{
run_extra_bps.count = 1;
run_extra_bps.v = push_array(scratch.arena, D_Breakpoint, 1);
run_extra_bps.v[0].vaddr = params->vaddr;
if(params->file_path.size != 0)
{
run_extra_bps.v[0].file_path = params->file_path;
run_extra_bps.v[0].pt = params->cursor;
}
else if(params->vaddr != 0)
{
run_extra_bps.v[0].vaddr_expr = push_str8f(scratch.arena, "0x%I64x", params->vaddr);
}
d_cmd(D_CmdKind_Run);
}break;
case D_CmdKind_Run:
{
CTRL_EntityList processes = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Process);
CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process);
if(processes.count != 0)
{
d_cmd(D_CmdKind_Continue);
@@ -2228,7 +1975,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
}break;
case D_CmdKind_Restart:
{
CTRL_EntityList processes = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Process);
CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process);
if(processes.count != 0)
{
d_cmd(D_CmdKind_KillAll);
@@ -2238,7 +1985,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
case D_CmdKind_StepInto:
case D_CmdKind_StepOver:
{
CTRL_EntityList processes = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Process);
CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process);
if(processes.count != 0)
{
D_CmdKind step_cmd_kind = (cmd->kind == D_CmdKind_StepInto
@@ -2255,7 +2002,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
}
else if(!d_ctrl_targets_running())
{
d_cmd(D_CmdKind_LaunchAndInit, .targets = *targets);
d_cmd(D_CmdKind_LaunchAndStepInto, .targets = *targets);
}
}break;
@@ -2277,18 +2024,18 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
case D_CmdKind_FreezeLocalMachine:
{
CTRL_MachineID machine_id = CTRL_MachineID_Local;
d_cmd(D_CmdKind_FreezeMachine, .machine = ctrl_handle_make(machine_id, dmn_handle_zero()));
d_cmd(D_CmdKind_FreezeMachine, .entity = ctrl_handle_make(machine_id, dmn_handle_zero()));
}break;
case D_CmdKind_ThawLocalMachine:
{
CTRL_MachineID machine_id = CTRL_MachineID_Local;
d_cmd(D_CmdKind_ThawMachine, .machine = ctrl_handle_make(machine_id, dmn_handle_zero()));
d_cmd(D_CmdKind_ThawMachine, .entity = ctrl_handle_make(machine_id, dmn_handle_zero()));
}break;
case D_CmdKind_FreezeEntity:
case D_CmdKind_ThawEntity:
{
B32 should_freeze = (cmd->kind == D_CmdKind_FreezeEntity);
CTRL_Entity *root = ctrl_entity_from_handle(d_state->ctrl_entity_store, params->entity);
CTRL_Entity *root = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->entity);
for(CTRL_Entity *e = root; e != &ctrl_entity_nil; e = ctrl_entity_rec_depth_first_pre(e, root).next)
{
if(e->kind == CTRL_EntityKind_Thread)
@@ -2303,7 +2050,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
{
need_run = 1;
run_kind = d_state->ctrl_last_run_kind;
run_thread = ctrl_entity_from_handle(d_state->ctrl_entity_store, d_state->ctrl_last_run_thread_handle);
run_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, d_state->ctrl_last_run_thread_handle);
run_flags = d_state->ctrl_last_run_flags;
run_traps = d_state->ctrl_last_run_traps;
}
@@ -2312,12 +2059,12 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
//- rjf: entity decoration
case D_CmdKind_SetEntityColor:
{
CTRL_Entity *entity = ctrl_entity_from_handle(d_state->ctrl_entity_store, params->entity);
CTRL_Entity *entity = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->entity);
entity->rgba = params->rgba;
}break;
case D_CmdKind_SetEntityName:
{
CTRL_Entity *entity = ctrl_entity_from_handle(d_state->ctrl_entity_store, params->entity);
CTRL_Entity *entity = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->entity);
ctrl_entity_equip_string(d_state->ctrl_entity_store, entity, params->string);
}break;
@@ -2331,7 +2078,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
msg->kind = CTRL_MsgKind_Attach;
msg->entity_id = pid;
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
MemoryCopyStruct(&msg->meta_evals, meta_evals);
}
}break;
}
@@ -2353,7 +2099,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
msg->entity = run_thread->handle;
msg->parent = process->handle;
MemoryCopyArray(msg->exception_code_filters, exception_code_filters);
MemoryCopyStruct(&msg->meta_evals, meta_evals);
MemoryCopyStruct(&msg->traps, &run_traps);
D_BreakpointArray *bp_batches[] =
{
@@ -2368,6 +2113,12 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
// rjf: unpack user breakpoint entity
D_Breakpoint *bp = &batch_breakpoints->v[idx];
// rjf: d -> ctrl flags
CTRL_UserBreakpointFlags ctrl_bp_flags = 0;
if(bp->flags & D_BreakpointFlag_BreakOnWrite) { ctrl_bp_flags |= CTRL_UserBreakpointFlag_BreakOnWrite; }
if(bp->flags & D_BreakpointFlag_BreakOnRead) { ctrl_bp_flags |= CTRL_UserBreakpointFlag_BreakOnRead; }
if(bp->flags & D_BreakpointFlag_BreakOnExecute) { ctrl_bp_flags |= CTRL_UserBreakpointFlag_BreakOnExecute; }
// rjf: textual location -> add breakpoints for all possible override locations
if(bp->file_path.size != 0 && bp->pt.line != 0)
{
@@ -2375,28 +2126,25 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
for(String8Node *n = overrides.first; n != 0; n = n->next)
{
CTRL_UserBreakpoint ctrl_user_bp = {CTRL_UserBreakpointKind_FileNameAndLineColNumber};
ctrl_user_bp.flags = ctrl_bp_flags;
ctrl_user_bp.id = bp->id;
ctrl_user_bp.string = n->string;
ctrl_user_bp.pt = bp->pt;
ctrl_user_bp.condition = bp->condition;
ctrl_user_bp.size = bp->size;
ctrl_user_breakpoint_list_push(scratch.arena, &msg->user_bps, &ctrl_user_bp);
}
}
// rjf: virtual address location -> add breakpoint for address
else if(bp->vaddr != 0)
// rjf: virtual address expression -> add expression breakpoint
else if(bp->vaddr_expr.size != 0)
{
CTRL_UserBreakpoint ctrl_user_bp = {CTRL_UserBreakpointKind_VirtualAddress};
ctrl_user_bp.u64 = bp->vaddr;
ctrl_user_bp.condition = bp->condition;
ctrl_user_breakpoint_list_push(scratch.arena, &msg->user_bps, &ctrl_user_bp);
}
// rjf: symbol name location -> add breakpoint for symbol name
else if(bp->symbol_name.size != 0)
{
CTRL_UserBreakpoint ctrl_user_bp = {CTRL_UserBreakpointKind_SymbolNameAndOffset};
ctrl_user_bp.string = bp->symbol_name;
CTRL_UserBreakpoint ctrl_user_bp = {CTRL_UserBreakpointKind_Expression};
ctrl_user_bp.flags = ctrl_bp_flags;
ctrl_user_bp.id = bp->id;
ctrl_user_bp.string = bp->vaddr_expr;
ctrl_user_bp.condition = bp->condition;
ctrl_user_bp.size = bp->size;
ctrl_user_breakpoint_list_push(scratch.arena, &msg->user_bps, &ctrl_user_bp);
}
}
+16 -89
View File
@@ -28,14 +28,24 @@ struct D_TargetArray
U64 count;
};
typedef U32 D_BreakpointFlags;
enum
{
D_BreakpointFlag_BreakOnWrite = (1<<0),
D_BreakpointFlag_BreakOnRead = (1<<1),
D_BreakpointFlag_BreakOnExecute = (1<<2),
};
typedef struct D_Breakpoint D_Breakpoint;
struct D_Breakpoint
{
D_BreakpointFlags flags;
U64 id;
String8 file_path;
TxtPt pt;
String8 symbol_name;
U64 vaddr;
String8 vaddr_expr;
String8 condition;
U64 size;
};
typedef struct D_BreakpointArray D_BreakpointArray;
@@ -89,6 +99,7 @@ struct D_Event
CTRL_Handle thread;
U64 vaddr;
U64 code;
U64 id;
};
typedef struct D_EventNode D_EventNode;
@@ -158,42 +169,6 @@ D_RunKind;
#include "dbg_engine/generated/dbg_engine.meta.h"
////////////////////////////////
//~ rjf: View Rules
typedef U32 D_ViewRuleSpecInfoFlags; // NOTE(rjf): see @view_rule_info
enum
{
D_ViewRuleSpecInfoFlag_Inherited = (1<<0),
D_ViewRuleSpecInfoFlag_Expandable = (1<<1),
D_ViewRuleSpecInfoFlag_ExprResolution = (1<<2),
D_ViewRuleSpecInfoFlag_VizBlockProd = (1<<3),
};
typedef struct D_ViewRuleSpecInfo D_ViewRuleSpecInfo;
struct D_ViewRuleSpecInfo
{
String8 string;
String8 display_string;
String8 schema;
String8 description;
D_ViewRuleSpecInfoFlags flags;
};
typedef struct D_ViewRuleSpecInfoArray D_ViewRuleSpecInfoArray;
struct D_ViewRuleSpecInfoArray
{
D_ViewRuleSpecInfo *v;
U64 count;
};
typedef struct D_ViewRuleSpec D_ViewRuleSpec;
struct D_ViewRuleSpec
{
D_ViewRuleSpec *hash_next;
D_ViewRuleSpecInfo info;
};
////////////////////////////////
//~ rjf: Command Types
@@ -240,35 +215,6 @@ struct D_CmdList
////////////////////////////////
//~ rjf: Main State Caches
//- rjf: per-thread unwind cache
typedef struct D_UnwindCacheNode D_UnwindCacheNode;
struct D_UnwindCacheNode
{
D_UnwindCacheNode *next;
D_UnwindCacheNode *prev;
U64 reggen;
U64 memgen;
Arena *arena;
CTRL_Handle thread;
CTRL_Unwind unwind;
};
typedef struct D_UnwindCacheSlot D_UnwindCacheSlot;
struct D_UnwindCacheSlot
{
D_UnwindCacheNode *first;
D_UnwindCacheNode *last;
};
typedef struct D_UnwindCache D_UnwindCache;
struct D_UnwindCache
{
U64 slots_count;
D_UnwindCacheSlot *slots;
D_UnwindCacheNode *free_node;
};
//- rjf: per-run tls-base-vaddr cache
typedef struct D_RunTLSBaseCacheNode D_RunTLSBaseCacheNode;
@@ -331,17 +277,15 @@ struct D_State
// rjf: top-level state
Arena *arena;
U64 frame_index;
U64 frame_eval_memread_endt_us;
// rjf: commands
Arena *cmds_arena;
D_CmdList cmds;
// rjf: output log key
U128 output_log_key;
HS_Key output_log_key;
// rjf: per-run caches
D_UnwindCache unwind_cache;
U64 tls_base_cache_reggen_idx;
U64 tls_base_cache_memgen_idx;
D_RunTLSBaseCache tls_base_caches[2];
@@ -353,10 +297,6 @@ struct D_State
D_RunLocalsCache member_caches[2];
U64 member_cache_gen;
// rjf: view rule specification table
U64 view_rule_spec_table_size;
D_ViewRuleSpec **view_rule_spec_table;
// rjf: user -> ctrl driving state
Arena *ctrl_last_run_arena;
D_RunKind ctrl_last_run_kind;
@@ -373,7 +313,7 @@ struct D_State
CTRL_MsgList ctrl_msgs;
// rjf: ctrl -> user reading state
CTRL_EntityStore *ctrl_entity_store;
CTRL_EntityCtxRWStore *ctrl_entity_store;
Arena *ctrl_stop_arena;
CTRL_Event ctrl_last_stop_event;
};
@@ -381,7 +321,6 @@ struct D_State
////////////////////////////////
//~ rjf: Globals
read_only global D_ViewRuleSpec d_nil_core_view_rule_spec = {0};
global D_State *d_state = 0;
////////////////////////////////
@@ -416,12 +355,6 @@ internal D_CmdParams d_cmd_params_copy(Arena *arena, D_CmdParams *src);
//- rjf: command lists
internal void d_cmd_list_push_new(Arena *arena, D_CmdList *cmds, D_CmdKind kind, D_CmdParams *params);
////////////////////////////////
//~ rjf: View Rule Spec Stateful Functions
internal void d_register_view_rule_specs(D_ViewRuleSpecInfoArray specs);
internal D_ViewRuleSpec *d_view_rule_spec_from_string(String8 string);
////////////////////////////////
//~ rjf: Stepping "Trap Net" Builders
@@ -432,13 +365,8 @@ internal CTRL_TrapList d_trap_net_from_thread__step_into_line(Arena *arena, CTRL
////////////////////////////////
//~ rjf: Debug Info Lookups
//- rjf: voff|vaddr -> symbol lookups
internal String8 d_symbol_name_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff, B32 decorated);
internal String8 d_symbol_name_from_process_vaddr(Arena *arena, CTRL_Entity *process, U64 vaddr, B32 decorated);
//- rjf: symbol -> voff lookups
internal U64 d_voff_from_dbgi_key_symbol_name(DI_Key *dbgi_key, String8 symbol_name);
internal U64 d_type_num_from_dbgi_key_name(DI_Key *dbgi_key, String8 name);
//- rjf: voff -> line info
internal D_LineList d_lines_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff);
@@ -477,7 +405,6 @@ internal B32 d_ctrl_targets_running(void);
internal DI_KeyList d_push_active_dbgi_key_list(Arena *arena);
//- rjf: per-run caches
internal CTRL_Unwind d_query_cached_unwind_from_thread(CTRL_Entity *thread);
internal U64 d_query_cached_rip_from_thread(CTRL_Entity *thread);
internal U64 d_query_cached_rip_from_thread_unwind(CTRL_Entity *thread, U64 unwind_count);
internal U64 d_query_cached_tls_base_vaddr_from_process_root_rip(CTRL_Entity *process, U64 root_vaddr, U64 rip_vaddr);
@@ -495,6 +422,6 @@ internal B32 d_next_cmd(D_Cmd **cmd);
//~ rjf: Main Layer Top-Level Calls
internal void d_init(void);
internal D_EventList d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_PathMapArray *path_maps, U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64], CTRL_MetaEvalArray *meta_evals);
internal D_EventList d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_PathMapArray *path_maps, U64 exception_code_filters[(CTRL_ExceptionCodeKind_COUNT+63)/64]);
#endif // DBG_ENGINE_CORE_H
@@ -3,31 +3,3 @@
//- GENERATED CODE
C_LINKAGE_BEGIN
D_ViewRuleSpecInfo d_core_view_rule_spec_info_table[21] =
{
{str8_lit_comp("default"), str8_lit_comp("Default"), str8_lit_comp(""), str8_lit_comp(""), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("array"), str8_lit_comp("Array"), str8_lit_comp("x:{expr}"), str8_lit_comp("Specifies that a pointer points to N elements, rather than only 1."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*1)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("slice"), str8_lit_comp("Slice"), str8_lit_comp(""), str8_lit_comp("Specifies that a pointer within a struct, also containing an integer, points to the number of elements encoded by the integer."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*1)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("list"), str8_lit_comp("List"), str8_lit_comp("x:{member}"), str8_lit_comp("Specifies that some struct, union, or class forms the top of a linked list, and the member which points at the following element in the list."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("bswap"), str8_lit_comp("Byte Swap"), str8_lit_comp(""), str8_lit_comp("Specifies that all integral evaluations should be byte-swapped, such that their endianness is reversed."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*1)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("cast"), str8_lit_comp("Cast"), str8_lit_comp("x:{type}"), str8_lit_comp("Specifies that the expression to which the view rule is applied should be casted to the provided type."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*1)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("dec"), str8_lit_comp("Decimal Base (Base 10)"), str8_lit_comp(""), str8_lit_comp("Specifies that all integral evaluations should appear in base-10 form."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("bin"), str8_lit_comp("Binary Base (Base 2)"), str8_lit_comp(""), str8_lit_comp("Specifies that all integral evaluations should appear in base-2 form."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("oct"), str8_lit_comp("Octal Base (Base 8)"), str8_lit_comp(""), str8_lit_comp("Specifies that all integral evaluations should appear in base-8 form."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("hex"), str8_lit_comp("Hexadecimal Base (Base 16)"), str8_lit_comp(""), str8_lit_comp("Specifies that all integral evaluations should appear in base-16 form."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("only"), str8_lit_comp("Only Specified Members"), str8_lit_comp("x:{member}"), str8_lit_comp("Specifies that only the specified members should appear in struct, union, or class evaluations."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("omit"), str8_lit_comp("Omit Specified Members"), str8_lit_comp("x:{member}"), str8_lit_comp("Omits a list of member names from appearing in struct, union, or class evaluations."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("no_addr"), str8_lit_comp("Disable Address Values"), str8_lit_comp(""), str8_lit_comp("Displays only what pointers point to, if possible, without the pointer's address value."), (D_ViewRuleSpecInfoFlag_Inherited*1)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("checkbox"), str8_lit_comp("Checkbox"), str8_lit_comp(""), str8_lit_comp("Displays simple integer values as checkboxes, encoding zero or nonzero values."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*0)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*0), },
{str8_lit_comp("color_rgba"), str8_lit_comp("Color (RGBA)"), str8_lit_comp(""), str8_lit_comp("Displays as a color, interpreting the data as encoding R, G, B, and A values."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*1)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("text"), str8_lit_comp("Text"), str8_lit_comp("x:{'lang':lang, 'size':expr}"), str8_lit_comp("Displays as text."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*1)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("disasm"), str8_lit_comp("Disassembly"), str8_lit_comp("x:{'arch':arch, 'size':expr}"), str8_lit_comp("Displays as disassembled instructions, interpreting the data as raw machine code."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*1)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("memory"), str8_lit_comp("Memory"), str8_lit_comp("x:{'size':expr}"), str8_lit_comp("Displays as a raw memory grid."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*1)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("graph"), str8_lit_comp("Graph"), str8_lit_comp(""), str8_lit_comp("Displays as a pointer graph, visualizing nodes and edges formed by pointers directly."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*1)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("bitmap"), str8_lit_comp("Bitmap"), str8_lit_comp("x:{'w':expr, 'h':expr, 'fmt':tex2dformat}"), str8_lit_comp("Displays as a bitmap, interpreting the data as raw pixel data."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*1)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
{str8_lit_comp("geo3d"), str8_lit_comp("Geometry (3D)"), str8_lit_comp("x:{'count':expr, 'vtx':expr, 'vtx_size':expr}"), str8_lit_comp("Displays as geometry, interpreting the data as index or vertex data."), (D_ViewRuleSpecInfoFlag_Inherited*0)|(D_ViewRuleSpecInfoFlag_Expandable*1)|(D_ViewRuleSpecInfoFlag_ExprResolution*0)|(D_ViewRuleSpecInfoFlag_VizBlockProd*1), },
};
C_LINKAGE_END
+1 -30
View File
@@ -10,7 +10,7 @@ typedef enum D_CmdKind
{
D_CmdKind_Null,
D_CmdKind_LaunchAndRun,
D_CmdKind_LaunchAndInit,
D_CmdKind_LaunchAndStepInto,
D_CmdKind_Kill,
D_CmdKind_KillAll,
D_CmdKind_Detach,
@@ -24,7 +24,6 @@ D_CmdKind_Halt,
D_CmdKind_SoftHaltRefresh,
D_CmdKind_SetThreadIP,
D_CmdKind_RunToLine,
D_CmdKind_RunToAddress,
D_CmdKind_Run,
D_CmdKind_Restart,
D_CmdKind_StepInto,
@@ -45,32 +44,6 @@ D_CmdKind_Attach,
D_CmdKind_COUNT,
} D_CmdKind;
typedef enum D_ViewRuleKind
{
D_ViewRuleKind_Default,
D_ViewRuleKind_Array,
D_ViewRuleKind_Slice,
D_ViewRuleKind_List,
D_ViewRuleKind_ByteSwap,
D_ViewRuleKind_Cast,
D_ViewRuleKind_BaseDec,
D_ViewRuleKind_BaseBin,
D_ViewRuleKind_BaseOct,
D_ViewRuleKind_BaseHex,
D_ViewRuleKind_Only,
D_ViewRuleKind_Omit,
D_ViewRuleKind_NoAddr,
D_ViewRuleKind_Checkbox,
D_ViewRuleKind_ColorRGBA,
D_ViewRuleKind_Text,
D_ViewRuleKind_Disasm,
D_ViewRuleKind_Memory,
D_ViewRuleKind_Graph,
D_ViewRuleKind_Bitmap,
D_ViewRuleKind_Geo3D,
D_ViewRuleKind_COUNT,
} D_ViewRuleKind;
global B32 DEV_simulate_lag = 0;
global B32 DEV_draw_ui_text_pos = 0;
global B32 DEV_draw_ui_focus_debug = 0;
@@ -78,7 +51,6 @@ global B32 DEV_draw_ui_box_heatmap = 0;
global B32 DEV_eval_compiler_tooltips = 0;
global B32 DEV_eval_watch_key_tooltips = 0;
global B32 DEV_cmd_context_tooltips = 0;
global B32 DEV_scratch_mouse_draw = 0;
global B32 DEV_updating_indicator = 0;
struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] =
{
@@ -89,7 +61,6 @@ struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] =
{&DEV_eval_compiler_tooltips, str8_lit_comp("eval_compiler_tooltips")},
{&DEV_eval_watch_key_tooltips, str8_lit_comp("eval_watch_key_tooltips")},
{&DEV_cmd_context_tooltips, str8_lit_comp("cmd_context_tooltips")},
{&DEV_scratch_mouse_draw, str8_lit_comp("scratch_mouse_draw")},
{&DEV_updating_indicator, str8_lit_comp("updating_indicator")},
};
#endif // DBG_ENGINE_META_H
+39 -26
View File
@@ -1,6 +1,9 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#undef LAYER_COLOR
#define LAYER_COLOR 0x7c4ce3ff
////////////////////////////////
//~ rjf: Basic Helpers
@@ -262,22 +265,26 @@ di_scope_open(void)
scope = push_array_no_zero(di_tctx->arena, DI_Scope, 1);
}
MemoryZeroStruct(scope);
DLLPushBack(di_tctx->first_scope, di_tctx->last_scope, scope);
return scope;
}
internal void
di_scope_close(DI_Scope *scope)
{
DLLRemove(di_tctx->first_scope, di_tctx->last_scope, scope);
for(DI_Touch *t = scope->first_touch, *next = 0; t != 0; t = next)
{
next = t->next;
if(t->node != 0)
{
ins_atomic_u64_dec_eval(&t->node->touch_count);
os_condition_variable_broadcast(t->stripe->cv);
}
if(t->search_node != 0)
{
ins_atomic_u64_dec_eval(&t->search_node->scope_refcount);
os_condition_variable_broadcast(t->search_stripe->cv);
}
SLLStackPush(di_tctx->free_touch, t);
}
@@ -285,7 +292,7 @@ di_scope_close(DI_Scope *scope)
}
internal void
di_scope_touch_node__stripe_mutex_r_guarded(DI_Scope *scope, DI_Node *node)
di_scope_touch_node__stripe_mutex_r_guarded(DI_Scope *scope, DI_Stripe *stripe, DI_Node *node)
{
if(node != 0)
{
@@ -303,10 +310,11 @@ di_scope_touch_node__stripe_mutex_r_guarded(DI_Scope *scope, DI_Node *node)
MemoryZeroStruct(touch);
SLLQueuePush(scope->first_touch, scope->last_touch, touch);
touch->node = node;
touch->stripe = stripe;
}
internal void
di_scope_touch_search_node__stripe_mutex_r_guarded(DI_Scope *scope, DI_SearchNode *node)
di_scope_touch_search_node__stripe_mutex_r_guarded(DI_Scope *scope, DI_SearchStripe *stripe, DI_SearchNode *node)
{
if(node != 0)
{
@@ -324,6 +332,7 @@ di_scope_touch_search_node__stripe_mutex_r_guarded(DI_Scope *scope, DI_SearchNod
MemoryZeroStruct(touch);
SLLQueuePush(scope->first_touch, scope->last_touch, touch);
touch->search_node = node;
touch->search_stripe = stripe;
}
////////////////////////////////
@@ -522,6 +531,7 @@ di_close(DI_Key *key)
DI_Slot *slot = &di_shared->slots[slot_idx];
DI_Stripe *stripe = &di_shared->stripes[stripe_idx];
log_infof("close_debug_info: {\"%S\", 0x%I64x}\n", key_normalized.path, key_normalized.min_timestamp);
B32 closed = 0;
OS_MutexScopeW(stripe->rw_mutex)
{
//- rjf: find existing node
@@ -533,16 +543,8 @@ di_close(DI_Key *key)
node->ref_count -= 1;
if(node->ref_count == 0) for(;;)
{
//- rjf: wait for touch count to go to 0
if(ins_atomic_u64_eval(&node->touch_count) != 0)
{
os_rw_mutex_drop_w(stripe->rw_mutex);
for(U64 start_t = os_now_microseconds(); os_now_microseconds() <= start_t + 250;);
os_rw_mutex_take_w(stripe->rw_mutex);
}
//- rjf: release
if(node->ref_count == 0 && ins_atomic_u64_eval(&node->touch_count) == 0)
if(ins_atomic_u64_eval(&node->touch_count) == 0)
{
di_string_release__stripe_mutex_w_guarded(stripe, node->key.path);
if(node->file_base != 0)
@@ -565,6 +567,9 @@ di_close(DI_Key *key)
SLLStackPush(stripe->free_node, node);
break;
}
//- rjf: wait for touch count to go to 0
os_condition_variable_wait_rw_w(stripe->cv, stripe->rw_mutex, max_U64);
}
}
}
@@ -580,7 +585,7 @@ internal RDI_Parsed *
di_rdi_from_key(DI_Scope *scope, DI_Key *key, U64 endt_us)
{
ProfBeginFunction();
RDI_Parsed *result = &di_rdi_parsed_nil;
RDI_Parsed *result = &rdi_parsed_nil;
if(key->path.size != 0)
{
Temp scratch = scratch_begin(0, 0);
@@ -610,7 +615,7 @@ di_rdi_from_key(DI_Scope *scope, DI_Key *key, U64 endt_us)
//- rjf: parse done -> touch, grab result
if(node != 0 && node->parse_done)
{
di_scope_touch_node__stripe_mutex_r_guarded(scope, node);
di_scope_touch_node__stripe_mutex_r_guarded(scope, stripe, node);
result = &node->rdi;
break;
}
@@ -702,12 +707,11 @@ di_search_items_from_key_params_query(DI_Scope *scope, U128 key, DI_SearchParams
B32 params_stale = 1;
B32 query_stale = 1;
B32 results_stale = 1;
if(params_hash == node->buckets[node->bucket_read_gen%ArrayCount(node->buckets)].params_hash &&
node->bucket_read_gen != 0)
if(node->bucket_read_gen != 0)
{
di_scope_touch_search_node__stripe_mutex_r_guarded(scope, node);
di_scope_touch_search_node__stripe_mutex_r_guarded(scope, stripe, node);
items = node->items;
params_stale = 0;
params_stale = (params_hash != node->buckets[node->bucket_read_gen%ArrayCount(node->buckets)].params_hash);
query_stale = !str8_match(query, node->buckets[node->bucket_read_gen%ArrayCount(node->buckets)].query, 0);
results_stale = (node->bucket_read_gen < node->bucket_write_gen);
}
@@ -716,8 +720,8 @@ di_search_items_from_key_params_query(DI_Scope *scope, U128 key, DI_SearchParams
*stale_out = (params_stale || query_stale || results_stale);
}
// rjf: if query stale -> request again
if(query_stale && node->bucket_read_gen <= node->bucket_write_gen && node->bucket_write_gen < node->bucket_read_gen + ArrayCount(node->buckets)-1)
// rjf: if query or params stale -> request again
if((query_stale || params_stale) && node->bucket_read_gen <= node->bucket_write_gen && node->bucket_write_gen < node->bucket_read_gen + ArrayCount(node->buckets)-1)
{
node->bucket_write_gen += 1;
if(node->bucket_write_gen >= node->bucket_items_gen + ArrayCount(node->buckets))
@@ -1084,7 +1088,7 @@ ASYNC_WORK_DEF(di_parse_work)
////////////////////////////
//- rjf: do initial parse of rdi
//
RDI_Parsed rdi_parsed_maybe_compressed = di_rdi_parsed_nil;
RDI_Parsed rdi_parsed_maybe_compressed = rdi_parsed_nil;
{
RDI_ParseStatus parse_status = rdi_parse((U8 *)file_base, file_props.size, &rdi_parsed_maybe_compressed);
(void)parse_status;
@@ -1349,7 +1353,6 @@ di_search_thread__entry_point(void *p)
for(;;)
{
Temp scratch = scratch_begin(0, 0);
DI_Scope *di_scope = di_scope_open();
//- rjf: get next key, unpack
U128 key = di_u2s_dequeue_req(thread_idx);
@@ -1380,6 +1383,9 @@ di_search_thread__entry_point(void *p)
}
}
//- rjf: begin debug info scope
DI_Scope *di_scope = di_scope_open();
//- rjf: get all rdis
U64 rdis_count = params.dbgi_keys.count;
RDI_Parsed **rdis = push_array(scratch.arena, RDI_Parsed *, rdis_count);
@@ -1428,6 +1434,9 @@ di_search_thread__entry_point(void *p)
cancelled = (cancelled || out->cancelled);
}
//- rjf: end debug info scope
di_scope_close(di_scope);
//- rjf: list -> array
DI_SearchItemArray items = {0};
if(arena != 0 && !cancelled)
@@ -1464,13 +1473,14 @@ di_search_thread__entry_point(void *p)
quick_sort(items.v, items.count, sizeof(DI_SearchItem), di_qsort_compare_search_items);
}
//- rjf: commit to cache - busyloop on scope touches
//- rjf: commit to cache - wait on scope touches
if(arena != 0)
{
for(B32 done = 0; !done;)
OS_MutexScopeW(stripe->rw_mutex) for(;;)
{
B32 found = 0;
OS_MutexScopeW(stripe->rw_mutex) for(DI_SearchNode *n = slot->first; n != 0; n = n->next)
B32 done = 0;
for(DI_SearchNode *n = slot->first; n != 0; n = n->next)
{
if(u128_match(n->key, key))
{
@@ -1489,14 +1499,17 @@ di_search_thread__entry_point(void *p)
break;
}
}
if(!found)
if((found && done) || !found)
{
break;
}
if(found && !done)
{
os_condition_variable_wait_rw_w(stripe->cv, stripe->rw_mutex, os_now_microseconds()+1000);
}
}
}
di_scope_close(di_scope);
scratch_end(scratch);
}
}
+7 -3
View File
@@ -218,13 +218,16 @@ struct DI_Touch
{
DI_Touch *next;
DI_Node *node;
DI_Stripe *stripe;
DI_SearchNode *search_node;
DI_SearchStripe *search_stripe;
};
typedef struct DI_Scope DI_Scope;
struct DI_Scope
{
DI_Scope *next;
DI_Scope *prev;
DI_Touch *first_touch;
DI_Touch *last_touch;
};
@@ -233,6 +236,8 @@ typedef struct DI_TCTX DI_TCTX;
struct DI_TCTX
{
Arena *arena;
DI_Scope *first_scope;
DI_Scope *last_scope;
DI_Scope *free_scope;
DI_Touch *free_touch;
};
@@ -376,7 +381,6 @@ struct DI_Shared
global DI_Shared *di_shared = 0;
thread_static DI_TCTX *di_tctx = 0;
global RDI_Parsed di_rdi_parsed_nil = {0};
////////////////////////////////
//~ rjf: Basic Helpers
@@ -407,8 +411,8 @@ internal void di_init(void);
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);
internal void di_scope_touch_search_node__stripe_mutex_r_guarded(DI_Scope *scope, DI_SearchNode *node);
internal void di_scope_touch_node__stripe_mutex_r_guarded(DI_Scope *scope, DI_Stripe *stripe, DI_Node *node);
internal void di_scope_touch_search_node__stripe_mutex_r_guarded(DI_Scope *scope, DI_SearchStripe *stripe, DI_SearchNode *node);
////////////////////////////////
//~ rjf: Per-Slot Functions
+11 -1
View File
@@ -73,7 +73,7 @@ struct DMN_Event
U64 size;
String8 string;
U32 code; // code gives pid & tid on CreateProcess and CreateThread (respectfully)
U32 flags;
U32 flags; // DMN_TrapFlags, if `DMN_EventKind_SetBreakpoint`
S32 signo;
S32 sigcode;
U64 instruction_pointer;
@@ -100,12 +100,22 @@ struct DMN_EventList
////////////////////////////////
//~ rjf: Run Control Types
typedef U32 DMN_TrapFlags;
enum
{
DMN_TrapFlag_BreakOnWrite = (1<<0),
DMN_TrapFlag_BreakOnRead = (1<<1),
DMN_TrapFlag_BreakOnExecute = (1<<2),
};
typedef struct DMN_Trap DMN_Trap;
struct DMN_Trap
{
DMN_Handle process;
U64 vaddr;
U64 id;
DMN_TrapFlags flags;
U32 size;
};
typedef struct DMN_TrapChunkNode DMN_TrapChunkNode;
+3
View File
@@ -21,6 +21,9 @@ DMN_EventKindTable:
{Memory}
{DebugString}
{SetThreadName}
{SetThreadColor}
{SetBreakpoint}
{UnsetBreakpoint}
}
@table(name)
+4 -1
View File
@@ -4,7 +4,7 @@
//- GENERATED CODE
C_LINKAGE_BEGIN
String8 dmn_event_kind_string_table[17] =
String8 dmn_event_kind_string_table[20] =
{
str8_lit_comp("Null"),
str8_lit_comp("Error"),
@@ -23,6 +23,9 @@ str8_lit_comp("Halt"),
str8_lit_comp("Memory"),
str8_lit_comp("DebugString"),
str8_lit_comp("SetThreadName"),
str8_lit_comp("SetThreadColor"),
str8_lit_comp("SetBreakpoint"),
str8_lit_comp("UnsetBreakpoint"),
};
String8 dmn_exception_kind_string_table[5] =
+4 -1
View File
@@ -25,6 +25,9 @@ DMN_EventKind_Halt,
DMN_EventKind_Memory,
DMN_EventKind_DebugString,
DMN_EventKind_SetThreadName,
DMN_EventKind_SetThreadColor,
DMN_EventKind_SetBreakpoint,
DMN_EventKind_UnsetBreakpoint,
DMN_EventKind_COUNT,
} DMN_EventKind;
@@ -58,7 +61,7 @@ DMN_ExceptionKind_COUNT,
} DMN_ExceptionKind;
C_LINKAGE_BEGIN
extern String8 dmn_event_kind_string_table[17];
extern String8 dmn_event_kind_string_table[20];
extern String8 dmn_exception_kind_string_table[5];
C_LINKAGE_END
+21
View File
@@ -15,6 +15,8 @@ dmn_init(void)
internal DMN_CtrlCtx *
dmn_ctrl_begin(void)
{
DMN_CtrlCtx *ctx = (DMN_CtrlCtx *)1;
return ctx;
}
internal void
@@ -30,26 +32,32 @@ dmn_ctrl_exclusive_access_end(void)
internal U32
dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params)
{
return 0;
}
internal B32
dmn_ctrl_attach(DMN_CtrlCtx *ctx, U32 pid)
{
return 0;
}
internal B32
dmn_ctrl_kill(DMN_CtrlCtx *ctx, DMN_Handle process, U32 exit_code)
{
return 0;
}
internal B32
dmn_ctrl_detach(DMN_CtrlCtx *ctx, DMN_Handle process)
{
return 0;
}
internal DMN_EventList
dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
{
DMN_EventList evts = {0};
return evts;
}
////////////////////////////////
@@ -68,16 +76,19 @@ dmn_halt(U64 code, U64 user_data)
internal U64
dmn_run_gen(void)
{
return 0;
}
internal U64
dmn_mem_gen(void)
{
return 0;
}
internal U64
dmn_reg_gen(void)
{
return 0;
}
//- rjf: non-blocking-control-thread access barriers
@@ -85,6 +96,7 @@ dmn_reg_gen(void)
internal B32
dmn_access_open(void)
{
return 0;
}
internal void
@@ -97,6 +109,7 @@ dmn_access_close(void)
internal U64
dmn_process_memory_reserve(DMN_Handle process, U64 vaddr, U64 size)
{
return 0;
}
internal void
@@ -122,11 +135,13 @@ dmn_process_memory_protect(DMN_Handle process, U64 vaddr, U64 size, OS_AccessFla
internal U64
dmn_process_read(DMN_Handle process, Rng1U64 range, void *dst)
{
return 0;
}
internal B32
dmn_process_write(DMN_Handle process, Rng1U64 range, void *src)
{
return 0;
}
//- rjf: threads
@@ -134,26 +149,31 @@ dmn_process_write(DMN_Handle process, Rng1U64 range, void *src)
internal Arch
dmn_arch_from_thread(DMN_Handle handle)
{
return Arch_Null;
}
internal U64
dmn_stack_base_vaddr_from_thread(DMN_Handle handle)
{
return 0;
}
internal U64
dmn_tls_root_vaddr_from_thread(DMN_Handle handle)
{
return 0;
}
internal B32
dmn_thread_read_reg_block(DMN_Handle handle, void *reg_block)
{
return 0;
}
internal B32
dmn_thread_write_reg_block(DMN_Handle handle, void *reg_block)
{
return 0;
}
//- rjf: system process listing
@@ -166,6 +186,7 @@ dmn_process_iter_begin(DMN_ProcessIter *iter)
internal B32
dmn_process_iter_next(Arena *arena, DMN_ProcessIter *iter, DMN_ProcessInfo *info_out)
{
return 0;
}
internal void
+340 -41
View File
@@ -56,16 +56,17 @@ dmn_w32_entity_alloc(DMN_W32_Entity *parent, DMN_W32_EntityKind kind, U64 id)
// rjf: allocate
DMN_W32_Entity *e = dmn_w32_shared->entities_first_free;
{
U32 gen = 0;
if(e != 0)
{
SLLStackPop(dmn_w32_shared->entities_first_free);
gen = e->gen;
}
else
{
e = push_array_no_zero(dmn_w32_shared->entities_arena, DMN_W32_Entity, 1);
dmn_w32_shared->entities_count += 1;
}
U32 gen = e->gen;
MemoryZeroStruct(e);
e->gen = gen+1;
}
@@ -155,6 +156,7 @@ dmn_w32_entity_release(DMN_W32_Entity *entity)
{
CloseHandle(t->e->handle);
}
t->e->kind = DMN_W32_EntityKind_Null;
// rjf: remove from id -> entity map
if(t->e->id != 0)
@@ -469,9 +471,9 @@ dmn_w32_image_info_from_process_base_vaddr(HANDLE process, U64 base_vaddr)
}
// rjf: get COFF header
B32 got_file_header = 0;
U64 file_header_off = 0;
COFF_FileHeader file_header = {0};
B32 got_coff_header = 0;
U64 coff_header_off = 0;
COFF_FileHeader coff_header = {0};
if(pe_offset > 0)
{
U64 pe_magic_off = base_vaddr + pe_offset;
@@ -479,28 +481,28 @@ dmn_w32_image_info_from_process_base_vaddr(HANDLE process, U64 base_vaddr)
dmn_w32_process_read_struct(process, pe_magic_off, &pe_magic);
if(pe_magic == PE_MAGIC)
{
file_header_off = pe_magic_off + sizeof(pe_magic);
if(dmn_w32_process_read_struct(process, file_header_off, &file_header))
coff_header_off = pe_magic_off + sizeof(pe_magic);
if(dmn_w32_process_read_struct(process, coff_header_off, &coff_header))
{
got_file_header = 1;
got_coff_header = 1;
}
}
}
// rjf: get arch and size
DMN_W32_ImageInfo result = zero_struct;
if(got_file_header)
if(got_coff_header)
{
U64 optional_size_off = 0;
Arch arch = Arch_Null;
switch(file_header.machine)
switch(coff_header.machine)
{
case COFF_Machine_X86:
case COFF_MachineType_X86:
{
arch = Arch_x86;
optional_size_off = OffsetOf(PE_OptionalHeader32, sizeof_image);
}break;
case COFF_Machine_X64:
case COFF_MachineType_X64:
{
arch = Arch_x64;
optional_size_off = OffsetOf(PE_OptionalHeader32Plus, sizeof_image);
@@ -510,7 +512,7 @@ dmn_w32_image_info_from_process_base_vaddr(HANDLE process, U64 base_vaddr)
}
if(arch != Arch_Null)
{
U64 optional_off = file_header_off + sizeof(COFF_FileHeader);
U64 optional_off = coff_header_off + sizeof(coff_header);
U32 size = 0;
if(dmn_w32_process_read_struct(process, optional_off+optional_size_off, &size) >= sizeof(size))
{
@@ -749,12 +751,12 @@ dmn_w32_thread_read_reg_block(Arch arch, HANDLE thread, void *reg_block)
dst->fs.u16 = ctx->SegFs;
dst->gs.u16 = ctx->SegGs;
dst->ss.u16 = ctx->SegSs;
dst->dr0.u32 = ctx->Dr0;
dst->dr1.u32 = ctx->Dr1;
dst->dr2.u32 = ctx->Dr2;
dst->dr3.u32 = ctx->Dr3;
dst->dr6.u32 = ctx->Dr6;
dst->dr7.u32 = ctx->Dr7;
dst->dr0.u64 = ctx->Dr0;
dst->dr1.u64 = ctx->Dr1;
dst->dr2.u64 = ctx->Dr2;
dst->dr3.u64 = ctx->Dr3;
dst->dr6.u64 = ctx->Dr6;
dst->dr7.u64 = ctx->Dr7;
// NOTE(rjf): this bit is "supposed to always be 1", according to old info.
// may need to be investigated.
dst->rflags.u64 = ctx->EFlags | 0x2;
@@ -1020,12 +1022,12 @@ dmn_w32_thread_write_reg_block(Arch arch, HANDLE thread, void *reg_block)
ctx->SegFs = src->fs.u16;
ctx->SegGs = src->gs.u16;
ctx->SegSs = src->ss.u16;
ctx->Dr0 = src->dr0.u32;
ctx->Dr1 = src->dr1.u32;
ctx->Dr2 = src->dr2.u32;
ctx->Dr3 = src->dr3.u32;
ctx->Dr6 = src->dr6.u32;
ctx->Dr7 = src->dr7.u32;
ctx->Dr0 = src->dr0.u64;
ctx->Dr1 = src->dr1.u64;
ctx->Dr2 = src->dr2.u64;
ctx->Dr3 = src->dr3.u64;
ctx->Dr6 = src->dr6.u64;
ctx->Dr7 = src->dr7.u64;
ctx->EFlags = src->rflags.u64;
fxsave->ControlWord = src->fcw.u16;
fxsave->StatusWord = src->fsw.u16;
@@ -1291,7 +1293,6 @@ dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params)
inherit_handles = 1;
}
PROCESS_INFORMATION process_info = {0};
AllocConsole();
if(CreateProcessW(0, (WCHAR*)cmd16.str, 0, 0, 1, creation_flags, (WCHAR*)env16.str, (WCHAR*)dir16.str, &startup_info, &process_info))
{
// check if we are 32-bit app, and just close it immediately
@@ -1313,15 +1314,13 @@ dmn_ctrl_launch(DMN_CtrlCtx *ctx, OS_ProcessLaunchParams *params)
}
else
{
MessageBox(0, "Error starting process.", "Process error", MB_OK|MB_ICONSTOP);
}
FreeConsole();
//- rjf: eliminate all handles which have stuck around from the AllocConsole
{
SetStdHandle(STD_INPUT_HANDLE, 0);
SetStdHandle(STD_OUTPUT_HANDLE, 0);
SetStdHandle(STD_ERROR_HANDLE, 0);
DWORD error = GetLastError();
LPWSTR message = 0;
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL), (LPWSTR)&message, 0, 0);
String8 message8 = message ? str8_from_16(scratch.arena, str16_cstring(message)) : str8_lit("unknown error");
LocalFree(message);
log_user_errorf("There was an error starting %S: %S", params->cmd_line.first->string, message8);
}
}
scratch_end(scratch);
@@ -1560,10 +1559,161 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
for(U64 n_idx = 0; n_idx < n->count; n_idx += 1, trap_idx += 1)
{
DMN_Trap *trap = n->v+n_idx;
trap_swap_bytes[trap_idx] = 0xCC;
dmn_process_read(trap->process, r1u64(trap->vaddr, trap->vaddr+1), trap_swap_bytes+trap_idx);
U8 int3 = 0xCC;
dmn_process_write(trap->process, r1u64(trap->vaddr, trap->vaddr+1), &int3);
if(trap->flags == 0)
{
trap_swap_bytes[trap_idx] = 0xCC;
dmn_process_read(trap->process, r1u64(trap->vaddr, trap->vaddr+1), trap_swap_bytes+trap_idx);
U8 int3 = 0xCC;
dmn_process_write(trap->process, r1u64(trap->vaddr, trap->vaddr+1), &int3);
}
}
}
}
//////////////////////////
//- rjf: gather all flagged traps, bucketed by process
//
typedef struct DMN_FlaggedTrapTask DMN_FlaggedTrapTask;
struct DMN_FlaggedTrapTask
{
DMN_FlaggedTrapTask *next;
DMN_Handle process;
DMN_TrapChunkList traps;
};
DMN_FlaggedTrapTask *first_flagged_trap_task = 0;
DMN_FlaggedTrapTask *last_flagged_trap_task= 0;
for(DMN_TrapChunkNode *n = ctrls->traps.first; n != 0; n = n->next)
{
for(U64 n_idx = 0; n_idx < n->count; n_idx += 1)
{
DMN_Trap *trap = n->v+n_idx;
if(trap->flags != 0)
{
DMN_FlaggedTrapTask *task = 0;
for(DMN_FlaggedTrapTask *t = first_flagged_trap_task; t != 0; t = t->next)
{
if(dmn_handle_match(t->process, trap->process))
{
task = t;
break;
}
}
if(task == 0)
{
task = push_array(scratch.arena, DMN_FlaggedTrapTask, 1);
SLLQueuePush(first_flagged_trap_task, last_flagged_trap_task, task);
task->process = trap->process;
}
B32 already_in_task = 0;
for(DMN_TrapChunkNode *n = task->traps.first; n != 0; n = n->next)
{
for(U64 n_idx = 0; n_idx < n->count; n_idx += 1)
{
if(n->v[n_idx].id == trap->id)
{
already_in_task = 1;
goto end_look_for_existing_trap_in_task;
}
}
}
end_look_for_existing_trap_in_task:;
if(!already_in_task)
{
dmn_trap_chunk_list_push(scratch.arena, &task->traps, 8, trap);
}
}
}
}
//////////////////////////
//- rjf: write all debug register states, for flagged-traps
//
ProfScope("write all debug register states, for flagged-traps")
{
//- rjf: for each flagged trap task, iterate all threads in the
// associated process, and prepare debug registers accordingly
for(DMN_FlaggedTrapTask *t = first_flagged_trap_task; t != 0; t = t->next)
{
DMN_Handle process = t->process;
DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process);
for(DMN_W32_Entity *child = process_entity->first;
child != &dmn_w32_entity_nil;
child = child->next)
{
if(child->kind == DMN_W32_EntityKind_Thread)
{
switch(child->arch)
{
default:{}break;
//- rjf: x64
case Arch_x64:
{
REGS_RegBlockX64 regs = {0};
dmn_w32_thread_read_reg_block(child->arch, child->handle, &regs);
{
U64 trap_idx = 0;
for(DMN_TrapChunkNode *n = t->traps.first; n != 0; n = n->next)
{
for(U64 n_idx = 0; n_idx < n->count && trap_idx < 4; n_idx += 1, trap_idx += 1)
{
DMN_Trap *trap = &n->v[n_idx];
REGS_Reg64 *addr_reg = &regs.dr0;
switch(trap_idx)
{
default:{}break;
case 0:{addr_reg = &regs.dr0;}break;
case 1:{addr_reg = &regs.dr1;}break;
case 2:{addr_reg = &regs.dr2;}break;
case 3:{addr_reg = &regs.dr3;}break;
}
addr_reg->u64 = trap->vaddr;
regs.dr7.u64 |= bit9|bit10|bit11;
regs.dr7.u64 |= (1ull << (trap_idx*2));
// NOTE(rjf): global-enable regs.dr7.u64 |= (1ull << (trap_idx*2+1));
regs.dr7.u64 &= ~((U64)(bit17|bit18|bit19|bit20) << (trap_idx*4));
regs.dr7.u64 &= ~((U64)(bit15|bit16));
switch(trap->flags)
{
case DMN_TrapFlag_BreakOnExecute:
default:{}break;
case DMN_TrapFlag_BreakOnWrite:
case DMN_TrapFlag_BreakOnWrite|DMN_TrapFlag_BreakOnExecute:
{
regs.dr7.u64 |= ((U64)bit17) << (trap_idx*4);
}break;
case DMN_TrapFlag_BreakOnRead|DMN_TrapFlag_BreakOnWrite|DMN_TrapFlag_BreakOnExecute:
case DMN_TrapFlag_BreakOnRead|DMN_TrapFlag_BreakOnWrite:
{
regs.dr7.u64 |= (((U64)bit17) << (trap_idx*4));
regs.dr7.u64 |= (((U64)bit18) << (trap_idx*4));
}break;
}
switch(trap->size)
{
case 1:
default:{}break;
case 2:
{
regs.dr7.u64 |= (((U64)bit19) << (trap_idx*4));
}break;
case 4:
{
regs.dr7.u64 |= (((U64)bit19) << (trap_idx*4));
regs.dr7.u64 |= (((U64)bit20) << (trap_idx*4));
}break;
case 8:
{
regs.dr7.u64 |= (((U64)bit20) << (trap_idx*4));
}break;
}
}
}
}
dmn_w32_thread_write_reg_block(child->arch, child->handle, &regs);
}break;
}
}
}
}
}
@@ -1721,6 +1871,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
{
dmn_w32_shared->resume_needed = 0;
resume_good = !!ContinueDebugEvent(dmn_w32_shared->resume_pid, dmn_w32_shared->resume_tid, resume_code);
DWORD error = GetLastError();
dmn_w32_shared->resume_needed = 0;
dmn_w32_shared->resume_tid = 0;
dmn_w32_shared->resume_pid = 0;
@@ -1736,6 +1887,8 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
}
else
{
DWORD err = GetLastError();
(void)err;
keep_going = 1;
}
ins_atomic_u64_inc_eval(&dmn_w32_shared->run_gen);
@@ -1843,6 +1996,15 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
{
DMN_W32_Entity *process = dmn_w32_entity_from_kind_id(DMN_W32_EntityKind_Process, evt.dwProcessId);
// rjf: if this was the process we were going to resume, then we will
// just not resume, and wait for another debug event
if(evt.dwProcessId == dmn_w32_shared->resume_pid)
{
dmn_w32_shared->resume_needed = 0;
dmn_w32_shared->resume_tid = 0;
dmn_w32_shared->resume_pid = 0;
}
// rjf: generate events for children
for(DMN_W32_Entity *child = process->first; child != &dmn_w32_entity_nil; child = child->next)
{
@@ -1948,6 +2110,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
e->kind = DMN_EventKind_Halt;
dmn_w32_shared->halter_process = dmn_handle_zero();
dmn_w32_shared->halter_tid = 0;
keep_going = 0;
}
// rjf: if this thread is *not* the halter, then generate a regular exit-thread event
@@ -2089,6 +2252,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
//- rjf: check if this trap is a usage-code-specified trap or something else
B32 hit_user_trap = 0;
U64 user_trap_id = 0;
if(is_trap)
{
for(DMN_TrapChunkNode *n = ctrls->traps.first; n != 0; n = n->next)
@@ -2098,6 +2262,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
if(dmn_handle_match(n->v[idx].process, dmn_w32_handle_from_entity(process)) && n->v[idx].vaddr == instruction_pointer)
{
hit_user_trap = 1;
user_trap_id = n->v[idx].id;
break;
}
}
@@ -2186,6 +2351,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
e->code = exception->ExceptionCode;
e->flags = exception->ExceptionFlags;
e->instruction_pointer = (U64)exception->ExceptionAddress;
e->user_data = user_trap_id;
//- rjf: fill according to exception code
switch(exception->ExceptionCode)
@@ -2215,6 +2381,72 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
case DMN_W32_EXCEPTION_SINGLE_STEP:
{
e->kind = DMN_EventKind_SingleStep;
// NOTE(rjf): data breakpoints are reported via single-steps
// over the instructions which caused the breakpoint to be
// hit - so if we have data breakpoints set, we need to
// check this thread's debug registers, to determine if this
// is a regular single-step or a data breakpoint hit.
if(first_flagged_trap_task != 0)
{
// rjf: first determine the flagged trap index
U64 flagged_trap_idx = 0;
switch(thread->arch)
{
default:{NotImplemented;}break;
case Arch_x64:
{
REGS_RegBlockX64 regs = {0};
dmn_w32_thread_read_reg_block(thread->arch, thread->handle, &regs);
if(regs.dr6.u64 & 0xF)
{
e->kind = DMN_EventKind_Breakpoint;
if(0){}
else if(regs.dr7.u64 & (1ull<<0) && regs.dr6.u64 & (1ull<<0)) { flagged_trap_idx = 0; }
else if(regs.dr7.u64 & (1ull<<2) && regs.dr6.u64 & (1ull<<1)) { flagged_trap_idx = 1; }
else if(regs.dr7.u64 & (1ull<<4) && regs.dr6.u64 & (1ull<<2)) { flagged_trap_idx = 2; }
else if(regs.dr7.u64 & (1ull<<8) && regs.dr6.u64 & (1ull<<3)) { flagged_trap_idx = 3; }
}
}break;
}
// rjf: find the flagged trap task for this thread's process
DMN_W32_Entity *process = thread->parent;
DMN_FlaggedTrapTask *task = 0;
for(DMN_FlaggedTrapTask *t = first_flagged_trap_task; t != 0; t = t->next)
{
if(dmn_handle_match(t->process, dmn_w32_handle_from_entity(process)))
{
task = t;
break;
}
}
// rjf: find the trap
DMN_Trap *trap = 0;
if(task != 0)
{
U64 trap_idx = 0;
for(DMN_TrapChunkNode *n = task->traps.first; n != 0; n = n->next)
{
for(U64 n_idx = 0; n_idx < n->count; n_idx += 1, trap_idx += 1)
{
if(trap_idx == flagged_trap_idx)
{
trap = &n->v[n_idx];
goto break_search_for_flagged_trap;
}
}
}
break_search_for_flagged_trap:;
}
// rjf: fill event based on trap
if(trap != 0)
{
e->user_data = trap->id;
}
}
}break;
//- rjf: fill throw info
@@ -2303,6 +2535,31 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
}
}break;
//- rjf: fill set-thread-color info
case DMN_W32_EXCEPTION_RADDBG_SET_THREAD_COLOR:
{
e->kind = DMN_EventKind_SetThreadColor;
e->code = exception->ExceptionInformation[0];
e->user_data = exception->ExceptionInformation[1];
}break;
//- rjf: fill set-data-breakpoint info
case DMN_W32_EXCEPTION_RADDBG_SET_BREAKPOINT:
{
U64 vaddr = exception->ExceptionInformation[0];
U64 size = exception->ExceptionInformation[1];
U64 read = exception->ExceptionInformation[2];
U64 write = exception->ExceptionInformation[3];
U64 exec = exception->ExceptionInformation[4];
U64 set = exception->ExceptionInformation[5];
e->kind = set ? DMN_EventKind_SetBreakpoint : DMN_EventKind_UnsetBreakpoint;
e->address = vaddr;
e->size = size;
if(read) { e->flags |= DMN_TrapFlag_BreakOnRead; }
if(write) { e->flags |= DMN_TrapFlag_BreakOnWrite; }
if(exec) { e->flags |= DMN_TrapFlag_BreakOnExecute; }
}break;
//- rjf: unhandled exception case
default:
{
@@ -2400,6 +2657,10 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
for(DMN_W32_EntityNode *n = first_run_thread; n != 0; n = n->next)
{
DMN_W32_Entity *thread = n->v;
if(thread->kind != DMN_W32_EntityKind_Thread)
{
continue;
}
DWORD suspend_result = SuspendThread(thread->handle);
switch(suspend_result)
{
@@ -2428,7 +2689,9 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
}
}
////////////////////////
//- rjf: gather new thread-names
//
ProfScope("gather new thread names") if(dmn_w32_GetThreadDescription != 0)
{
for(DMN_W32_Entity *process = dmn_w32_shared->entities_base->first;
@@ -2481,10 +2744,46 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
for(U64 n_idx = 0; n_idx < n->count; n_idx += 1, trap_idx += 1)
{
DMN_Trap *trap = n->v+n_idx;
U8 og_byte = trap_swap_bytes[trap_idx];
if(og_byte != 0xCC)
if(trap->flags == 0)
{
dmn_process_write(trap->process, r1u64(trap->vaddr, trap->vaddr+1), &og_byte);
U8 og_byte = trap_swap_bytes[trap_idx];
if(og_byte != 0xCC)
{
dmn_process_write(trap->process, r1u64(trap->vaddr, trap->vaddr+1), &og_byte);
}
}
}
}
}
//////////////////////////
//- rjf: clear all debug register states, for flagged-traps
//
ProfScope("clear all debug register states, for flagged-traps")
{
for(DMN_FlaggedTrapTask *t = first_flagged_trap_task; t != 0; t = t->next)
{
DMN_Handle process = t->process;
DMN_W32_Entity *process_entity = dmn_w32_entity_from_handle(process);
for(DMN_W32_Entity *child = process_entity->first;
child != &dmn_w32_entity_nil;
child = child->next)
{
if(child->kind == DMN_W32_EntityKind_Thread)
{
switch(child->arch)
{
default:{}break;
//- rjf: x64
case Arch_x64:
{
REGS_RegBlockX64 regs = {0};
dmn_w32_thread_read_reg_block(child->arch, child->handle, &regs);
regs.dr7.u64 = 0;
dmn_w32_thread_write_reg_block(child->arch, child->handle, &regs);
}break;
}
}
}
}
+43 -41
View File
@@ -15,47 +15,49 @@
////////////////////////////////
//~ rjf: Win32 Exception Codes
#define DMN_W32_EXCEPTION_BREAKPOINT 0x80000003u
#define DMN_W32_EXCEPTION_SINGLE_STEP 0x80000004u
#define DMN_W32_EXCEPTION_LONG_JUMP 0x80000026u
#define DMN_W32_EXCEPTION_ACCESS_VIOLATION 0xC0000005u
#define DMN_W32_EXCEPTION_ARRAY_BOUNDS_EXCEEDED 0xC000008Cu
#define DMN_W32_EXCEPTION_DATA_TYPE_MISALIGNMENT 0x80000002u
#define DMN_W32_EXCEPTION_GUARD_PAGE_VIOLATION 0x80000001u
#define DMN_W32_EXCEPTION_FLT_DENORMAL_OPERAND 0xC000008Du
#define DMN_W32_EXCEPTION_FLT_DEVIDE_BY_ZERO 0xC000008Eu
#define DMN_W32_EXCEPTION_FLT_INEXACT_RESULT 0xC000008Fu
#define DMN_W32_EXCEPTION_FLT_INVALID_OPERATION 0xC0000090u
#define DMN_W32_EXCEPTION_FLT_OVERFLOW 0xC0000091u
#define DMN_W32_EXCEPTION_FLT_STACK_CHECK 0xC0000092u
#define DMN_W32_EXCEPTION_FLT_UNDERFLOW 0xC0000093u
#define DMN_W32_EXCEPTION_INT_DIVIDE_BY_ZERO 0xC0000094u
#define DMN_W32_EXCEPTION_INT_OVERFLOW 0xC0000095u
#define DMN_W32_EXCEPTION_PRIVILEGED_INSTRUCTION 0xC0000096u
#define DMN_W32_EXCEPTION_ILLEGAL_INSTRUCTION 0xC000001Du
#define DMN_W32_EXCEPTION_IN_PAGE_ERROR 0xC0000006u
#define DMN_W32_EXCEPTION_INVALID_DISPOSITION 0xC0000026u
#define DMN_W32_EXCEPTION_NONCONTINUABLE 0xC0000025u
#define DMN_W32_EXCEPTION_STACK_OVERFLOW 0xC00000FDu
#define DMN_W32_EXCEPTION_INVALID_HANDLE 0xC0000008u
#define DMN_W32_EXCEPTION_UNWIND_CONSOLIDATE 0x80000029u
#define DMN_W32_EXCEPTION_DLL_NOT_FOUND 0xC0000135u
#define DMN_W32_EXCEPTION_ORDINAL_NOT_FOUND 0xC0000138u
#define DMN_W32_EXCEPTION_ENTRY_POINT_NOT_FOUND 0xC0000139u
#define DMN_W32_EXCEPTION_DLL_INIT_FAILED 0xC0000142u
#define DMN_W32_EXCEPTION_CONTROL_C_EXIT 0xC000013Au
#define DMN_W32_EXCEPTION_FLT_MULTIPLE_FAULTS 0xC00002B4u
#define DMN_W32_EXCEPTION_FLT_MULTIPLE_TRAPS 0xC00002B5u
#define DMN_W32_EXCEPTION_NAT_CONSUMPTION 0xC00002C9u
#define DMN_W32_EXCEPTION_HEAP_CORRUPTION 0xC0000374u
#define DMN_W32_EXCEPTION_STACK_BUFFER_OVERRUN 0xC0000409u
#define DMN_W32_EXCEPTION_INVALID_CRUNTIME_PARAM 0xC0000417u
#define DMN_W32_EXCEPTION_ASSERT_FAILURE 0xC0000420u
#define DMN_W32_EXCEPTION_NO_MEMORY 0xC0000017u
#define DMN_W32_EXCEPTION_THROW 0xE06D7363u
#define DMN_W32_EXCEPTION_SET_THREAD_NAME 0x406d1388u
#define DMN_w32_EXCEPTION_CLRDBG_NOTIFICATION 0x04242420u
#define DMN_w32_EXCEPTION_CLR 0xE0434352u
#define DMN_W32_EXCEPTION_BREAKPOINT 0x80000003u
#define DMN_W32_EXCEPTION_SINGLE_STEP 0x80000004u
#define DMN_W32_EXCEPTION_LONG_JUMP 0x80000026u
#define DMN_W32_EXCEPTION_ACCESS_VIOLATION 0xC0000005u
#define DMN_W32_EXCEPTION_ARRAY_BOUNDS_EXCEEDED 0xC000008Cu
#define DMN_W32_EXCEPTION_DATA_TYPE_MISALIGNMENT 0x80000002u
#define DMN_W32_EXCEPTION_GUARD_PAGE_VIOLATION 0x80000001u
#define DMN_W32_EXCEPTION_FLT_DENORMAL_OPERAND 0xC000008Du
#define DMN_W32_EXCEPTION_FLT_DEVIDE_BY_ZERO 0xC000008Eu
#define DMN_W32_EXCEPTION_FLT_INEXACT_RESULT 0xC000008Fu
#define DMN_W32_EXCEPTION_FLT_INVALID_OPERATION 0xC0000090u
#define DMN_W32_EXCEPTION_FLT_OVERFLOW 0xC0000091u
#define DMN_W32_EXCEPTION_FLT_STACK_CHECK 0xC0000092u
#define DMN_W32_EXCEPTION_FLT_UNDERFLOW 0xC0000093u
#define DMN_W32_EXCEPTION_INT_DIVIDE_BY_ZERO 0xC0000094u
#define DMN_W32_EXCEPTION_INT_OVERFLOW 0xC0000095u
#define DMN_W32_EXCEPTION_PRIVILEGED_INSTRUCTION 0xC0000096u
#define DMN_W32_EXCEPTION_ILLEGAL_INSTRUCTION 0xC000001Du
#define DMN_W32_EXCEPTION_IN_PAGE_ERROR 0xC0000006u
#define DMN_W32_EXCEPTION_INVALID_DISPOSITION 0xC0000026u
#define DMN_W32_EXCEPTION_NONCONTINUABLE 0xC0000025u
#define DMN_W32_EXCEPTION_STACK_OVERFLOW 0xC00000FDu
#define DMN_W32_EXCEPTION_INVALID_HANDLE 0xC0000008u
#define DMN_W32_EXCEPTION_UNWIND_CONSOLIDATE 0x80000029u
#define DMN_W32_EXCEPTION_DLL_NOT_FOUND 0xC0000135u
#define DMN_W32_EXCEPTION_ORDINAL_NOT_FOUND 0xC0000138u
#define DMN_W32_EXCEPTION_ENTRY_POINT_NOT_FOUND 0xC0000139u
#define DMN_W32_EXCEPTION_DLL_INIT_FAILED 0xC0000142u
#define DMN_W32_EXCEPTION_CONTROL_C_EXIT 0xC000013Au
#define DMN_W32_EXCEPTION_FLT_MULTIPLE_FAULTS 0xC00002B4u
#define DMN_W32_EXCEPTION_FLT_MULTIPLE_TRAPS 0xC00002B5u
#define DMN_W32_EXCEPTION_NAT_CONSUMPTION 0xC00002C9u
#define DMN_W32_EXCEPTION_HEAP_CORRUPTION 0xC0000374u
#define DMN_W32_EXCEPTION_STACK_BUFFER_OVERRUN 0xC0000409u
#define DMN_W32_EXCEPTION_INVALID_CRUNTIME_PARAM 0xC0000417u
#define DMN_W32_EXCEPTION_ASSERT_FAILURE 0xC0000420u
#define DMN_W32_EXCEPTION_NO_MEMORY 0xC0000017u
#define DMN_W32_EXCEPTION_THROW 0xE06D7363u
#define DMN_W32_EXCEPTION_SET_THREAD_NAME 0x406d1388u
#define DMN_w32_EXCEPTION_CLRDBG_NOTIFICATION 0x04242420u
#define DMN_w32_EXCEPTION_CLR 0xE0434352u
#define DMN_W32_EXCEPTION_RADDBG_SET_THREAD_COLOR 0x00524144u
#define DMN_W32_EXCEPTION_RADDBG_SET_BREAKPOINT 0x00524145u
////////////////////////////////
//~ rjf: Win32 Register Codes
+117 -42
View File
@@ -45,9 +45,9 @@ dr_hash_from_string(String8 string)
//~ rjf: Fancy String Type Functions
internal void
dr_fancy_string_list_push(Arena *arena, DR_FancyStringList *list, DR_FancyString *str)
dr_fstrs_push(Arena *arena, DR_FStrList *list, DR_FStr *str)
{
DR_FancyStringNode *n = push_array_no_zero(arena, DR_FancyStringNode, 1);
DR_FStrNode *n = push_array_no_zero(arena, DR_FStrNode, 1);
MemoryCopyStruct(&n->v, str);
SLLQueuePush(list->first, list->last, n);
list->node_count += 1;
@@ -55,7 +55,38 @@ dr_fancy_string_list_push(Arena *arena, DR_FancyStringList *list, DR_FancyString
}
internal void
dr_fancy_string_list_concat_in_place(DR_FancyStringList *dst, DR_FancyStringList *to_push)
dr_fstrs_push_new_(Arena *arena, DR_FStrList *list, DR_FStrParams *params, DR_FStrParams *overrides, String8 string)
{
DR_FStr fstr = {string, *params};
if(!fnt_tag_match(fnt_tag_zero(), overrides->font))
{
fstr.params.font = overrides->font;
}
if(overrides->raster_flags != 0)
{
fstr.params.raster_flags = overrides->raster_flags;
}
if(overrides->color.x != 0 || overrides->color.y != 0 || overrides->color.z != 0 || overrides->color.w != 0)
{
fstr.params.color = overrides->color;
}
if(overrides->size != 0)
{
fstr.params.size = overrides->size;
}
if(overrides->underline_thickness != 0)
{
fstr.params.underline_thickness = overrides->underline_thickness;
}
if(overrides->strikethrough_thickness != 0)
{
fstr.params.strikethrough_thickness = overrides->strikethrough_thickness;
}
dr_fstrs_push(arena, list, &fstr);
}
internal void
dr_fstrs_concat_in_place(DR_FStrList *dst, DR_FStrList *to_push)
{
if(dst->last != 0 && to_push->first != 0)
{
@@ -71,34 +102,80 @@ dr_fancy_string_list_concat_in_place(DR_FancyStringList *dst, DR_FancyStringList
MemoryZeroStruct(to_push);
}
internal DR_FStrList
dr_fstrs_copy(Arena *arena, DR_FStrList *src)
{
DR_FStrList dst = {0};
for(DR_FStrNode *src_n = src->first; src_n != 0; src_n = src_n->next)
{
DR_FStr fstr = src_n->v;
fstr.string = push_str8_copy(arena, fstr.string);
dr_fstrs_push(arena, &dst, &fstr);
}
return dst;
}
internal String8
dr_string_from_fancy_string_list(Arena *arena, DR_FancyStringList *list)
dr_string_from_fstrs(Arena *arena, DR_FStrList *list)
{
String8 result = {0};
result.size = list->total_size;
result.str = push_array_no_zero(arena, U8, result.size);
U64 idx = 0;
for(DR_FancyStringNode *n = list->first; n != 0; n = n->next)
{
MemoryCopy(result.str+idx, n->v.string.str, n->v.string.size);
idx += n->v.string.size;
Temp scratch = scratch_begin(&arena, 1);
String8List parts = {0};
for(DR_FStrNode *n = list->first; n != 0; n = n->next)
{
if(!fnt_tag_match(n->v.params.font, dr_thread_ctx->icon_font))
{
str8_list_push(scratch.arena, &parts, n->v.string);
}
}
result = str8_list_join(arena, &parts, 0);
result = str8_skip_chop_whitespace(result);
scratch_end(scratch);
}
return result;
}
internal DR_FancyRunList
dr_fancy_run_list_from_fancy_string_list(Arena *arena, F32 tab_size_px, FNT_RasterFlags flags, DR_FancyStringList *strs)
internal FuzzyMatchRangeList
dr_fuzzy_match_find_from_fstrs(Arena *arena, DR_FStrList *fstrs, String8 needle)
{
Temp scratch = scratch_begin(&arena, 1);
String8 fstrs_string = {0};
fstrs_string.size = fstrs->total_size;
fstrs_string.str = push_array(arena, U8, fstrs_string.size);
{
// TODO(rjf): the fact that we only increment on non-icon portions is super weird?
// we are only doing that because of the rendering of the fuzzy matches, so maybe
// once that is straightened out, we can fix the code here too...
U64 off = 0;
for(DR_FStrNode *n = fstrs->first; n != 0; n = n->next)
{
if(!fnt_tag_match(n->v.params.font, dr_thread_ctx->icon_font))
{
MemoryCopy(fstrs_string.str + off, n->v.string.str, n->v.string.size);
off += n->v.string.size;
}
}
}
FuzzyMatchRangeList ranges = fuzzy_match_find(arena, needle, fstrs_string);
scratch_end(scratch);
return ranges;
}
internal DR_FRunList
dr_fruns_from_fstrs(Arena *arena, F32 tab_size_px, DR_FStrList *strs)
{
ProfBeginFunction();
DR_FancyRunList run_list = {0};
DR_FRunList run_list = {0};
F32 base_align_px = 0;
for(DR_FancyStringNode *n = strs->first; n != 0; n = n->next)
for(DR_FStrNode *n = strs->first; n != 0; n = n->next)
{
DR_FancyRunNode *dst_n = push_array(arena, DR_FancyRunNode, 1);
dst_n->v.run = fnt_push_run_from_string(arena, n->v.font, n->v.size, base_align_px, tab_size_px, flags, n->v.string);
dst_n->v.color = n->v.color;
dst_n->v.underline_thickness = n->v.underline_thickness;
dst_n->v.strikethrough_thickness = n->v.strikethrough_thickness;
DR_FRunNode *dst_n = push_array(arena, DR_FRunNode, 1);
dst_n->v.run = fnt_run_from_string(n->v.params.font, n->v.params.size, base_align_px, tab_size_px, n->v.params.raster_flags, n->v.string);
dst_n->v.color = n->v.params.color;
dst_n->v.underline_thickness = n->v.params.underline_thickness;
dst_n->v.strikethrough_thickness = n->v.params.strikethrough_thickness;
dst_n->v.icon = (fnt_tag_match(n->v.params.font, dr_thread_ctx->icon_font));
SLLQueuePush(run_list.first, run_list.last, dst_n);
run_list.node_count += 1;
run_list.dim.x += dst_n->v.run.dim.x;
@@ -109,20 +186,14 @@ dr_fancy_run_list_from_fancy_string_list(Arena *arena, F32 tab_size_px, FNT_Rast
return run_list;
}
internal DR_FancyRunList
dr_fancy_run_list_copy(Arena *arena, DR_FancyRunList *src)
internal Vec2F32
dr_dim_from_fstrs(F32 tab_size_px, DR_FStrList *fstrs)
{
DR_FancyRunList dst = {0};
for(DR_FancyRunNode *src_n = src->first; src_n != 0; src_n = src_n->next)
{
DR_FancyRunNode *dst_n = push_array(arena, DR_FancyRunNode, 1);
SLLQueuePush(dst.first, dst.last, dst_n);
MemoryCopyStruct(&dst_n->v, &src_n->v);
dst_n->v.run.pieces = fnt_piece_array_copy(arena, &src_n->v.run.pieces);
dst.node_count += 1;
}
dst.dim = src->dim;
return dst;
Temp scratch = scratch_begin(0, 0);
DR_FRunList fruns = dr_fruns_from_fstrs(scratch.arena, tab_size_px, fstrs);
Vec2F32 dim = fruns.dim;
scratch_end(scratch);
return dim;
}
////////////////////////////////
@@ -131,7 +202,7 @@ dr_fancy_run_list_copy(Arena *arena, DR_FancyRunList *src)
// (Frame boundaries)
internal void
dr_begin_frame(void)
dr_begin_frame(FNT_Tag icon_font)
{
if(dr_thread_ctx == 0)
{
@@ -143,6 +214,7 @@ dr_begin_frame(void)
arena_pop_to(dr_thread_ctx->arena, dr_thread_ctx->arena_frame_start_pos);
dr_thread_ctx->free_bucket_selection = 0;
dr_thread_ctx->top_bucket = 0;
dr_thread_ctx->icon_font = icon_font;
}
internal void
@@ -455,7 +527,7 @@ dr_sub_bucket(DR_Bucket *bucket)
//- rjf: text
internal void
dr_truncated_fancy_run_list(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FNT_Run trailer_run)
dr_truncated_fancy_run_list(Vec2F32 p, DR_FRunList *list, F32 max_x, FNT_Run trailer_run)
{
ProfBeginFunction();
@@ -467,9 +539,9 @@ dr_truncated_fancy_run_list(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FNT_Run
B32 trailer_found = 0;
Vec4F32 last_color = {0};
U64 byte_off = 0;
for(DR_FancyRunNode *n = list->first; n != 0; n = n->next)
for(DR_FRunNode *n = list->first; n != 0; n = n->next)
{
DR_FancyRun *fr = &n->v;
DR_FRun *fr = &n->v;
Rng1F32 pixel_range = {0};
{
pixel_range.min = 100000;
@@ -502,7 +574,7 @@ dr_truncated_fancy_run_list(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FNT_Run
if(!r_handle_match(texture, r_handle_zero()))
{
dr_img(dst, src, texture, fr->color, 0, 0, 0);
//dr_rect(dst, v4f32(0, 1, 0, 0.5f), 0, 1.f, 0.f);
// dr_rect(dst, v4f32(0, 1, 0, 0.5f), 0, 1.f, 0.f);
}
advance += piece->advance;
pixel_range.min = Min(pre_advance, pixel_range.min);
@@ -558,7 +630,7 @@ dr_truncated_fancy_run_list(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FNT_Run
}
internal void
dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color)
dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color)
{
for(FuzzyMatchRangeNode *match_n = ranges->first; match_n != 0; match_n = match_n->next)
{
@@ -573,9 +645,9 @@ dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FancyRunList *list, F32 max_x
F32 advance = 0;
F32 ascent = 0;
F32 descent = 0;
for(DR_FancyRunNode *fr_n = list->first; fr_n != 0; fr_n = fr_n->next)
for(DR_FRunNode *fr_n = list->first; fr_n != 0; fr_n = fr_n->next)
{
DR_FancyRun *fr = &fr_n->v;
DR_FRun *fr = &fr_n->v;
FNT_Run *run = &fr->run;
ascent = run->ascent;
descent = run->descent;
@@ -589,7 +661,10 @@ dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FancyRunList *list, F32 max_x
pixel_range.min = Min(pre_advance, pixel_range.min);
pixel_range.max = Max(post_advance, pixel_range.max);
}
byte_off += piece->decode_size;
if(!fr->icon)
{
byte_off += piece->decode_size;
}
advance += piece->advance;
}
}
@@ -637,7 +712,7 @@ internal void
dr_text(FNT_Tag font, F32 size, F32 base_align_px, F32 tab_size_px, FNT_RasterFlags flags, Vec2F32 p, Vec4F32 color, String8 string)
{
Temp scratch = scratch_begin(0, 0);
FNT_Run run = fnt_push_run_from_string(scratch.arena, font, size, base_align_px, tab_size_px, flags, string);
FNT_Run run = fnt_run_from_string(font, size, base_align_px, tab_size_px, flags, string);
dr_text_run(p, color, run);
scratch_end(scratch);
}
+42 -30
View File
@@ -7,54 +7,62 @@
////////////////////////////////
//~ rjf: Fancy String Types
typedef struct DR_FancyString DR_FancyString;
struct DR_FancyString
typedef struct DR_FStrParams DR_FStrParams;
struct DR_FStrParams
{
FNT_Tag font;
String8 string;
FNT_RasterFlags raster_flags;
Vec4F32 color;
F32 size;
F32 underline_thickness;
F32 strikethrough_thickness;
};
typedef struct DR_FancyStringNode DR_FancyStringNode;
struct DR_FancyStringNode
typedef struct DR_FStr DR_FStr;
struct DR_FStr
{
DR_FancyStringNode *next;
DR_FancyString v;
String8 string;
DR_FStrParams params;
};
typedef struct DR_FancyStringList DR_FancyStringList;
struct DR_FancyStringList
typedef struct DR_FStrNode DR_FStrNode;
struct DR_FStrNode
{
DR_FancyStringNode *first;
DR_FancyStringNode *last;
DR_FStrNode *next;
DR_FStr v;
};
typedef struct DR_FStrList DR_FStrList;
struct DR_FStrList
{
DR_FStrNode *first;
DR_FStrNode *last;
U64 node_count;
U64 total_size;
};
typedef struct DR_FancyRun DR_FancyRun;
struct DR_FancyRun
typedef struct DR_FRun DR_FRun;
struct DR_FRun
{
FNT_Run run;
Vec4F32 color;
F32 underline_thickness;
F32 strikethrough_thickness;
B32 icon;
};
typedef struct DR_FancyRunNode DR_FancyRunNode;
struct DR_FancyRunNode
typedef struct DR_FRunNode DR_FRunNode;
struct DR_FRunNode
{
DR_FancyRunNode *next;
DR_FancyRun v;
DR_FRunNode *next;
DR_FRun v;
};
typedef struct DR_FancyRunList DR_FancyRunList;
struct DR_FancyRunList
typedef struct DR_FRunList DR_FRunList;
struct DR_FRunList
{
DR_FancyRunNode *first;
DR_FancyRunNode *last;
DR_FRunNode *first;
DR_FRunNode *last;
U64 node_count;
Vec2F32 dim;
};
@@ -91,6 +99,7 @@ struct DR_ThreadCtx
{
Arena *arena;
U64 arena_frame_start_pos;
FNT_Tag icon_font;
DR_BucketSelectionNode *top_bucket;
DR_BucketSelectionNode *free_bucket_selection;
};
@@ -108,19 +117,22 @@ internal U64 dr_hash_from_string(String8 string);
////////////////////////////////
//~ rjf: Fancy String Type Functions
internal void dr_fancy_string_list_push(Arena *arena, DR_FancyStringList *list, DR_FancyString *str);
#define dr_fancy_string_list_push_new(arena, list, font_, size_, color_, string_, ...) dr_fancy_string_list_push((arena), (list), &(DR_FancyString){.font = (font_), .string = (string_), .color = (color_), .size = (size_), __VA_ARGS__})
internal void dr_fancy_string_list_concat_in_place(DR_FancyStringList *dst, DR_FancyStringList *to_push);
internal String8 dr_string_from_fancy_string_list(Arena *arena, DR_FancyStringList *list);
internal DR_FancyRunList dr_fancy_run_list_from_fancy_string_list(Arena *arena, F32 tab_size_px, FNT_RasterFlags flags, DR_FancyStringList *strs);
internal DR_FancyRunList dr_fancy_run_list_copy(Arena *arena, DR_FancyRunList *src);
internal void dr_fstrs_push(Arena *arena, DR_FStrList *list, DR_FStr *str);
internal void dr_fstrs_push_new_(Arena *arena, DR_FStrList *list, DR_FStrParams *params, DR_FStrParams *overrides, String8 string);
#define dr_fstrs_push_new(arena, list, params, string, ...) dr_fstrs_push_new_((arena), (list), (params), &(DR_FStrParams){.size = 0, __VA_ARGS__}, (string))
internal void dr_fstrs_concat_in_place(DR_FStrList *dst, DR_FStrList *to_push);
internal DR_FStrList dr_fstrs_copy(Arena *arena, DR_FStrList *src);
internal String8 dr_string_from_fstrs(Arena *arena, DR_FStrList *list);
internal FuzzyMatchRangeList dr_fuzzy_match_find_from_fstrs(Arena *arena, DR_FStrList *fstrs, String8 needle);
internal DR_FRunList dr_fruns_from_fstrs(Arena *arena, F32 tab_size_px, DR_FStrList *strs);
internal Vec2F32 dr_dim_from_fstrs(F32 tab_size_px, DR_FStrList *fstrs);
////////////////////////////////
//~ rjf: Top-Level API
//
// (Frame boundaries & bucket submission)
internal void dr_begin_frame(void);
internal void dr_begin_frame(FNT_Tag icon_font);
internal void dr_submit_bucket(OS_Handle os_window, R_Handle r_window, DR_Bucket *bucket);
////////////////////////////////
@@ -184,8 +196,8 @@ internal void dr_sub_bucket(DR_Bucket *bucket);
//~ rjf: Draw Call Helpers
//- rjf: text
internal void dr_truncated_fancy_run_list(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FNT_Run trailer_run);
internal void dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FancyRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color);
internal void dr_truncated_fancy_run_list(Vec2F32 p, DR_FRunList *list, F32 max_x, FNT_Run trailer_run);
internal void dr_truncated_fancy_run_fuzzy_matches(Vec2F32 p, DR_FRunList *list, F32 max_x, FuzzyMatchRangeList *ranges, Vec4F32 color);
internal void dr_text_run(Vec2F32 p, Vec4F32 color, FNT_Run run);
internal void dr_text(FNT_Tag font, F32 size, F32 base_align_px, F32 tab_size_px, FNT_RasterFlags flags, Vec2F32 p, Vec4F32 color, String8 string);
+132 -10
View File
@@ -1,6 +1,74 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal U64
dw_reg_size_from_code_x86(DW_Reg reg_code)
{
switch (reg_code) {
#define X(reg_name_dw, reg_code_dw, reg_name_rdi, reg_pos, reg_size) case DW_RegX86_##reg_name_dw: return reg_size;
DW_Regs_X86_XList(X)
#undef X
}
return 0;
}
internal U64
dw_reg_pos_from_code_x86(DW_Reg reg_code)
{
switch (reg_code) {
#define X(reg_name_dw, reg_code_dw, reg_name_rdi, reg_pos, reg_size) case DW_RegX86_##reg_name_dw: return reg_pos;
DW_Regs_X86_XList(X)
#undef X
}
return max_U64;
}
internal U64
dw_reg_size_from_code_x64(DW_Reg reg_code)
{
switch (reg_code) {
#define X(reg_name_dw, reg_code_dw, reg_name_rdi, reg_pos, reg_size) case DW_RegX64_##reg_name_dw: return reg_size;
DW_Regs_X64_XList(X)
#undef X
}
return 0;
}
internal U64
dw_reg_pos_from_code_x64(DW_Reg reg_code)
{
switch (reg_code) {
#define X(reg_name_dw, reg_code_dw, reg_name_rdi, reg_pos, reg_size) case DW_RegX64_##reg_name_dw: return reg_pos;
DW_Regs_X64_XList(X)
#undef X
}
return max_U64;
}
internal U64
dw_reg_size_from_code(Arch arch, DW_Reg reg_code)
{
switch (arch) {
case Arch_Null: break;
case Arch_x86: return dw_reg_size_from_code_x86(reg_code);
case Arch_x64: return dw_reg_size_from_code_x64(reg_code);
default: NotImplemented; break;
}
return 0;
}
internal U64
dw_reg_pos_from_code(Arch arch, DW_Reg reg_code)
{
switch (arch) {
case Arch_Null: break;
case Arch_x86: return dw_reg_pos_from_code_x86(reg_code);
case Arch_x64: return dw_reg_pos_from_code_x64(reg_code);
default: NotImplemented; break;
}
return max_U64;
}
internal DW_AttribClass
dw_attrib_class_from_attrib_kind_v2(DW_AttribKind k)
{
@@ -135,6 +203,11 @@ internal DW_AttribClass
dw_attrib_class_from_form_kind(DW_Version ver, DW_FormKind k)
{
#define X(_N,_C) case DW_Form_##_N: return _C;
switch (k) {
DW_Form_AttribClass_GNU_XList(X)
}
switch (ver) {
case DW_Version_5: {
switch (k) {
@@ -207,20 +280,20 @@ dw_dwo_name_string_from_section_kind(DW_SectionKind k)
}
internal U64
dw_offset_size_from_mode(DW_Mode mode)
dw_size_from_format(DW_Format format)
{
U64 result = 0;
switch (mode) {
case DW_Mode_Null: break;
case DW_Mode_32Bit: result = 4; break;
case DW_Mode_64Bit: result = 8; break;
switch (format) {
case DW_Format_Null: break;
case DW_Format_32Bit: result = 4; break;
case DW_Format_64Bit: result = 8; break;
default: InvalidPath; break;
}
return result;
}
internal DW_AttribClass
dw_pick_attrib_value_class(DW_Version ver, DW_Ext ext, DW_Language lang, B32 relaxed, DW_AttribKind attrib_kind, DW_FormKind form_kind)
dw_pick_attrib_value_class(DW_Version ver, DW_Ext ext, B32 relaxed, DW_AttribKind attrib_kind, DW_FormKind form_kind)
{
// NOTE(rjf): DWARF's spec specifies two mappings:
// (DW_AttribKind) => List(DW_AttribClass)
@@ -257,10 +330,59 @@ dw_pick_attrib_value_class(DW_Version ver, DW_Ext ext, DW_Language lang, B32 rel
}
}
if (attrib_kind != DW_Attrib_Null && form_kind != DW_Form_Null) {
//Assert(result != DW_AttribClass_Null && result != DW_AttribClass_Undefined);
}
return result;
}
internal U64
dw_pick_default_lower_bound(DW_Language lang)
{
U64 lower_bound = max_U64;
switch (lang) {
case DW_Language_Null: break;
case DW_Language_C89:
case DW_Language_C:
case DW_Language_CPlusPlus:
case DW_Language_C99:
case DW_Language_CPlusPlus03:
case DW_Language_CPlusPlus11:
case DW_Language_C11:
case DW_Language_CPlusPlus14:
case DW_Language_Java:
case DW_Language_ObjC:
case DW_Language_ObjCPlusPlus:
case DW_Language_UPC:
case DW_Language_D:
case DW_Language_Python:
case DW_Language_OpenCL:
case DW_Language_Go:
case DW_Language_Haskell:
case DW_Language_OCaml:
case DW_Language_Rust:
case DW_Language_Swift:
case DW_Language_Dylan:
case DW_Language_RenderScript:
case DW_Language_BLISS:
lower_bound = 0;
break;
case DW_Language_Ada83:
case DW_Language_Cobol74:
case DW_Language_Cobol85:
case DW_Language_Fortran77:
case DW_Language_Fortran90:
case DW_Language_Pascal83:
case DW_Language_Modula2:
case DW_Language_Ada95:
case DW_Language_Fortran95:
case DW_Language_PLI:
case DW_Language_Modula3:
case DW_Language_Julia:
case DW_Language_Fortran03:
case DW_Language_Fortran08:
lower_bound = 1;
default:
NotImplemented;
break;
}
return lower_bound;
}
+234 -140
View File
@@ -29,32 +29,35 @@ typedef enum DW_ExtEnum
DW_Ext_All = DW_Ext_GNU|DW_Ext_LLVM|DW_Ext_APPLE|DW_Ext_MIPS,
} DW_ExtEnum;
typedef enum DW_Mode
#define DW_FormatFromSize(size) ((size) >= max_U32 ? DW_Format_64Bit : DW_Format_32Bit)
typedef enum DW_Format
{
DW_Mode_Null,
DW_Mode_32Bit,
DW_Mode_64Bit
} DW_Mode;
DW_Format_Null,
DW_Format_32Bit,
DW_Format_64Bit
} DW_Format;
#define DW_SectionKind_XList(X) \
X(Null, "", "", "" ) \
X(Abbrev, ".debug_abbrev", "__debug_abbrev", ".debug_abbrev.dwo" ) \
X(ARanges, ".debug_aranges", "__debug_aranges", ".debug_aranges.dwo" ) \
X(Frame, ".debug_frame", "__debug_frame", ".debug_frame.dwo" ) \
X(Info, ".debug_info", "__debug_info", ".debug_info.dwo" ) \
X(Line, ".debug_line", "__debug_line", ".debug_line.dwo" ) \
X(Loc, ".debug_loc", "__debug_loc", ".debug_loc.dwo" ) \
X(MacInfo, ".debug_macinfo", "__debug_macinfo", ".debug_macinfo.dwo" ) \
X(PubNames, ".debug_pubnames", "__debug_pubnames", ".debug_pubnames.dwo" ) \
X(PubTypes, ".debug_pubtypes", "__debug_pubtypes", ".debug_pubtypes.dwo" ) \
X(Ranges, ".debug_ranges", "__debug_ranges", ".debug_ranges.dwo" ) \
X(Str, ".debug_str", "__debug_str", ".debug_str.dwo" ) \
X(Addr, ".debug_addr", "__debug_addr", ".debug_addr.dwo" ) \
X(LocLists, ".debug_loclists", "__debug_loclists", ".debug_loclists.dwo" ) \
X(RngLists, ".debug_rnglists", "__debug_rnglists", ".debug_rnglists.dwo" ) \
X(StrOffsets, ".debug_stroffsets", "__debug_stroffsets", ".debug_stroffsets.dwo" ) \
X(LineStr, ".debug_linestr", "__debug_linestr", ".debug_linestr.dwo" ) \
X(Names, ".debug_names", "__debug_names", ".debug_names.dwo" )
#define DW_SentinelFromSize(address_size) ((address_size) == 4 ? max_U32 : (address_size) == 8 ? max_U64 : 0)
#define DW_SectionKind_XList(X )\
X(Null, "", "", "" )\
X(Abbrev, ".debug_abbrev", "__debug_abbrev", ".debug_abbrev.dwo" )\
X(ARanges, ".debug_aranges", "__debug_aranges", ".debug_aranges.dwo" )\
X(Frame, ".debug_frame", "__debug_frame", ".debug_frame.dwo" )\
X(Info, ".debug_info", "__debug_info", ".debug_info.dwo" )\
X(Line, ".debug_line", "__debug_line", ".debug_line.dwo" )\
X(Loc, ".debug_loc", "__debug_loc", ".debug_loc.dwo" )\
X(MacInfo, ".debug_macinfo", "__debug_macinfo", ".debug_macinfo.dwo" )\
X(PubNames, ".debug_pubnames", "__debug_pubnames", ".debug_pubnames.dwo" )\
X(PubTypes, ".debug_pubtypes", "__debug_pubtypes", ".debug_pubtypes.dwo" )\
X(Ranges, ".debug_ranges", "__debug_ranges", ".debug_ranges.dwo" )\
X(Str, ".debug_str", "__debug_str", ".debug_str.dwo" )\
X(Addr, ".debug_addr", "__debug_addr", ".debug_addr.dwo" )\
X(LocLists, ".debug_loclists", "__debug_loclists", ".debug_loclists.dwo" )\
X(RngLists, ".debug_rnglists", "__debug_rnglists", ".debug_rnglists.dwo" )\
X(StrOffsets, ".debug_str_offsets", "__debug_str_offsets", ".debug_str_offsets.dwo")\
X(LineStr, ".debug_line_str", "__debug_line_str", ".debug_line_str.dwo" )\
X(Names, ".debug_names", "__debug_names", ".debug_names.dwo" )
typedef U64 DW_SectionKind;
typedef enum DW_SectionKindEnum
@@ -82,8 +85,8 @@ typedef enum DW_SectionKindEnum
X(Ada95, 0x0D) \
X(Fortran95, 0x0E) \
X(PLI, 0x0F) \
X(ObjectiveC, 0x10) \
X(ObjectiveCPlusPlus, 0x11) \
X(ObjC, 0x10) \
X(ObjCPlusPlus, 0x11) \
X(UPC, 0x12) \
X(D, 0x13) \
X(Python, 0x14) \
@@ -119,6 +122,20 @@ typedef enum DW_LanguageEnum
DW_Language_UserHi = 0xffff,
} DW_LanguageEnum;
#define DW_Inl_XList(X) \
X(NotInlined, 0) \
X(Inlined, 1) \
X(DeclaredNotInlined, 2) \
X(DeclaredInlined, 3)
typedef U32 DW_InlKind;
typedef enum DW_InlKindEnum
{
#define X(_N,_ID) DW_Inl_##_N = _ID,
DW_Inl_XList(X)
#undef X
} DW_InlKindEnum;
#define DW_StdOpcode_XList(X) \
X(ExtendedOpcode, 0x00) \
X(Copy, 0x01) \
@@ -157,19 +174,19 @@ typedef enum DW_ExtOpcode
#undef X
} DW_ExtOpcode;
#define DW_NameCase_XList(X) \
X(Sensitive, 0x00) \
X(Upper, 0x01) \
X(Lower, 0x02) \
X(Insensitive, 0x03)
#define DW_IDCaseKind_XList(X) \
X(CaseSensitive, 0x00) \
X(UpCase, 0x01) \
X(DownCase, 0x02) \
X(CaseInsensitive, 0x03)
typedef enum DW_NameCase
typedef U64 DW_IDCaseKind;
typedef enum DW_IDCaseKindEnum
{
#define X(_N,_ID) DW_NameCase_##_N = _ID,
DW_NameCase_XList(X)
#define X(_N,_ID) DW_IDCase_##_N = _ID,
DW_IDCaseKind_XList(X)
#undef X
DW_NameCase_Count
} DW_NameCase;
} DW_IDCaseKindEnum;
#define DW_Tag_V3_XList(X) \
X(ArrayType, 0x01) \
@@ -250,6 +267,7 @@ typedef enum DW_NameCase
typedef U64 DW_TagKind;
typedef enum DW_TagKindEnum
{
DW_Tag_Null,
#define X(_N,_ID) DW_Tag_##_N = _ID,
DW_Tag_V3_XList(X)
DW_Tag_V5_XList(X)
@@ -436,7 +454,7 @@ typedef enum DW_AttribClassEnum
X(LineStrp, DW_AttribClass_String) \
X(ImplicitConst, DW_AttribClass_Const) \
X(LocListx, DW_AttribClass_LocListPtr) \
X(RngListx, DW_AttribClass_RngListPtr) \
X(RngListx, DW_AttribClass_RngList) \
X(RefSup8, DW_AttribClass_Reference) \
X(Strx1, DW_AttribClass_String) \
X(Strx2, DW_AttribClass_String) \
@@ -447,6 +465,18 @@ typedef enum DW_AttribClassEnum
X(Addrx3, DW_AttribClass_Address) \
X(Addrx4, DW_AttribClass_Address)
#define DW_Form_GNU_XList(X) \
X(GNU_AddrIndex, 0x1f01) \
X(GNU_StrIndex, 0x1f02) \
X(GNU_RefAlt, 0x1f20) \
X(GNU_StrpAlt, 0x1f21)
#define DW_Form_AttribClass_GNU_XList(X) \
X(GNU_AddrIndex, DW_AttribClass_Undefined) \
X(GNU_StrIndex, DW_AttribClass_Undefined) \
X(GNU_RefAlt, DW_AttribClass_Undefined) \
X(GNU_StrpAlt, DW_AttribClass_String)
typedef U64 DW_FormKind;
typedef enum DW_FormEnum
{
@@ -455,6 +485,7 @@ typedef enum DW_FormEnum
DW_Form_V2_XList(X)
DW_Form_V4_XList(X)
DW_Form_V5_XList(X)
DW_Form_GNU_XList(X)
#undef X
} DW_FormEnum;
@@ -1143,41 +1174,41 @@ typedef enum DW_AttribKindEnum
DW_Attrib_UserHi = 0x3fff
} DW_AttribKindEnum;
#define DW_AttribTypeEncodingKind_XList(X) \
X(Null, 0x00) \
X(Address, 0x01) \
X(Boolean, 0x02) \
X(ComplexFloat, 0x03) \
X(Float, 0x04) \
X(Signed, 0x05) \
X(SignedChar, 0x06) \
X(Unsigned, 0x07) \
X(UnsignedChar, 0x08) \
X(ImaginaryFloat, 0x09) \
X(PackedDecimal, 0x0A) \
X(NumericString, 0x0B) \
X(Edited, 0x0C) \
X(SignedFixed, 0x0D) \
X(UnsignedFixed, 0x0E) \
X(DecimalFloat, 0x0F) \
X(Utf, 0x10) \
X(Ucs, 0x11) \
#define DW_ATE_XList(X) \
X(Null, 0x00) \
X(Address, 0x01) \
X(Boolean, 0x02) \
X(ComplexFloat, 0x03) \
X(Float, 0x04) \
X(Signed, 0x05) \
X(SignedChar, 0x06) \
X(Unsigned, 0x07) \
X(UnsignedChar, 0x08) \
X(ImaginaryFloat, 0x09) \
X(PackedDecimal, 0x0A) \
X(NumericString, 0x0B) \
X(Edited, 0x0C) \
X(SignedFixed, 0x0D) \
X(UnsignedFixed, 0x0E) \
X(DecimalFloat, 0x0F) \
X(Utf, 0x10) \
X(Ucs, 0x11) \
X(Ascii, 0x12)
typedef U64 DW_AttribTypeEncodingKind;
typedef enum DW_AttribTypeEncodingKindEnum
typedef U64 DW_ATE;
typedef enum DW_ATEEnum
{
#define X(_N,_ID) DW_AttribTypeEncodingKind_##_N = _ID,
DW_AttribTypeEncodingKind_XList(X)
#define X(_N,_ID) DW_ATE_##_N = _ID,
DW_ATE_XList(X)
#undef X
} DW_AttribTypeEncodingKindEnum;
} DW_ATEnum;
#define DW_CallingConventionKind_XList(X) \
X(DW_CallingConvention_Normal, 0x0) \
X(DW_CallingConvention_Program, 0x1) \
X(DW_CallingConvention_NoCall, 0x2) \
X(DW_CallingConvention_PassByValue, 0x1) \
X(DW_CallingConvention_PassByReference, 0x2)
#define DW_CallingConventionKind_XList(X) \
X(Normal, 0x0) \
X(Program, 0x1) \
X(NoCall, 0x3) \
X(PassByValue, 0x4) \
X(PassByReference, 0x5)
typedef U64 DW_CallingConventionKind;
typedef enum DW_CallingConventionKindEnum
@@ -1188,9 +1219,9 @@ typedef enum DW_CallingConventionKindEnum
} DW_CallingConventionKindEnum;
#define DW_AccessKind_XList(X) \
X(DW_Access_Public, 0x00) \
X(DW_Access_Private, 0x01) \
X(DW_Access_Protected, 0x02)
X(Public, 0x00) \
X(Private, 0x01) \
X(Protected, 0x02)
typedef U64 DW_AccessKind;
typedef enum DW_AccessKindEnum
@@ -1215,7 +1246,7 @@ typedef enum DW_VirtualityEnum
#define DW_RngListEntryKind(X) \
X(EndOfList, 0x00) \
X(BaseAddressX, 0x01) \
X(BaseAddressx, 0x01) \
X(StartxEndx, 0x02) \
X(StartxLength, 0x03) \
X(OffsetPair, 0x04) \
@@ -1223,32 +1254,51 @@ typedef enum DW_VirtualityEnum
X(StartEnd, 0x06) \
X(StartLength, 0x07)
typedef U64 DW_RngListEntryKind;
typedef enum DW_RngListEntryKindEnum
typedef U8 DW_RLE;
typedef enum DW_RLE_Enum
{
#define X(_N,_ID) DW_RngListEntryKind_##_N = _ID,
#define X(_N,_ID) DW_RLE_##_N = _ID,
DW_RngListEntryKind(X)
#undef X
} DW_RngListEntryKindEnum;
} DW_RLE_Enum;
#define DW_LocListEntry_XList(X) \
X(EndOfList, 0x00) \
X(BaseAddressX, 0x01) \
X(StartXEndX, 0x02) \
X(StartXLength, 0x03) \
X(BaseAddressx, 0x01) \
X(StartxEndx, 0x02) \
X(StartxLength, 0x03) \
X(OffsetPair, 0x04) \
X(DefaultLocation, 0x05) \
X(BaseAddress, 0x06) \
X(StartEnd, 0x07) \
X(StartLength, 0x08)
typedef U64 DW_LocListEntryKind;
typedef enum DW_LocListEntryEnum
#define DW_LocListEntry_GNU_XList(X) \
X(GNU_ViewPair, 0x9)
typedef U8 DW_LLE;
typedef enum DW_LLE_Enum
{
#define X(_N,_ID) DW_LocListEntryKind_##_N = _ID,
#define X(_N,_ID) DW_LLE_##_N = _ID,
DW_LocListEntry_XList(X)
#undef X
} DW_LocListEntryEnum;
} DW_LLEEnum;
#define DW_AddrClass_XList(X) \
X(None, 0) \
X(Near16, 1) \
X(Far16, 2) \
X(Huge16, 3) \
X(Near32, 4) \
X(Far32, 5)
typedef U64 DW_AddrClass;
typedef enum DW_AddrClassEnum
{
#define X(_N, _ID) DW_AddrClassKind_##_N = _ID,
DW_AddrClass_XList(X)
#undef X
} DW_AddrClassEnum;
#define DW_CompUnitKind_XList(X) \
X(Reserved, 0) \
@@ -1269,16 +1319,23 @@ typedef enum DW_CompUnitKindEnum
DW_CompUnitKind_UserHi = 0xff
} DW_CompUnitKindEnum;
typedef enum DW_LNCT
#define DW_LNCT_XList(X) \
X(Path, 0x1) \
X(DirectoryIndex, 0x2) \
X(TimeStamp, 0x3) \
X(Size, 0x4) \
X(MD5, 0x5) \
X(LLVM_Source, 0x2001)
typedef U64 DW_LNCT;
typedef enum DW_LNCTEnum
{
DW_LNCT_Path = 0x1,
DW_LNCT_DirectoryIndex = 0x2,
DW_LNCT_TimeStamp = 0x3,
DW_LNCT_Size = 0x4,
DW_LNCT_MD5 = 0x5,
DW_LNCT_UserLo = 0x2000,
DW_LNCT_UserHi = 0x3fff
} DW_LNCT;
#define X(_N, _ID) DW_LNCT_##_N = _ID,
DW_LNCT_XList(X)
#undef X
DW_LNCT_UserLo = 0x2000,
DW_LNCT_UserHi = 0x3fff
} DW_LNCTEnum;
#define DW_CFA_Kind1_XList(X) \
X(Nop, 0x0) \
@@ -1505,9 +1562,19 @@ enum
X(Convert, 0xa8) \
X(ReInterpret, 0xa9)
#define DW_Expr_GNU_XList(X) \
X(GNU_PushTlsAddress, 0xe0) \
X(GNU_UnInit, 0xf0)
#define DW_Expr_GNU_XList(X) \
X(GNU_PushTlsAddress, 0xe0) \
X(GNU_UnInit, 0xf0) \
X(GNU_ImplicitPointer, 0xf2) \
X(GNU_EntryValue, 0xf3) \
X(GNU_ConstType, 0xf4) \
X(GNU_RegvalType, 0xf5) \
X(GNU_DerefType, 0xf6) \
X(GNU_Convert, 0xf7) \
X(GNU_ParameterRef, 0xfa) \
X(GNU_AddrIndex, 0xfb) \
X(GNU_ConstIndex, 0xfc)
typedef U64 DW_ExprOp;
typedef enum DW_ExprOpEnum
{
@@ -1541,22 +1608,22 @@ typedef enum DW_ExprOpEnum
X(St5, 16, st5, 0, 10) \
X(St6, 17, st6, 0, 10) \
X(St7, 18, st7, 0, 10) \
X(Xmm0, 21, xmm0, 0, 16) \
X(Xmm1, 22, xmm1, 0, 16) \
X(Xmm2, 23, xmm2, 0, 16) \
X(Xmm3, 24, xmm3, 0, 16) \
X(Xmm4, 25, xmm4, 0, 16) \
X(Xmm5, 26, xmm5, 0, 16) \
X(Xmm6, 27, xmm6, 0, 16) \
X(Xmm7, 28, xmm7, 0, 16) \
X(Mm0, 29, mm0, 0, 4) \
X(Mm1, 30, mm1, 0, 4) \
X(Mm2, 31, mm2, 0, 4) \
X(Mm3, 32, mm3, 0, 4) \
X(Mm4, 33, mm4, 0, 4) \
X(Mm5, 34, mm5, 0, 4) \
X(Mm6, 35, mm6, 0, 4) \
X(Mm7, 36, mm7, 0, 4) \
X(Xmm0, 21, ymm0, 0, 16) \
X(Xmm1, 22, ymm1, 0, 16) \
X(Xmm2, 23, ymm2, 0, 16) \
X(Xmm3, 24, ymm3, 0, 16) \
X(Xmm4, 25, ymm4, 0, 16) \
X(Xmm5, 26, ymm5, 0, 16) \
X(Xmm6, 27, ymm6, 0, 16) \
X(Xmm7, 28, ymm7, 0, 16) \
X(Mm0, 29, fpr0, 0, 8) \
X(Mm1, 30, fpr1, 0, 8) \
X(Mm2, 31, fpr2, 0, 8) \
X(Mm3, 32, fpr3, 0, 8) \
X(Mm4, 33, fpr4, 0, 8) \
X(Mm5, 34, fpr5, 0, 8) \
X(Mm6, 35, fpr6, 0, 8) \
X(Mm7, 36, fpr7, 0, 8) \
X(Fcw, 37, fcw, 0, 2) \
X(Fsw, 38, fsw, 0, 2) \
X(Mxcsr, 39, mxcsr, 0, 4) \
@@ -1587,22 +1654,38 @@ typedef enum DW_ExprOpEnum
X(R14, 14, r14, 0, 8) \
X(R15, 15, r15, 0, 8) \
X(Rip, 16, rip, 0, 8) \
X(Xmm0, 17, ymm0, 0, 16) \
X(Xmm1, 18, ymm1, 0, 16) \
X(Xmm2, 19, ymm2, 0, 16) \
X(Xmm3, 20, ymm3, 0, 16) \
X(Xmm4, 21, ymm4, 0, 16) \
X(Xmm5, 22, ymm5, 0, 16) \
X(Xmm6, 23, ymm6, 0, 16) \
X(Xmm7, 24, ymm7, 0, 16) \
X(Xmm8, 25, ymm8, 0, 16) \
X(Xmm9, 26, ymm9, 0, 16) \
X(Xmm10, 27, ymm10, 0, 16) \
X(Xmm11, 28, ymm11, 0, 16) \
X(Xmm12, 29, ymm12, 0, 16) \
X(Xmm13, 30, ymm13, 0, 16) \
X(Xmm14, 31, ymm14, 0, 16) \
X(Xmm15, 32, ymm15, 0, 16) \
X(Xmm0, 17, zmm0, 0, 16) \
X(Xmm1, 18, zmm1, 0, 16) \
X(Xmm2, 19, zmm2, 0, 16) \
X(Xmm3, 20, zmm3, 0, 16) \
X(Xmm4, 21, zmm4, 0, 16) \
X(Xmm5, 22, zmm5, 0, 16) \
X(Xmm6, 23, zmm6, 0, 16) \
X(Xmm7, 24, zmm7, 0, 16) \
X(Xmm8, 25, zmm8, 0, 16) \
X(Xmm9, 26, zmm9, 0, 16) \
X(Xmm10, 27, zmm10, 0, 16) \
X(Xmm11, 28, zmm11, 0, 16) \
X(Xmm12, 29, zmm12, 0, 16) \
X(Xmm13, 30, zmm13, 0, 16) \
X(Xmm14, 31, zmm14, 0, 16) \
X(Xmm15, 32, zmm15, 0, 16) \
X(Xmm16, 67, zmm16, 0, 16) \
X(Xmm17, 68, zmm17, 0, 16) \
X(Xmm18, 69, zmm18, 0, 16) \
X(Xmm19, 70, zmm19, 0, 16) \
X(Xmm20, 71, zmm20, 0, 16) \
X(Xmm21, 72, zmm21, 0, 16) \
X(Xmm22, 73, zmm22, 0, 16) \
X(Xmm23, 74, zmm23, 0, 16) \
X(Xmm24, 75, zmm24, 0, 16) \
X(Xmm25, 76, zmm25, 0, 16) \
X(Xmm26, 77, zmm26, 0, 16) \
X(Xmm27, 78, zmm27, 0, 16) \
X(Xmm28, 79, zmm28, 0, 16) \
X(Xmm29, 80, zmm29, 0, 16) \
X(Xmm30, 81, zmm30, 0, 16) \
X(Xmm31, 82, zmm31, 0, 16) \
X(St0, 33, st0, 0, 10) \
X(St1, 34, st1, 0, 10) \
X(St2, 35, st2, 0, 10) \
@@ -1611,14 +1694,14 @@ typedef enum DW_ExprOpEnum
X(St5, 38, st5, 0, 10) \
X(St6, 39, st6, 0, 10) \
X(St7, 40, st7, 0, 10) \
X(Mm0, 41, mm0, 0, 8) \
X(Mm1, 42, mm1, 0, 8) \
X(Mm2, 43, mm2, 0, 8) \
X(Mm3, 44, mm3, 0, 8) \
X(Mm4, 45, mm4, 0, 8) \
X(Mm5, 46, mm5, 0, 8) \
X(Mm6, 47, mm6, 0, 8) \
X(Mm7, 48, mm7, 0, 8) \
X(Mm0, 41, fpr0, 0, 8) \
X(Mm1, 42, fpr1, 0, 8) \
X(Mm2, 43, fpr2, 0, 8) \
X(Mm3, 44, fpr3, 0, 8) \
X(Mm4, 45, fpr4, 0, 8) \
X(Mm5, 46, fpr5, 0, 8) \
X(Mm6, 47, fpr6, 0, 8) \
X(Mm7, 48, fpr7, 0, 8) \
X(Rflags, 49, rflags, 0, 4) \
X(Es, 50, es, 0, 2) \
X(Cs, 51, cs, 0, 2) \
@@ -1631,24 +1714,33 @@ typedef enum DW_ExprOpEnum
X(Tr, 62, nil, 0, 0) \
X(Ldtr, 63, nil, 0, 0)
typedef U32 DW_RegX86;
typedef U32 DW_Reg;
typedef DW_Reg DW_RegX86;
typedef enum DW_RegX86Enum
{
#define X(_N,_ID,...) DW_Reg_x86_##_N = _ID,
#define X(_N,_ID,...) DW_RegX86_##_N = _ID,
DW_Regs_X86_XList(X)
#undef X
} DW_RegX86Enum;
typedef U32 DW_RegX64;
typedef DW_Reg DW_RegX64;
typedef enum DW_RegX64Enum
{
#define X(_N,_ID,...) DW_Reg_x64_##_N = _ID,
#define X(_N,_ID,...) DW_RegX64_##_N = _ID,
DW_Regs_X64_XList(X)
#undef X
} DW_RegX64Enum;
////////////////////////////////
internal U64 dw_reg_size_from_code_x86(DW_Reg reg_code);
internal U64 dw_reg_pos_from_code_x86(DW_Reg reg_code);
internal U64 dw_reg_size_from_code_x64(DW_Reg reg_code);
internal U64 dw_reg_pos_from_code_x64(DW_Reg reg_code);
internal U64 dw_reg_size_from_code(Arch arch, DW_Reg reg_code);
internal U64 dw_reg_pos_from_code(Arch arch, DW_Reg reg_code);
//- Attrib Class Encodings
// Speced Encodings
@@ -1679,10 +1771,12 @@ internal String8 dw_dwo_name_string_from_section_kind (DW_SectionKind k);
////////////////////////////////
internal U64 dw_offset_size_from_mode(DW_Mode mode);
internal U64 dw_size_from_format(DW_Format format);
////////////////////////////////
internal DW_AttribClass dw_pick_attrib_value_class(DW_Version ver, DW_Ext ext, DW_Language lang, B32 relaxed, DW_AttribKind attrib, DW_FormKind form_kind);
internal DW_AttribClass dw_pick_attrib_value_class(DW_Version ver, DW_Ext ext, B32 relaxed, DW_AttribKind attrib, DW_FormKind form_kind);
internal U64 dw_pick_default_lower_bound(DW_Language lang);
#endif // DWARF_H
+68
View File
@@ -0,0 +1,68 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal B32
dw_is_dwarf_present_coff_section_table(String8 raw_image,
String8 string_table,
U64 section_count,
COFF_SectionHeader *section_table)
{
B32 is_dwarf_present = 0;
for (U64 i = 0; i < section_count; ++i) {
COFF_SectionHeader *header = &section_table[i];
String8 name = coff_name_from_section_header(string_table, header);
DW_SectionKind s = dw_section_kind_from_string(name);
if (s == DW_Section_Null) {
s = dw_section_dwo_kind_from_string(name);
}
is_dwarf_present = s != DW_Section_Null;
if (is_dwarf_present) {
break;
}
}
return is_dwarf_present;
}
internal DW_Input
dw_input_from_coff_section_table(Arena *arena,
String8 raw_image,
String8 string_table,
U64 section_count,
COFF_SectionHeader *section_table)
{
DW_Input input = {0};
B32 sect_status[ArrayCount(input.sec)] = {0};
for (U64 i = 0; i < section_count; ++i) {
COFF_SectionHeader *header = &section_table[i];
Rng1U64 raw_data_range = rng_1u64(header->foff, header->foff + header->fsize);
String8 name = coff_name_from_section_header(string_table, header);
DW_SectionKind s = dw_section_kind_from_string(name);
B32 is_dwo = 0;
if (s == DW_Section_Null) {
s = dw_section_dwo_kind_from_string(name);
is_dwo = 1;
}
if (s != DW_Section_Null) {
if (sect_status[s]) {
Assert(!"too many debug sections with identical name, picking first");
} else {
sect_status[s] = 1;
DW_Section *d = &input.sec[s];
d->name = push_str8_copy(arena, name);
d->data = str8_substr(raw_image, raw_data_range);
d->is_dwo = is_dwo;
}
}
}
return input;
}
+10
View File
@@ -0,0 +1,10 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef DWARF_COFF_H
#define DWARF_COFF_H
internal DW_Input dw_input_from_coff_section_table(Arena *arena, String8 raw_image, String8 string_table, U64 section_count, COFF_SectionHeader *section_table);
#endif // DWARF_COFF_H
+132
View File
@@ -0,0 +1,132 @@
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal B32
dw_is_dwarf_present_elf_section_table(String8 raw_image, ELF_BinInfo *bin)
{
Temp scratch = scratch_begin(0,0);
B32 is_dwarf_present = 0;
ELF_Shdr64Array sections = elf_shdr64_array_from_bin(scratch.arena, raw_image, &bin->hdr);
for (U64 i = 0; i < sections.count; ++i) {
ELF_Shdr64 *shdr = &sections.v[i];
String8 name = elf_name_from_shdr64(raw_image, &bin->hdr, bin->sh_name_range, shdr);
if (shdr->sh_type != ELF_SectionCode_ProgBits) {
continue;
}
DW_SectionKind s = dw_section_kind_from_string(name);
if (s == DW_Section_Null) {
s = dw_section_dwo_kind_from_string(name);
}
is_dwarf_present = s != DW_Section_Null;
if (is_dwarf_present) {
break;
}
}
scratch_end(scratch);
return is_dwarf_present;
}
internal DW_Input
dw_input_from_elf_section_table(Arena *arena, String8 raw_image, ELF_BinInfo *bin)
{
Temp scratch = scratch_begin(&arena, 1);
DW_Input result = {0};
B32 sect_status[ArrayCount(result.sec)] = {0};
ELF_Shdr64Array sections = elf_shdr64_array_from_bin(scratch.arena, raw_image, &bin->hdr);
for (U64 sect_idx = 1; sect_idx < sections.count; ++sect_idx) {
ELF_Shdr64 *shdr = &sections.v[sect_idx];
// skip BSS sections
if (shdr->sh_type != ELF_SectionCode_ProgBits) {
continue;
}
String8 name = elf_name_from_shdr64(raw_image, &bin->hdr, bin->sh_name_range, shdr);
DW_SectionKind s = dw_section_kind_from_string(name);
B32 is_dwo = 0;
if (s == DW_Section_Null) {
s = dw_section_dwo_kind_from_string(name);
is_dwo = 1;
}
if (s != DW_Section_Null) {
if (sect_status[s]) {
Assert(!"too many debug sections with identical name, picking first");
} else {
Rng1U64 raw_data_range = rng_1u64(shdr->sh_offset, shdr->sh_offset + shdr->sh_size);
String8 data = str8_substr(raw_image, raw_data_range);
// ELF was compiled with compressed debug info
if (shdr->sh_flags & ELF_Shf_Compressed) {
String8 comp_data_with_header = data;
// read header
ELF_Chdr64 chdr64 = {0};
U64 chdr_size = 0;
if (ELF_HdrIs64Bit(bin->hdr.e_ident)) {
chdr_size = str8_deserial_read_struct(comp_data_with_header, 0, &chdr64);
if (chdr_size != sizeof(chdr64)) {
Assert(!"not enough bytes to read header");
}
} else if (ELF_HdrIs32Bit(bin->hdr.e_ident)) {
ELF_Chdr32 chdr32 = {0};
chdr_size = str8_deserial_read_struct(comp_data_with_header, 0, &chdr32);
if (chdr_size == sizeof(chdr32)) {
chdr64 = elf_chdr64_from_chdr32(chdr32);
}
}
AssertAlways(IsPow2(chdr64.ch_addr_align));
// skip header
String8 comp_data = str8_skip(comp_data_with_header, chdr_size);
// push buffer for the decompressor
U8 *decomp_buffer = push_array_no_zero_aligned(arena, U8, chdr64.ch_size, chdr64.ch_addr_align);
U64 actual_decomp_size = 0;
// decompress
switch (chdr64.ch_type) {
case ELF_CompressType_None: {
AssertAlways(!"unexpected compression type");
} break;
case ELF_CompressType_ZLib: {
actual_decomp_size = zsinflate(decomp_buffer, chdr64.ch_size, comp_data.str, comp_data.size);
} break;
case ELF_CompressType_ZStd: {
// TODO: zstd lib
NotImplemented;
} break;
default: InvalidPath; break;
}
// TODO: error handling
AssertAlways(actual_decomp_size == chdr64.ch_size);
// set decompressed section data
data = str8(decomp_buffer, actual_decomp_size);
}
sect_status[s] = 1;
DW_Section *d = &result.sec[s];
d->name = push_str8_copy(arena, name);
d->data = data;
d->is_dwo = is_dwo;
}
}
}
scratch_end(scratch);
return result;
}
+11
View File
@@ -0,0 +1,11 @@
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef DWARF_ELF_H
#define DWARF_ELF_H
internal DW_Input dw_input_from_elf_section_table(Arena *arena, String8 raw_image, ELF_BinInfo *bin);
#endif // DWARF_ELF_H
+53 -10
View File
@@ -7,12 +7,10 @@ dw_string_from_expr_op(Arena *arena, DW_Version ver, DW_Ext ext, DW_ExprOp op)
String8 result = {0};
#define X(_N,...) case DW_ExprOp_##_N: result = str8_lit(Stringify(_N)); goto exit;
switch (ext) {
case DW_Ext_Null: break;
case DW_Ext_LLVM: break;
case DW_Ext_APPLE: break;
case DW_Ext_MIPS: break;
case DW_Ext_GNU: DW_Expr_GNU_XList(X); break;
if (ext & DW_Ext_GNU) {
switch (op) {
DW_Expr_GNU_XList(X);
}
}
switch (ver) {
@@ -48,6 +46,7 @@ internal String8
dw_string_from_tag_kind(Arena *arena, DW_TagKind kind)
{
switch (kind) {
case DW_Tag_Null: return str8_lit("Null");
#define X(_N,_ID) case DW_Tag_##_N: return str8_lit(Stringify(_N));
DW_Tag_V3_XList(X)
DW_Tag_V5_XList(X)
@@ -149,6 +148,50 @@ dw_string_from_language(Arena *arena, DW_Language kind)
return push_str8f(arena, "%x", kind);
}
internal String8
dw_string_from_inl(Arena *arena, DW_InlKind kind)
{
switch (kind) {
#define X(_N,_ID) case _ID: return str8_lit(Stringify(_N));
DW_Inl_XList(X)
#undef X
}
return push_str8f(arena, "%x", kind);
}
internal String8
dw_string_from_access_kind(Arena *arena, DW_AccessKind kind)
{
switch (kind) {
#define X(_N,_ID) case _ID: return str8_lit(Stringify(_N));
DW_AccessKind_XList(X)
#undef X
}
return push_str8f(arena, "%llx", kind);
}
internal String8
dw_string_from_calling_convetion(Arena *arena, DW_CallingConventionKind kind)
{
switch (kind) {
#define X(_N,_ID) case _ID: return str8_lit(Stringify(_N));
DW_CallingConventionKind_XList(X)
#undef X
}
return push_str8f(arena, "%llx", kind);
}
internal String8
dw_string_from_attrib_type_encoding(Arena *arena, DW_ATE kind)
{
switch (kind) {
#define X(_N,_ID) case _ID: return str8_lit(Stringify(_N));
DW_ATE_XList(X)
#undef X
}
return push_str8f(arena, "%llx", kind);
}
internal String8
dw_string_from_std_opcode(Arena *arena, DW_StdOpcode kind)
{
@@ -173,7 +216,7 @@ dw_string_from_ext_opcode(Arena *arena, DW_ExtOpcode kind)
}
internal String8
dw_string_from_loc_list_entry_kind(Arena *arena, DW_LocListEntryKind kind)
dw_string_from_loc_list_entry_kind(Arena *arena, DW_LLE kind)
{
NotImplemented;
return str8_zero();
@@ -187,7 +230,7 @@ dw_string_from_section_kind(Arena *arena, DW_SectionKind kind)
}
internal String8
dw_string_from_rng_list_entry_kind(Arena *arena, DW_RngListEntryKind kind)
dw_string_from_rng_list_entry_kind(Arena *arena, DW_RLE kind)
{
NotImplemented;
return str8_zero();
@@ -201,14 +244,14 @@ dw_string_from_register(Arena *arena, Arch arch, U64 reg_id)
case Arch_Null: break;
case Arch_x86: {
switch (reg_id) {
#define X(_N, _ID, ...) case DW_Reg_x86_##_N: reg_str = str8_lit(Stringify(_ID)); break;
#define X(_N, _ID, ...) case DW_RegX86_##_N: reg_str = str8_lit(Stringify(_N)); break;
DW_Regs_X86_XList(X)
#undef X
}
} break;
case Arch_x64: {
switch (reg_id) {
#define X(_N, _ID, ...) case DW_Reg_x64_##_N: reg_str = str8_lit(Stringify(_ID)); break;
#define X(_N, _ID, ...) case DW_RegX64_##_N: reg_str = str8_lit(Stringify(_N)); break;
DW_Regs_X64_XList(X)
#undef X
}
+1
View File
@@ -8,6 +8,7 @@ internal String8 dw_string_from_expr_op(Arena *arena, DW_Version ver, DW_Ext ext
internal String8 dw_string_from_tag_kind(Arena *arena, DW_TagKind kind);
internal String8 dw_string_from_attrib_kind(Arena *arena, DW_Version ver, DW_Ext ext, DW_AttribKind kind);
internal String8 dw_string_from_form_kind(Arena *arena, DW_Version ver, DW_FormKind kind);
internal String8 dw_string_access_kind(Arena *arena, DW_AccessKind kind);
//internal String8 dw_string_from_register(Arena *arena, Arch arch, U64 reg_id);
+10 -1
View File
@@ -3,13 +3,16 @@
//- analyzers
#if 0
internal DW_SimpleLoc
dw_expr__analyze_fast(void *base, Rng1U64 range, U64 text_section_base)
{
DW_SimpleLoc result = {DW_SimpleLocKind_Empty};
String8 expr_data = str8((U8*)data+range.min, (U8*)data+range.max);
U8 op = 0;
if (dw_based_range_read(base, range, 0, 1, &op)) {
if (str8_deserial_read_struct(expr_data, 0, &op)) {
// step params
U64 size_param = 0;
B32 is_signed = 0;
@@ -548,12 +551,14 @@ dw_expr__analyze_details(void *in_base, Rng1U64 in_range, DW_ExprMachineCallConf
scratch_end(scratch);
return result;
}
#endif
//- full eval
internal DW_Location
dw_expr__eval(Arena *arena_optional, void *expr_base, Rng1U64 expr_range, DW_ExprMachineConfig *config)
{
#if 0
Temp scratch = scratch_begin(&arena_optional, 1);
DW_Location result = {0};
@@ -1322,8 +1327,12 @@ dw_expr__eval(Arena *arena_optional, void *expr_base, Rng1U64 expr_range, DW_Exp
// clear stack
scratch_end(scratch);
return result;
#endif
DW_Location result = {0};
return result;
}
//- dw expr val stack
internal DW_ExprStack
+2741 -1991
View File
File diff suppressed because it is too large Load Diff
+305 -346
View File
@@ -4,38 +4,49 @@
#ifndef DWARF_PARSE_H
#define DWARF_PARSE_H
// NOTE(rjf): Some rules about the spaces of offsets and ranges:
//
// - Every stored/passed offset is relative to the base of its section.
// - Every stored/passed range has endpoints relative to the base of their section.
// - Upon calling a syms_based_range_* function, these offsets need to be
// converted into range-relative.
////////////////////////////////
//~ rjf: Constants
#define DWARF_VOID_TYPE_ID 0xffffffffffffffffull
////////////////////////////////
//~ rjf: Files + External Debug References
typedef struct DW_ExtDebugRef DW_ExtDebugRef;
struct DW_ExtDebugRef
typedef struct DW_Section
{
// NOTE(rjf): .dwo => an external DWARF V5 .dwo file
String8 dwo_path;
U64 dwo_id;
};
String8 name;
String8 data;
B32 is_dwo;
} DW_Section;
////////////////////////////////
//~ rjf: Abbrev Table
typedef struct DW_Input
{
DW_Section sec[DW_Section_Count];
DW_Section sup[DW_Section_Count];
} DW_Input;
typedef struct DW_AbbrevTableEntry DW_AbbrevTableEntry;
struct DW_AbbrevTableEntry
typedef struct DW_ListUnit
{
DW_Version version;
U64 address_size;
U64 segment_selector_size;
U64 entry_size;
String8 entries;
} DW_ListUnit;
typedef struct DW_ListUnitInput
{
U64 addr_count;
U64 str_offset_count;
U64 rnglist_count;
U64 loclist_count;
Rng1U64Array addr_ranges;
Rng1U64Array str_offset_ranges;
Rng1U64Array rnglist_ranges;
Rng1U64Array loclist_ranges;
DW_ListUnit *addrs;
DW_ListUnit *str_offsets;
DW_ListUnit *rnglists;
DW_ListUnit *loclists;
} DW_ListUnitInput;
typedef struct DW_AbbrevTableEntry
{
U64 id;
U64 off;
};
} DW_AbbrevTableEntry;
typedef struct DW_AbbrevTable DW_AbbrevTable;
struct DW_AbbrevTable
@@ -44,62 +55,6 @@ struct DW_AbbrevTable
DW_AbbrevTableEntry *entries;
};
////////////////////////////////
//~ Sections
typedef struct DW_Section DW_Section;
struct DW_Section
{
String8 name;
String8 data;
DW_Mode mode;
B32 is_dwo;
};
typedef struct DW_SectionArray DW_SectionArray;
struct DW_SectionArray
{
DW_Section v[DW_Section_Count];
};
////////////////////////////////
//~ rjf: Basic Line Info
typedef struct DW_LineFile DW_LineFile;
struct DW_LineFile
{
String8 file_name;
U64 dir_idx;
U64 modify_time;
U64 md5_digest[2];
U64 file_size;
};
typedef struct DW_LineVMFileNode DW_LineVMFileNode;
struct DW_LineVMFileNode
{
DW_LineVMFileNode *next;
DW_LineFile file;
};
typedef struct DW_LineVMFileList DW_LineVMFileList;
struct DW_LineVMFileList
{
U64 node_count;
DW_LineVMFileNode *first;
DW_LineVMFileNode *last;
};
typedef struct DW_LineVMFileArray DW_LineVMFileArray;
struct DW_LineVMFileArray
{
U64 count;
DW_LineFile *v;
};
////////////////////////////////
//~ rjf: Abbrevs
typedef enum DW_AbbrevKind
{
DW_Abbrev_Null,
@@ -108,215 +63,169 @@ typedef enum DW_AbbrevKind
DW_Abbrev_AttribSequenceEnd,
DW_Abbrev_DIEBegin,
DW_Abbrev_DIEEnd,
}
DW_AbbrevKind;
} DW_AbbrevKind;
typedef U32 DW_AbbrevFlags;
enum{
DW_AbbrevFlag_HasImplicitConst = (1<<0),
DW_AbbrevFlag_HasChildren = (1<<1),
enum
{
DW_AbbrevFlag_HasImplicitConst = (1 << 0),
DW_AbbrevFlag_HasChildren = (1 << 1),
};
typedef struct DW_Abbrev DW_Abbrev;
struct DW_Abbrev
typedef struct DW_Abbrev
{
DW_AbbrevKind kind;
Rng1U64 abbrev_range;
U64 sub_kind;
U64 id;
U64 const_value;
DW_AbbrevFlags flags;
};
} DW_Abbrev;
////////////////////////////////
//~ rjf: Attribs
typedef struct DW_AttribValueResolveParams DW_AttribValueResolveParams;
struct DW_AttribValueResolveParams
typedef union DW_Form
{
DW_Version version;
DW_Language language;
U64 addr_size; // NOTE(rjf): size in bytes of containing compilation unit's addresses
U64 containing_unit_info_off; // NOTE(rjf): containing compilation unit's offset into the .debug_info section
U64 debug_addrs_base; // NOTE(rjf): containing compilation unit's offset into the .debug_addrs section (DWARF V5 ONLY)
U64 debug_rnglists_base; // NOTE(rjf): containing compilation unit's offset into the .debug_rnglists section (DWARF V5 ONLY)
U64 debug_str_offs_base; // NOTE(rjf): containing compilation unit's offset into the .debug_str_offsets section (DWARF V5 ONLY)
U64 debug_loclists_base; // NOTE(rjf): containing compilation unit's offset into the .debug_loclists section (DWARF V5 ONLY)
};
String8 addr;
String8 block;
String8 data;
String8 string;
String8 exprloc;
B8 flag;
S64 sdata;
U64 udata;
U64 sec_offset;
U64 ref;
U64 strp_sup;
U64 xval;
U64 addrx;
U64 strx;
U64 rnglistx;
U64 ptr;
U64 implicit_const;
} DW_Form;
typedef struct DW_AttribValue DW_AttribValue;
struct DW_AttribValue
{
DW_SectionKind section;
U64 v[2];
};
typedef struct DW_Attrib DW_Attrib;
struct DW_Attrib
typedef struct DW_Attrib
{
U64 info_off;
U64 abbrev_off;
U64 abbrev_id;
DW_AttribKind attrib_kind;
DW_FormKind form_kind;
DW_AttribClass value_class;
DW_AttribValue form_value;
};
DW_Form form;
} DW_Attrib;
typedef struct DW_AttribArray DW_AttribArray;
struct DW_AttribArray
typedef struct DW_AttribNode
{
DW_Attrib *v;
U64 count;
};
struct DW_AttribNode *next;
DW_Attrib v;
} DW_AttribNode;
typedef struct DW_AttribNode DW_AttribNode;
struct DW_AttribNode
{
DW_AttribNode *next;
DW_Attrib attrib;
};
typedef struct DW_AttribList DW_AttribList;
struct DW_AttribList
typedef struct DW_AttribList
{
DW_AttribNode *first;
DW_AttribNode *last;
U64 count;
};
} DW_AttribList;
typedef struct DW_AttribListParseResult DW_AttribListParseResult;
struct DW_AttribListParseResult
typedef struct DW_Tag
{
DW_AttribList attribs;
U64 max_info_off;
U64 max_abbrev_off;
};
////////////////////////////////
//~ rjf: Compilation Units + Accelerators
typedef struct DW_CompRoot DW_CompRoot;
struct DW_CompRoot
{
// NOTE(rjf): Header Data
U64 size;
DW_CompUnitKind kind;
DW_Version version;
U64 address_size;
U64 abbrev_off;
U64 info_off;
Rng1U64 tags_info_range;
DW_AbbrevTable abbrev_table;
// NOTE(rjf): [parsed from DWARF attributes] Offsets For More Info (DWARF V5 ONLY)
U64 rnglist_base; // NOTE(rjf): Offset into the .debug_rnglists section where this comp unit's data is.
U64 loclist_base; // NOTE(rjf): Offset into the .debug_loclists section where this comp unit's data is.
U64 addrs_base; // NOTE(rjf): Offset into the .debug_addr section where this comp unit's data is.
U64 stroffs_base; // NOTE(rjf): Offset into the .debug_str_offsets section where this comp unit's data is.
// NOTE(rjf): [parsed from DWARF attributes] General Info
String8 name;
String8 producer;
String8 compile_dir;
String8 external_dwo_name;
U64 dwo_id;
DW_Language language;
U64 name_case;
B32 use_utf8;
U64 line_off;
U64 low_pc;
U64 high_pc;
DW_AttribValue ranges_attrib_value;
U64 base_addr;
};
////////////////////////////////
//~ rjf: Tags
typedef struct DW_Tag DW_Tag;
struct DW_Tag
{
DW_Tag *next_sibling;
DW_Tag *first_child;
DW_Tag *last_child;
DW_Tag *parent;
Rng1U64 info_range;
Rng1U64 abbrev_range;
B32 has_children;
U64 abbrev_id;
DW_TagKind kind;
U64 attribs_info_off;
U64 attribs_abbrev_off;
DW_AttribList attribs;
};
U64 info_off;
} DW_Tag;
typedef U32 DW_TagStubFlags;
enum
typedef struct DW_TagNode
{
DW_TagStubFlag_HasObjectPointerArg = (1<<0),
DW_TagStubFlag_HasLocation = (1<<1),
DW_TagStubFlag_HasExternal = (1<<2),
DW_TagStubFlag_HasSpecification = (1<<3),
};
DW_Tag tag;
struct DW_TagNode *sibling;
struct DW_TagNode *first_child;
struct DW_TagNode *last_child;
} DW_TagNode;
typedef struct DW_TagStub DW_TagStub;
struct DW_TagStub
typedef struct DW_Loc
{
U64 info_off;
DW_TagKind kind;
DW_TagStubFlags flags;
U64 children_info_off;
U64 attribs_info_off;
U64 attribs_abbrev_off;
// NOTE(rjf): DW_Attrib_Specification is tacked onto definitions that
// are filling out more info about a "prototype". That attribute is a reference
// that points back at the declaration tag. The declaration tag has the
// DW_Attrib_Declaration attribute, which is sort of like the reverse
// of that, except there's no reference. So what we're doing here is just storing
// a reference on both, that point back to each other, so it's always easy to
// get from decl => spec, or from spec => decl.
//SYMS_SymbolID ref;
// NOTE(rjf): DW_Attrib_AbstractOrigin is tacked onto some definitions
// that are used to specify information more specific to inlining, while wanting
// to refer to an "abstract" function DIE, that is not specific to any inline
// sites. The DWARF generator will not duplicate information across these, so
// we will occasionally need to look at an abstract origin to get abstract
// information, like name/linkage-name/etc.
//SYMS_SymbolID abstract_origin;
U64 _unused_;
};
Rng1U64 range;
String8 expr;
} DW_Loc;
typedef struct DW_TagStubNode DW_TagStubNode;
struct DW_TagStubNode
typedef struct DW_LocNode
{
DW_TagStubNode *next;
DW_TagStub stub;
};
DW_Loc v;
struct DW_LocNode *next;
} DW_LocNode;
typedef struct DW_TagStubList DW_TagStubList;
struct DW_TagStubList
typedef struct DW_LocList
{
DW_TagStubNode *first;
DW_TagStubNode *last;
U64 count;
};
U64 count;
DW_LocNode *first;
DW_LocNode *last;
} DW_LocList;
////////////////////////////////
//~ rjf: Line Info VM Types
typedef struct DW_LineVMHeader DW_LineVMHeader;
struct DW_LineVMHeader
typedef struct DW_CompUnit
{
U64 unit_length;
U64 unit_opl;
B32 relaxed;
DW_Ext ext;
DW_CompUnitKind kind;
DW_Version version;
DW_Format format;
U64 address_size;
U64 abbrev_off;
Rng1U64 info_range;
U64 first_tag_info_off;
DW_AbbrevTable abbrev_table;
String8 abbrev_data;
DW_ListUnit *addr_lu;
DW_ListUnit *str_offsets_lu;
DW_ListUnit *rnglists_lu;
DW_ListUnit *loclists_lu;
U64 low_pc;
U64 dwo_id;
DW_Tag tag;
HashTable *tag_ht;
} DW_CompUnit;
typedef struct DW_TagTree
{
DW_TagNode *root;
U64 tag_count;
} DW_TagTree;
typedef struct DW_LineFile
{
String8 file_name;
U64 dir_idx;
U64 modify_time;
U64 file_size;
U128 md5_digest;
String8 source;
} DW_LineFile;
typedef struct DW_LineVMFileNode
{
struct DW_LineVMFileNode *next;
DW_LineFile file;
} DW_LineVMFileNode;
typedef struct DW_LineVMFileList
{
U64 node_count;
DW_LineVMFileNode *first;
DW_LineVMFileNode *last;
} DW_LineVMFileList;
typedef struct DW_LineVMFileArray
{
U64 count;
DW_LineFile *v;
} DW_LineVMFileArray;
typedef struct DW_LineVMHeader
{
Rng1U64 unit_range;
DW_Version version;
U8 address_size; // Duplicates size from the compilation unit but is needed to support stripped exe that just have .debug_line and .debug_line_str.
U8 segment_selector_size;
U64 header_length;
U64 program_off;
U8 min_inst_len;
U8 max_ops_for_inst;
U8 default_is_stmt;
@@ -325,12 +234,11 @@ struct DW_LineVMHeader
U8 opcode_base;
U64 num_opcode_lens;
U8 *opcode_lens;
String8Array dir_table;
DW_LineVMFileArray dir_table;
DW_LineVMFileArray file_table;
};
} DW_LineVMHeader;
typedef struct DW_LineVMState DW_LineVMState;
struct DW_LineVMState
typedef struct DW_LineVMState
{
U64 address; // Address of a machine instruction.
U32 op_index; // This is used by the VLIW instructions to indicate index of operation inside the instruction.
@@ -351,144 +259,195 @@ struct DW_LineVMState
// prepare stack for a function.
B32 prologue_end;
B32 epilogue_begin; // NOTE(nick): Indicates that "address" points to section where function exits and unwinds stack.
U64 isa; // NOTE(nick): Instruction set that is used.
U64 discriminator; // NOTE(nick): Arbitrary id that indicates to which block these instructions belong.
B32 end_sequence; // NOTE(nick): Indicates that "address" points to the first instruction in the instruction block that follows.
// NOTE(rjf): it looks like LTO might sometimes zero out high PC and low PCs, causing a
// swath of line info to map to a range starting at 0. This causes overlapping ranges
// which we do not want to report. So this B32 will turn on emission.
B32 busted_seq;
};
B32 epilogue_begin; // Indicates that "address" points to section where function exits and unwinds stack.
U64 isa; // Instruction set that is used.
U64 discriminator; // Arbitrary id that indicates to which block these instructions belong.
B32 end_sequence; // Indicates that "address" points to the first instruction in the instruction block that follows.
} DW_LineVMState;
typedef struct DW_Line DW_Line;
struct DW_Line
typedef struct DW_Line
{
U64 file_index;
U32 line;
U32 column;
U64 voff;
};
U64 address;
} DW_Line;
typedef struct DW_LineNode DW_LineNode;
struct DW_LineNode
typedef struct DW_LineNode
{
DW_LineNode *next;
DW_Line v;
};
struct DW_LineNode *next;
DW_Line v;
} DW_LineNode;
typedef struct DW_LineSeqNode DW_LineSeqNode;
struct DW_LineSeqNode
typedef struct DW_LineSeqNode
{
DW_LineSeqNode *next;
U64 count;
DW_LineNode *first;
DW_LineNode *last;
};
struct DW_LineSeqNode *next;
U64 count;
DW_LineNode *first;
DW_LineNode *last;
} DW_LineSeqNode;
typedef struct DW_LineTableParseResult DW_LineTableParseResult;
struct DW_LineTableParseResult
typedef struct DW_LineTableParseResult
{
DW_LineVMHeader vm_header;
U64 seq_count;
DW_LineSeqNode *first_seq;
DW_LineSeqNode *last_seq;
};
} DW_LineTableParseResult;
////////////////////////////////
//~ rjf: .debug_pubnames and .debug_pubtypes
// .debug_pubnames and .debug_pubtypes
typedef struct DW_PubStringsBucket DW_PubStringsBucket;
struct DW_PubStringsBucket
typedef struct DW_PubStringsBucket
{
DW_PubStringsBucket *next;
String8 string;
U64 info_off;
U64 cu_info_off;
};
struct DW_PubStringsBucket *next;
String8 string;
U64 info_off;
U64 cu_info_off;
} DW_PubStringsBucket;
typedef struct DW_PubStringsTable DW_PubStringsTable;
struct DW_PubStringsTable
typedef struct DW_PubStringsTable
{
U64 size;
U64 size;
DW_PubStringsBucket **buckets;
};
} DW_PubStringsTable;
////////////////////////////////
//~ rjf: Basic Helpers
typedef struct DW_Reference
{
DW_CompUnit *cu;
U64 info_off;
} DW_Reference;
// hasher
internal U64 dw_hash_from_string(String8 string);
////////////////////////////////
//~ Specific Based Range Helpers
// deserial helpers
#define dw_based_range_read_struct(base, range, offset, out) dw_based_range_read(base, range, offset, sizeof(*out), out)
internal U64 str8_deserial_read_dwarf_packed_size(String8 string, U64 off, U64 *size_out);
internal U64 str8_deserial_read_dwarf_uint (String8 string, U64 off, DW_Format format, U64 *uint_out);
internal U64 str8_deserial_read_uleb128 (String8 string, U64 off, U64 *value_out);
internal U64 str8_deserial_read_sleb128 (String8 string, U64 off, S64 *value_out);
internal U64 str8_deserial_read_uleb128_array(Arena *arena, String8 string, U64 off, U64 count, U64 **arr_out);
internal U64 str8_deserial_read_sleb128_array(Arena *arena, String8 string, U64 off, U64 count, S64 **arr_out);
internal U64 dw_based_range_read(void *base, Rng1U64 range, U64 offset, U64 size, void *out);
internal String8 dw_based_range_read_string(void *base, Rng1U64 range, U64 offset);
internal void* dw_based_range_ptr(void *base, Rng1U64 range, U64 offset);
internal void* dw_based_range_ptr_size(void *base, Rng1U64 range, U64 offset, U64 size);
internal U64 dw_based_range_read_uleb128(void *base, Rng1U64 range, U64 offset, U64 *out_value);
internal U64 dw_based_range_read_sleb128(void *base, Rng1U64 range, U64 offset, S64 *out_value);
internal U64 dw_based_range_read_length(void *base, Rng1U64 range, U64 offset, U64 *out_value);
internal U64 dw_based_range_read_abbrev_tag(void *base, Rng1U64 range, U64 offset, DW_Abbrev *out_abbrev);
internal U64 dw_based_range_read_abbrev_attrib_info(void *base, Rng1U64 range, U64 offset, DW_Abbrev *out_abbrev);
internal U64 dw_based_range_read_attrib_form_value(void *base, Rng1U64 range, U64 offset, DW_Mode mode, U64 address_size, DW_FormKind form_kind, U64 implicit_const, DW_AttribValue *form_value_out);
internal Rng1U64List dw_unit_ranges_from_data(Arena *arena, String8 data);
internal DW_Mode dw_mode_from_sec(DW_SectionArray *sections, DW_SectionKind kind);
internal B32 dw_sec_is_present(DW_SectionArray *sections, DW_SectionKind kind);
internal void* dw_base_from_sec(DW_SectionArray *sections, DW_SectionKind kind);
internal Rng1U64 dw_range_from_sec(DW_SectionArray *sections, DW_SectionKind kind);
// list units
////////////////////////////////
//~ rjf: Abbrev Table
internal U64 dw_read_list_unit_header_addr (String8 unit_data, DW_ListUnit *lu_out);
internal U64 dw_read_list_unit_header_str_offsets(String8 unit_data, DW_ListUnit *lu_out);
internal U64 dw_read_list_unit_header_list (String8 unit_data, DW_ListUnit *lu_out);
internal DW_AbbrevTable dw_make_abbrev_table(Arena *arena, DW_SectionArray *sections, U64 start_abbrev_off);
internal DW_ListUnitInput dw_list_unit_input_from_input(Arena *arena, DW_Input *input);
internal U64 dw_offset_from_list_unit(DW_ListUnit *lu, U64 index);
internal U64 dw_addr_from_list_unit (DW_ListUnit *lu, U64 index);
// abbrev table
internal U64 dw_read_abbrev_tag (String8 data, U64 offset, DW_Abbrev *out_abbrev);
internal U64 dw_read_abbrev_attrib(String8 data, U64 offset, DW_Abbrev *out_abbrev);
internal DW_AbbrevTable dw_make_abbrev_table(Arena *arena, String8 abbrev_data, U64 start_abbrev_off);
internal U64 dw_abbrev_offset_from_abbrev_id(DW_AbbrevTable table, U64 abbrev_id);
////////////////////////////////
//~ rjf: Miscellaneous DWARF Section Parsing
// form and tag
//- rjf: .debug_ranges (DWARF V4)
internal Rng1U64List dw_v4_range_list_from_range_offset(Arena *arena, DW_SectionArray *sections, U64 addr_size, U64 comp_unit_base_addr, U64 range_off);
internal U64 dw_read_form(String8 data, U64 off, DW_Version version, DW_Format unit_format, U64 address_size, DW_FormKind form_kind, U64 implicit_const, DW_Form *form_out);
internal U64 dw_read_tag (Arena *arena, String8 tag_data, U64 tag_off, U64 tag_base, DW_AbbrevTable abbrev_table, String8 abbrev_data, DW_Version version, DW_Format unit_format, U64 address_size, DW_Tag *tag_out);
internal U64 dw_read_tag_cu(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 info_off, DW_Tag *tag_out);
//- rjf: .debug_pubtypes + .debug_pubnames (DWARF V4)
internal DW_PubStringsTable dw_v4_pub_strings_table_from_section_kind(Arena *arena, DW_SectionArray *sections, DW_SectionKind section_kind);
// attrib interp
//- rjf: .debug_str_offsets (DWARF V5)
internal U64 dw_v5_offset_from_offs_section_base_index(DW_SectionArray *sections, DW_SectionKind section, U64 base, U64 index);
internal U64 dw_interp_sec_offset(DW_FormKind form_kind, DW_Form form);
internal String8 dw_interp_exprloc (DW_FormKind form_kind, DW_Form form);
internal U128 dw_interp_const_u128(DW_FormKind form_kind, DW_Form form);
internal U64 dw_interp_const_u64 (DW_FormKind form_kind, DW_Form form);
internal U32 dw_interp_const_u32 (DW_FormKind form_kind, DW_Form form);
internal S64 dw_interp_const_s64 (DW_FormKind form_kind, DW_Form form);
internal S32 dw_interp_const_s32 (DW_FormKind form_kind, DW_Form form);
internal B32 dw_interp_flag (DW_FormKind form_kind, DW_Form form);
internal U64 dw_interp_address (U64 address_size, U64 base_addr, DW_ListUnit *addr_xlist, DW_FormKind form_kind, DW_Form form);
internal String8 dw_interp_block (DW_Input *input, DW_CompUnit *cu, DW_FormKind form_kind, DW_Form form);
internal String8 dw_interp_string (DW_Input *input, DW_Format unit_format, DW_ListUnit *str_offsets, DW_FormKind form_kind, DW_Form form);
internal String8 dw_interp_line_ptr (DW_Input *input, DW_FormKind form_kind, DW_Form form);
internal DW_LineFile * dw_interp_file (DW_LineVMHeader *line_vm, DW_FormKind form_kind, DW_Form form);
internal DW_Reference dw_interp_ref (DW_Input *input, DW_CompUnit *cu, DW_FormKind form_kind, DW_Form form);
internal DW_LocList dw_interp_loclist (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind form_kind, DW_Form form);
internal Rng1U64List dw_interp_rnglist (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind form_kind, DW_Form form);
//- rjf: .debug_addr (DWARF V5)
internal U64 dw_v5_addr_from_addrs_section_base_index(DW_SectionArray *sections, DW_SectionKind section, U64 base, U64 index);
internal String8 dw_exprloc_from_attrib_ptr (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal U128 dw_const_u128_from_attrib_ptr(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal U64 dw_const_u64_from_attrib_ptr (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal U32 dw_const_u32_from_attrib_ptr (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal S64 dw_const_s64_from_attrib_ptr (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal S32 dw_const_s32_from_attrib_ptr (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal B32 dw_flag_from_attrib_ptr (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal U64 dw_address_from_attrib_ptr (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal String8 dw_block_from_attrib_ptr (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal String8 dw_string_from_attrib_ptr (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal String8 dw_line_ptr_from_attrib_ptr (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal DW_LineFile * dw_file_from_attrib_ptr (DW_CompUnit *cu, DW_LineVMHeader *line_vm, DW_Attrib *attrib);
internal DW_Reference dw_ref_from_attrib_ptr (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal DW_LocList dw_loclist_from_attrib_ptr (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal Rng1U64List dw_rnglist_from_attrib_ptr (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
//- rjf: .debug_rnglists parsing (DWARF V5)
internal U64 dw_v5_sec_offset_from_rnglist_or_loclist_section_base_index(DW_SectionArray *sections, DW_SectionKind section_kind, U64 base, U64 index);
internal Rng1U64List dw_v5_range_list_from_rnglist_offset(Arena *arena, DW_SectionArray *sections, DW_SectionKind section, U64 addr_size, U64 addr_section_base, U64 offset);
internal String8 dw_exprloc_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal U128 dw_const_u128_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal U64 dw_const_u64_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal U32 dw_const_u32_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal B32 dw_flag_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal U64 dw_address_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal String8 dw_block_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal String8 dw_string_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal String8 dw_line_ptr_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal String8 dw_line_ptr_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal DW_LineFile * dw_file_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_LineVMHeader *line_vm, DW_Tag tag, DW_AttribKind kind);
internal DW_Reference dw_ref_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal DW_LocList dw_loclist_from_attrib (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal Rng1U64List dw_rnglist_from_attrib (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
////////////////////////////////
//~ rjf: Attrib Value Parsing
// compile unit
internal DW_AttribValueResolveParams dw_attrib_value_resolve_params_from_comp_root(DW_CompRoot *root);
internal DW_AttribValue dw_attrib_value_from_form_value(DW_SectionArray *sections, DW_AttribValueResolveParams resolve_params, DW_FormKind form_kind, DW_AttribClass value_class, DW_AttribValue form_value);
internal String8 dw_string_from_attrib_value(DW_SectionArray *sections, DW_AttribValue value);
internal Rng1U64List dw_range_list_from_high_low_pc_and_ranges_attrib_value(Arena *arena, DW_SectionArray *sections, U64 address_size, U64 comp_unit_base_addr, U64 addr_section_base, U64 low_pc, U64 high_pc, DW_AttribValue ranges_value);
internal DW_CompUnit dw_cu_from_info_off(Arena *arena, DW_Input *input, DW_ListUnitInput lu_input, U64 offset, B32 relaxed);
internal DW_TagTree dw_tag_tree_from_cu(Arena *arena, DW_Input *input, DW_CompUnit *cu);
internal HashTable * dw_make_tag_hash_table(Arena *arena, DW_TagTree tag_tree);
internal DW_TagNode * dw_tag_node_from_info_off(DW_CompUnit *cu, U64 info_off);
////////////////////////////////
//~ rjf: Tag Parsing
// line info
internal DW_AttribListParseResult dw_parse_attrib_list_from_info_abbrev_offsets(Arena *arena, DW_SectionArray *sections, DW_Version ver, DW_Ext ext, DW_Language lang, U64 address_size, U64 info_off, U64 abbrev_off, B32 relaxed);
internal DW_Tag* dw_tag_from_info_offset(Arena *arena, DW_SectionArray *sections, DW_AbbrevTable abbrev_table, DW_Version ver, DW_Ext ext, DW_Language lang, U64 address_size, U64 info_offset, B32 relaxed);
internal DW_TagStub dw_stub_from_tag(DW_SectionArray *sections, DW_AttribValueResolveParams resolve_params, DW_Tag *tag);
internal U64 dw_read_line_file(String8 line_data,
U64 line_off,
DW_Input *input,
DW_Version unit_version,
DW_Format unit_format,
DW_Ext ext,
U64 address_size,
DW_ListUnit *str_offsets,
U64 enc_count,
U64 *enc_arr,
DW_LineFile *line_file_out);
internal U64 dw_read_line_vm_header(Arena *arena,
String8 line_data,
U64 line_off,
DW_Input *input,
String8 cu_dir,
String8 cu_name,
U8 cu_address_size,
DW_ListUnit *cu_str_offsets,
DW_LineVMHeader *header_out);
//- rjf: line info
internal void dw_line_vm_reset(DW_LineVMState *state, B32 default_is_stmt);
internal void dw_line_vm_advance(DW_LineVMState *state, U64 advance, U64 min_inst_len, U64 max_ops_for_inst);
internal void dw_line_vm_reset(DW_LineVMState *state, B32 default_is_stmt);
internal void dw_line_vm_advance(DW_LineVMState *state, U64 advance, U64 min_inst_len, U64 max_ops_for_inst);
internal DW_LineSeqNode * dw_push_line_seq(Arena* arena, DW_LineTableParseResult *parsed_tbl);
internal DW_LineNode * dw_push_line(Arena *arena, DW_LineTableParseResult *tbl, DW_LineVMState *vm_state, B32 start_of_sequence);
internal String8 dw_path_from_file(Arena *arena, DW_LineVMHeader *vm, DW_LineFile *file);
internal String8 dw_path_from_file_idx(Arena *arena, DW_LineVMHeader *vm, U64 file_idx);
internal DW_LineSeqNode* dw_push_line_seq(Arena* arena, DW_LineTableParseResult *parsed_tbl);
internal DW_LineNode* dw_push_line(Arena *arena, DW_LineTableParseResult *tbl, DW_LineVMState *vm_state, B32 start_of_sequence);
internal DW_LineTableParseResult dw_parsed_line_table_from_comp_root(Arena *arena, DW_SectionArray *sections, DW_CompRoot *root);
internal U64 dw_read_line_file(void *line_base, Rng1U64 line_rng, U64 line_off, DW_Mode mode, DW_SectionArray *sections, DW_AttribValueResolveParams resolve_params, U8 address_size, U64 format_count, Rng1U64 *formats, DW_LineFile *line_file_out);
internal U64 dw_read_line_vm_header(Arena *arena, void *line_base, Rng1U64 line_rng, U64 line_off, DW_Mode mode, DW_SectionArray *sections, DW_AttribValueResolveParams resolve_params, String8 compile_dir, String8 unit_name, DW_LineVMHeader *header_out);
internal DW_LineTableParseResult dw_parsed_line_table_from_data(Arena *arena, String8 unit_data, DW_Input *input, String8 cu_dir, String8 cu_name, U8 cu_address_size, DW_ListUnit *cu_str_offsets);
// helper for .debug_pubtypes and .debug_pubnames
internal DW_PubStringsTable dw_v4_pub_strings_table_from_section_kind(Arena *arena, DW_Input *input, DW_SectionKind section_kind);
#endif // DWARF_PARSE_H
+9 -1
View File
@@ -1,6 +1,11 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal U64 dw_based_range_read(void *base, Rng1U64 range, U64 off, U64 size, void *out) { return 0; }
internal U64 dw_based_range_read_uleb128(void *base, Rng1U64 range, U64 off, U64 *out) { return 0; }
internal U64 dw_based_range_read_sleb128(void *base, Rng1U64 range, U64 off, S64 *out) { return 0; }
internal U64 dw_based_range_read_length(void *base, Rng1U64 range, U64 off, U64 *out) { return 0; }
////////////////////////////////
// x64 Unwind Function
@@ -148,7 +153,7 @@ dw_unwind_x64__apply_frame_rules(String8 raw_eh_frame,
// is this a roll-over CFA?
B32 is_roll_over_cfa = 0;
if (reg_idx == DW_Reg_x64_Rsp) {
if (reg_idx == DW_RegX64_Rsp) {
DW_CFIRegisterRule rule = row->cells[reg_idx].rule;
if (rule == DW_CFIRegisterRule_Undefined || rule == DW_CFIRegisterRule_SameValue) {
is_roll_over_cfa = 1;
@@ -410,6 +415,8 @@ dw_unwind_parse_pointer_x64(void *frame_base, Rng1U64 frame_range, DW_EhPtrCtx *
internal void
dw_unwind_parse_cie_x64(void *base, Rng1U64 range, DW_EhPtrCtx *ptr_ctx, U64 off, DW_CIEUnpacked *cie_out)
{
NotImplemented;
#if 0
MemoryZeroStruct(cie_out);
// get version
@@ -521,6 +528,7 @@ dw_unwind_parse_cie_x64(void *base, Rng1U64 range, DW_EhPtrCtx *ptr_ctx, U64 off
cie_out->cfi_range.min = cfi_off;
cie_out->cfi_range.max = cfi_off + cfi_size;
}
#endif
}
internal void
+143
View File
@@ -0,0 +1,143 @@
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: 32 => 64 bit conversions
internal ELF_Hdr64
elf_hdr64_from_hdr32(ELF_Hdr32 h32)
{
ELF_Hdr64 h64 = {0};
MemoryCopy(h64.e_ident, h32.e_ident, sizeof(h64.e_ident));
h64.e_type = h32.e_type;
h64.e_machine = h32.e_machine;
h64.e_version = h32.e_version;
h64.e_entry = (U64)h32.e_entry;
h64.e_phoff = (U64)h32.e_phoff;
h64.e_shoff = (U64)h32.e_shoff;
h64.e_flags = h32.e_flags;
h64.e_ehsize = h32.e_ehsize;
h64.e_phentsize = h32.e_phentsize;
h64.e_phnum = h32.e_phnum;
h64.e_shentsize = h32.e_shentsize;
h64.e_shnum = h32.e_shnum;
h64.e_shstrndx = h32.e_shstrndx;
return h64;
}
internal ELF_Shdr64
elf_shdr64_from_shdr32(ELF_Shdr32 h32)
{
ELF_Shdr64 h64 = {0};
h64.sh_name = h32.sh_name;
h64.sh_type = h32.sh_type;
h64.sh_flags = (U64)h32.sh_flags;
h64.sh_addr = (U64)h32.sh_addr;
h64.sh_offset = (U64)h32.sh_offset;
h64.sh_size = (U64)h32.sh_size;
h64.sh_link = h32.sh_link;
h64.sh_info = h32.sh_info;
h64.sh_addralign = (U64)h32.sh_addralign;
h64.sh_entsize = (U64)h32.sh_entsize;
return h64;
}
internal ELF_Phdr64
elf_phdr64_from_phdr32(ELF_Phdr32 h32)
{
ELF_Phdr64 h64 = {0};
h64.p_type = h32.p_type;
h64.p_flags = h32.p_flags;
h64.p_offset = (U64)h32.p_offset;
h64.p_vaddr = (U64)h32.p_vaddr;
h64.p_paddr = (U64)h32.p_paddr;
h64.p_filesz = (U64)h32.p_filesz;
h64.p_memsz = (U64)h32.p_memsz;
h64.p_align = (U64)h32.p_align;
return h64;
}
internal ELF_Dyn64
elf_dyn64_from_dyn32(ELF_Dyn32 h32)
{
ELF_Dyn64 h64 = {0};
h64.tag = (U64)h32.tag;
h64.val = (U64)h32.val;
return h64;
}
internal ELF_Sym64
elf_sym64_from_sym32(ELF_Sym32 sym32)
{
ELF_Sym64 sym64 = {0};
sym64.st_name = sym32.st_name;
sym64.st_value = sym32.st_value;
sym64.st_size = sym32.st_size;
sym64.st_info = sym32.st_info;
sym64.st_other = sym32.st_other;
sym64.st_shndx = sym32.st_shndx;
return sym64;
}
internal ELF_Rel64
elf_rel64_from_rel32(ELF_Rel32 rel32)
{
U32 sym = ELF32_R_SYM(rel32.r_info);
U32 type = ELF32_R_TYPE(rel32.r_info);
ELF_Rel64 rel64 = {0};
rel64.r_info = ELF64_R_INFO(sym, type);
rel64.r_offset = rel32.r_offset;
return rel64;
}
internal ELF_Rela64
elf_rela64_from_rela32(ELF_Rela32 rela32)
{
U32 sym = ELF32_R_SYM(rela32.r_info);
U32 type = ELF32_R_TYPE(rela32.r_info);
ELF_Rela64 rela64 = {0};
rela64.r_offset = rela32.r_info;
rela64.r_info = ELF64_R_INFO(sym, type);
rela64.r_addend = rela32.r_addend;
return rela64;
}
internal ELF_Chdr64
elf_chdr64_from_chdr32(ELF_Chdr32 chdr32)
{
ELF_Chdr64 chdr64 = {0};
chdr64.ch_type = chdr32.ch_type;
chdr64.ch_size = chdr32.ch_size;
chdr64.ch_addr_align = chdr32.ch_addr_align;
return chdr64;
}
////////////////////////////////
internal String8
elf_string_from_class(Arena *arena, ELF_Class v)
{
switch (v) {
case ELF_Class_None: return str8_lit("None");
case ELF_Class_32: return str8_lit("32Bit");
case ELF_Class_64: return str8_lit("64Bit");
}
return push_str8f(arena, "%#x", v);
}
////////////////////////////////
internal Arch
arch_from_elf_machine(ELF_MachineKind e_machine)
{
Arch arch = Arch_Null;
switch (e_machine) {
case ELF_MachineKind_None: arch = Arch_Null; break;
case ELF_MachineKind_AARCH64: arch = Arch_arm32; break;
case ELF_MachineKind_ARM: arch = Arch_arm32; break;
case ELF_MachineKind_386: arch = Arch_x86; break;
case ELF_MachineKind_X86_64: arch = Arch_x64; break;
default: NotImplemented; break;
}
return arch;
}
+996
View File
@@ -0,0 +1,996 @@
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef ELF_H
#define ELF_H
typedef U8 ELF_Class;
enum
{
ELF_Class_None = 0,
ELF_Class_32 = 1,
ELF_Class_64 = 2,
ELF_Class_Count = 3
};
typedef U8 ELF_OsAbi;
enum
{
ELF_OsAbi_None,
ELF_OsAbi_SYSV,
ELF_OsAbi_HPUX,
ELF_OsAbi_NETBSD,
ELF_OsAbi_GNU,
ELF_OsAbi_LINUX,
ELF_OsAbi_SOLARIS,
ELF_OsAbi_IRIX,
ELF_OsAbi_FREEBSD,
ELF_OsAbi_TRU64,
ELF_OsAbi_ARM = 97,
ELF_OsAbi_STANDALONE = 255,
};
typedef U8 ELF_Version;
enum
{
ELF_Version_None,
ELF_Version_Current,
};
typedef U16 ELF_MachineKind;
enum
{
ELF_MachineKind_None = 0,
ELF_MachineKind_M32 = 1,
ELF_MachineKind_SPARC = 2,
ELF_MachineKind_386 = 3,
ELF_MachineKind_68K = 4,
ELF_MachineKind_88K = 5,
ELF_MachineKind_IAMCU = 6,
ELF_MachineKind_860 = 7,
ELF_MachineKind_MIPS = 8,
ELF_MachineKind_S370 = 9,
ELF_MachineKind_MIPS_RS3_LE = 10,
// 11-14 reserved
ELF_MachineKind_PARISC = 15,
// 16 reserved
ELF_MachineKind_VPP500 = 17,
ELF_MachineKind_SPARC32PLUS = 18,
// nick: Sun's "v8plus"
ELF_MachineKind_INTEL960 = 19,
ELF_MachineKind_PPC = 20,
ELF_MachineKind_PPC64 = 21,
ELF_MachineKind_S390 = 22,
ELF_MachineKind_SPU = 23,
// 24-35 reserved
ELF_MachineKind_V800 = 36,
ELF_MachineKind_FR20 = 37,
ELF_MachineKind_RH32 = 38,
ELF_MachineKind_MCORE = 39,
ELF_MachineKind_ARM = 40,
ELF_MachineKind_SH = 42,
ELF_MachineKind_ALPHA = 41,
ELF_MachineKind_SPARCV9 = 43,
ELF_MachineKind_TRICORE = 44,
ELF_MachineKind_ARC = 45,
ELF_MachineKind_H8_300 = 46,
ELF_MachineKind_H8_300H = 47,
ELF_MachineKind_H8S = 48,
ELF_MachineKind_H8_500 = 49,
ELF_MachineKind_IA_64 = 50,
ELF_MachineKind_MIPS_X = 51,
ELF_MachineKind_COLDFILE = 52,
ELF_MachineKind_68HC12 = 53,
ELF_MachineKind_MMA = 54,
ELF_MachineKind_PCP = 55,
ELF_MachineKind_NCPU = 56,
ELF_MachineKind_NDR1 = 57,
ELF_MachineKind_STARCORE = 58,
ELF_MachineKind_ME16 = 59,
ELF_MachineKind_ST100 = 60,
ELF_MachineKind_TINYJ = 61,
ELF_MachineKind_X86_64 = 62,
ELF_MachineKind_AARCH64 = 183,
ELF_MachineKind_TI_C6000 = 140,
ELF_MachineKind_L1OM = 180,
ELF_MachineKind_K1OM = 181,
ELF_MachineKind_RISCV = 243,
ELF_MachineKind_S390_OLD = 0xA390,
};
typedef U8 ELF_Data;
enum
{
ELF_Data_None = 0,
ELF_Data_2LSB = 1,
ELF_Data_2MSB = 2,
};
typedef U32 ELF_PType;
enum
{
ELF_PType_Null = 0,
ELF_PType_Load = 1,
ELF_PType_Dynamic = 2,
ELF_PType_Interp = 3,
ELF_PType_Note = 4,
ELF_PType_ShLib = 5,
ELF_PType_PHdr = 6,
ELF_PType_Tls = 7,
ELF_PType_LoOs = 0x60000000,
ELF_PType_HiOs = 0x6fffffff,
ELF_PType_LowProc = 0x70000000,
ELF_PType_HighProc = 0x7fffffff,
// specific to Sun
ELF_PType_LowSunW = 0x6ffffffa,
ELF_PType_SunWBSS = 0x6ffffffb,
ELF_PType_GnuEHFrame = 0x6474E550,
ELF_PType_GnuStack = ELF_PType_LoOs + 0x474e550, // frame unwind information
ELF_PType_GnuRelro = ELF_PType_LoOs + 0x474e551, // stack flags
ELF_PType_GnuProperty = ELF_PType_LoOs + 0x474e552, // read-only after relocations
ELF_PType_SunEHFrame = ELF_PType_GnuEHFrame,
};
typedef U32 ELF_PFlag;
enum
{
ELF_PFlag_Exec = (1 << 0),
ELF_PFlag_Write = (1 << 1),
ELF_PFlag_Read = (1 << 2),
};
typedef U32 ELF_SectionCode;
enum
{
ELF_SectionCode_Null = 0,
ELF_SectionCode_ProgBits = 1,
ELF_SectionCode_Symtab = 2,
ELF_SectionCode_Strtab = 3,
ELF_SectionCode_Rela = 4,
ELF_SectionCode_Hash = 5,
ELF_SectionCode_Dynamic = 6,
ELF_SectionCode_Note = 7,
ELF_SectionCode_NoBits = 8,
ELF_SectionCode_Rel = 9,
ELF_SectionCode_Shlib = 10,
ELF_SectionCode_Dynsym = 11,
ELF_SectionCode_InitArray = 14,
ELF_SectionCode_FiniArray = 15, // Array of ptrs to init functions
ELF_SectionCode_PreinitArray = 16, // Array of ptrs to finish functions
ELF_SectionCode_Group = 17, // Array of ptrs to pre-init funcs
ELF_SectionCode_SymtabShndx = 18, // Section contains a section group
ELF_SectionCode_GNU_IncrementalInputs = 0x6fff4700, // Indices for SHN_XINDEX entries
ELF_SectionCode_GNU_Attributes = 0x6ffffff5, // Incremental build data
ELF_SectionCode_GNU_Hash = 0x6ffffff6, // Object attributes
ELF_SectionCode_GNU_LibList = 0x6ffffff7, // GNU style symbol hash table
ELF_SectionCode_SUNW_verdef = 0x6ffffffd,
ELF_SectionCode_SUNW_verneed = 0x6ffffffe, // Versions defined by file
ELF_SectionCode_SUNW_versym = 0x6fffffff, // Versions needed by file
// Symbol versions
ELF_SectionCode_GNU_verdef = ELF_SectionCode_SUNW_verdef,
ELF_SectionCode_GNU_verneed = ELF_SectionCode_SUNW_verneed,
ELF_SectionCode_GNU_versym = ELF_SectionCode_SUNW_versym,
ELF_SectionCode_Proc,
ELF_SectionCode_User,
};
typedef U32 ELF_SectionIndex;
enum
{
ELF_SectionIndex_Undef = 0, // Symbol with section index is undefined and must be resolved by the link editor
ELF_SectionIndex_Abs = 0xfff1, // Symbol has absolute value and wont change after relocations
ELF_SectionIndex_Common = 0xfff2, // This symbol indicates to linker to allocate the storage at address multiple of st_value
ELF_SectionIndex_LoReserve = 0xff00,
ELF_SectionIndex_HiReserve = 0xffff,
// Processor specific
ELF_SectionIndex_LoProc = ELF_SectionIndex_LoReserve,
ELF_SectionIndex_HiProc = 0xff1f,
// Reserved for OS
ELF_SectionIndex_LoOs = 0xff20,
ELF_SectionIndex_HiOs = 0xff3f,
ELF_SectionIndex_IA64_ASNI_Common = ELF_SectionIndex_LoProc,
ELF_SectionIndex_X8664_LCommon = 0xff02,
ELF_SectionIndex_MIPS_SCommon = 0xff03,
ELF_SectionIndex_TIC6X_Common = ELF_SectionIndex_LoReserve,
ELF_SectionIndex_MIPS_SUndefined = 0xff04,
};
typedef U32 ELF_SectionFlag;
enum
{
ELF_Shf_Write = (1 << 0),
ELF_Shf_Alloc = (1 << 1),
ELF_Shf_ExecInstr = (1 << 2),
ELF_Shf_Merge = (1 << 4),
ELF_Shf_Strings = (1 << 5),
ELF_Shf_InfoLink = (1 << 6),
ELF_Shf_LinkOrder = (1 << 7),
ELF_Shf_OsNonConforming = (1 << 8),
ELF_Shf_Group = (1 << 9),
ELF_Shf_Tls = (1 << 10),
ELF_Shf_Compressed = (1 << 11),
ELF_Shf_MaskOs_Shift = 16, ELF_Shf_MaskOs_Mask = 0xff,
ELF_Shf_AMD64Large = (1 << 28),
ELF_Shf_Ordered = (1 << 30),
ELF_Shf_Exclude = (1 << 31),
ELF_Shf_MaskProc_Shift = 28, ELF_Shf_MaskProc_Mask = 0xf,
};
#define ELF_SectionFlag_Extract_MaskOs(f) (U8)(((f) >> ELF_SectionFlag_MaskOs_Shift) & ELF_SectionFlag_MaskOs_Mask)
#define ELF_SectionFlag_Extract_MaskProc(f) (U8)(((f) >> ELF_SectionFlag_MaskProc_shift) & ELF_SectionFlag_MaskProc_Mask)
typedef U32 ELF_AuxType;
enum
{
ELF_AuxType_Null = 0,
ELF_AuxType_Phdr = 3, // program headers
ELF_AuxType_Phent = 4, // size of a program header
ELF_AuxType_Phnum = 5, // number of program headers
ELF_AuxType_Pagesz = 6, // system page size
ELF_AuxType_Base = 7, // interpreter base address
ELF_AuxType_Flags = 8,
ELF_AuxType_Entry = 9, // program entry point
ELF_AuxType_Uid = 11,
ELF_AuxType_Euid = 12,
ELF_AuxType_Gid = 13,
ELF_AuxType_Egid = 14,
ELF_AuxType_Platform = 15,
ELF_AuxType_Hwcap = 16,
ELF_AuxType_Clktck = 17,
ELF_AuxType_DCacheBSize = 19,
ELF_AuxType_ICacheBSize = 20,
ELF_AuxType_UCacheBSize = 21,
ELF_AuxType_IgnorePPC = 22,
ELF_AuxType_Secure = 23,
ELF_AuxType_BasePlatform = 24,
ELF_AuxType_Random = 25,
ELF_AuxType_Hwcap2 = 26, // addres to 16 random bytes
ELF_AuxType_ExecFn = 31,
ELF_AuxType_SysInfo = 32, // file name of executable
ELF_AuxType_SysInfoEhdr = 33,
ELF_AuxType_L1I_CacheSize = 40,
ELF_AuxType_L1I_CacheGeometry = 41,
ELF_AuxType_L1D_CacheSize = 42,
ELF_AuxType_L1D_CacheGeometry = 43,
ELF_AuxType_L2_CacheSize = 44,
ELF_AuxType_L2_CacheGeometry = 45,
ELF_AuxType_L3_CacheSize = 46,
ELF_AuxType_L3_CacheGeometry = 47,
};
typedef U32 ELF_DynTag;
enum
{
ELF_DynTag_Null = 0,
ELF_DynTag_Needed = 1,
ELF_DynTag_PltRelsz = 2,
ELF_DynTag_PltGot = 3,
ELF_DynTag_Hash = 4,
ELF_DynTag_Strtab = 5,
ELF_DynTag_Symtab = 6,
ELF_DynTag_Rela = 7,
ELF_DynTag_Relasz = 8,
ELF_DynTag_Relaent = 9,
ELF_DynTag_Strsz = 10,
ELF_DynTag_Syment = 11,
ELF_DynTag_Init = 12,
ELF_DynTag_Fini = 13,
ELF_DynTag_SoName = 14,
ELF_DynTag_RPath = 15,
ELF_DynTag_Symbolic = 16,
ELF_DynTag_Rel = 17,
ELF_DynTag_Relsz = 18,
ELF_DynTag_Relent = 19,
ELF_DynTag_Pltrel = 20,
ELF_DynTag_Debug = 21,
ELF_DynTag_TextRel = 22,
ELF_DynTag_JmpRel = 23,
ELF_DynTag_BindNow = 24,
ELF_DynTag_InitArray = 25,
ELF_DynTag_FiniArray = 26,
ELF_DynTag_InitArraysz = 27,
ELF_DynTag_FIniArraysz = 28,
ELF_DynTag_RunPath = 29,
ELF_DynTag_Flags = 30,
ELF_DynTag_PreInitArray = 32,
ELF_DynTag_PreInitArraysz = 33,
ELF_DynTag_SymtabShndx = 34,
ELF_DynTag_LoOs = 0x6000000D,
ELF_DynTag_HiOs = 0x6ffff000,
ELF_DynTag_ValRngLo = 0x6ffffd00,
ELF_DynTag_GNU_PreLinked = 0x6ffffdf5,
ELF_DynTag_GNU_Conflictsz = 0x6ffffdf6,
ELF_DynTag_GNU_LibListsz = 0x6ffffdf7,
ELF_DynTag_Checksum = 0x6ffffdf8,
ELF_DynTag_Pltpadsz = 0x6ffffdf9,
ELF_DynTag_Moveent = 0x6ffffdfa,
ELF_DynTag_Movesz = 0x6ffffdfb,
ELF_DynTag_Feature = 0x6ffffdfc,
ELF_DynTag_PosFlag_1 = 0x6ffffdfd,
ELF_DynTag_SymInSz = 0x6ffffdfe,
ELF_DynTag_SymInEnt = 0x6ffffdff,
ELF_DynTag_ValRngHi = ELF_DynTag_SymInEnt,
ELF_DynTag_AddrRngLo = 0x6ffffe00,
ELF_DynTag_GNU_Hash = 0x6ffffef5,
ELF_DynTag_TlsDescPlt = 0x6ffffef6,
ELF_DynTag_TlsDescGot = 0x6ffffef7,
ELF_DynTag_GNU_Conflict = 0x6ffffef8,
ELF_DynTag_GNU_LibList = 0x6ffffef9,
ELF_DynTag_Config = 0x6ffffefa,
ELF_DynTag_DepAudit = 0x6ffffefb,
ELF_DynTag_Audit = 0x6ffffefc,
ELF_DynTag_PltPad = 0x6ffffefd,
ELF_DynTag_MoveTab = 0x6ffffefe,
ELF_DynTag_SymInfo = 0x6ffffeff,
ELF_DynTag_AddrRngHi = ELF_DynTag_SymInfo,
ELF_DynTag_RelaCount = 0x6ffffff9,
ELF_DynTag_RelCount = 0x6ffffffa,
ELF_DynTag_Flags_1 = 0x6ffffffb,
ELF_DynTag_VerDef = 0x6ffffffc,
ELF_DynTag_VerDefNum = 0x6ffffffd,
ELF_DynTag_VerNeed = 0x6ffffffe,
ELF_DynTag_VerNeedNum = 0x6fffffff,
ELF_DynTag_VerSym = 0x6ffffff0,
ELF_DynTag_LoProc = 0x70000000,
ELF_DynTag_HiProc = 0x7fffffff,
};
typedef U32 ELF_DynFlag;
enum
{
ELF_DynFlag_Origin = (1 << 0),
ELF_DynFlag_Symbolic = (1 << 1),
ELF_DynFlag_TextTel = (1 << 2),
ELF_DynFlag_BindNow = (1 << 3),
ELF_DynFlag_StaticTls = (1 << 4),
};
typedef U32 ELF_DynFeatureFlag;
enum
{
ELF_DynFeatureFlag_ParInit = (1 << 0),
ELF_DynFeatureFlag_ConfExp = (1 << 1),
};
typedef U8 ELF_SymBind;
enum
{
// the same name may exists in multiple files without interfering with each other.
ELF_SymBind_Local = 0,
// Visible to all objects that are linked together.
ELF_SymBind_Global = 1,
// If there is a global symbol with identical name linker doesn't issue an error.
ELF_SymBind_Weak = 2,
ELF_SymBind_LoProc = 13,
ELF_SymBind_HiProc = 15,
};
typedef U8 ELF_SymType;
enum
{
ELF_SymType_NoType = 0,
// Type is not specified.
ELF_SymType_Object = 1,
// Symbol is associated with data object, such as a variable, an array, etc.
ELF_SymType_Func = 2,
// Symbol is associated with a function.
ELF_SymType_Section = 3,
// Symbol is used to relocate sections and normally have LOCAL binding.
ELF_SymType_File = 4,
// Gives name of the source file associated with object.
ELF_SymType_Common = 5,
ELF_SymType_Tls = 6,
ELF_SymType_LoProc = 13,
ELF_SymType_HiProc = 15,
};
typedef U8 ELF_SymVisibility;
enum
{
ELF_SymVisibility_Default = 0,
ELF_SymVisibility_Internal = 1,
ELF_SymVisibility_Hidden = 2,
ELF_SymVisibility_Protected = 3,
};
typedef U32 ELF_RelocI386;
enum
{
ELF_RelocI386_None = 0,
ELF_RelocI386_32 = 1,
ELF_RelocI386_PC32 = 2,
ELF_RelocI386_GOT32 = 3,
ELF_RelocI386_PLT32 = 4,
ELF_RelocI386_Copy = 5,
ELF_RelocI386_GlobDat = 6,
ELF_RelocI386_JumpSlot = 7,
ELF_RelocI386_Relative = 8,
ELF_RelocI386_GotOff = 9,
ELF_RelocI386_GotPc = 10,
ELF_RelocI386_32Plt = 11,
ELF_RelocI386_Tls_tpoff = 14,
ELF_RelocI386_Tls_ie = 15,
ELF_RelocI386_Tls_gotie = 16,
ELF_RelocI386_Tls_le = 17,
ELF_RelocI386_Tls_gd = 18,
ELF_RelocI386_Tls_ldm = 19,
ELF_RelocI386_16 = 20,
ELF_RelocI386_PC16 = 21,
ELF_RelocI386_8 = 22,
ELF_RelocI386_Pc8 = 23,
ELF_RelocI386_TlsGd32 = 24,
ELF_RelocI386_TlsGdPush = 25,
ELF_RelocI386_TlsGdCall = 26,
ELF_RelocI386_TlsGdPop = 27,
ELF_RelocI386_TlsLdm32 = 28,
ELF_RelocI386_TlsLdmPush = 29,
ELF_RelocI386_TlsLdmCall = 30,
ELF_RelocI386_TlsLdmPop = 31,
ELF_RelocI386_TlsLdo32 = 32,
ELF_RelocI386_TlsIe32 = 33,
ELF_RelocI386_TlsLe32 = 34,
ELF_RelocI386_TlsDtpmod32 = 35,
ELF_RelocI386_TlsDtpoff32 = 36,
ELF_RelocI386_TlsTpoff32 = 37,
// 38 is not taken
ELF_RelocI386_TlsGotDesc = 39,
ELF_RelocI386_TlsDescCall = 40,
ELF_RelocI386_TlsDesc = 41,
ELF_RelocI386_IRelative = 42,
ELF_RelocI386_Gotx32x = 43,
ELF_RelocI386_UsedByIntel200 = 200,
ELF_RelocI386_GNU_VTInherit = 250,
ELF_RelocI386_GNU_VTEntry = 251,
};
typedef U32 ELF_RelocX8664;
enum
{
ELF_RelocX8664_None = 0,
ELF_RelocX8664_64 = 1,
ELF_RelocX8664_Pc32 = 2,
ELF_RelocX8664_Got32 = 3,
ELF_RelocX8664_Plt32 = 4,
ELF_RelocX8664_Copy = 5,
ELF_RelocX8664_GlobDat = 6,
ELF_RelocX8664_JumpSlot = 7,
ELF_RelocX8664_Relative = 8,
ELF_RelocX8664_GotPcRel = 9,
ELF_RelocX8664_32 = 10,
ELF_RelocX8664_32S = 11,
ELF_RelocX8664_16 = 12,
ELF_RelocX8664_Pc16 = 13,
ELF_RelocX8664_8 = 14,
ELF_RelocX8664_Pc8 = 15,
ELF_RelocX8664_DtpMod64 = 16,
ELF_RelocX8664_DtpOff64 = 17,
ELF_RelocX8664_TpOff64 = 18,
ELF_RelocX8664_TlsGd = 19,
ELF_RelocX8664_TlsLd = 20,
ELF_RelocX8664_DtpOff32 = 21,
ELF_RelocX8664_GotTpOff = 22,
ELF_RelocX8664_TpOff32 = 23,
ELF_RelocX8664_Pc64 = 24,
ELF_RelocX8664_GotOff64 = 25,
ELF_RelocX8664_GotPc32 = 26,
ELF_RelocX8664_Got64 = 27,
ELF_RelocX8664_GotPcRel64 = 28,
ELF_RelocX8664_GotPc64 = 29,
ELF_RelocX8664_GotPlt64 = 30,
ELF_RelocX8664_PltOff64 = 31,
ELF_RelocX8664_Size32 = 32,
ELF_RelocX8664_Size64 = 33,
ELF_RelocX8664_GotPc32TlsDesc = 34,
ELF_RelocX8664_TlsDescCall = 35,
ELF_RelocX8664_TlsDesc = 36,
ELF_RelocX8664_IRelative = 37,
ELF_RelocX8664_Relative64 = 38,
ELF_RelocX8664_Pc32Bnd = 39,
ELF_RelocX8664_Plt32Bnd = 40,
ELF_RelocX8664_GotPcRelx = 41,
ELF_RelocX8664_RexGotPcRelx = 42,
ELF_RelocX8664_GNU_VTInherit = 250,
ELF_RelocX8664_GNU_VTEntry = 251,
};
typedef U32 ELF_ExternalVerFlag;
enum
{
ELF_ExternalVerFlag_Base = (1 << 0),
ELF_ExternalVerFlag_Weak = (1 << 1),
ELF_ExternalVerFlag_Info = (1 << 2),
};
typedef U32 ELF_NoteType;
enum
{
ELF_NoteType_GNU_Abi = 1,
ELF_NoteType_GNU_HwCap = 2,
ELF_NoteType_GNU_BuildId = 3,
ELF_NoteType_GNU_GoldVersion = 4,
ELF_NoteType_GNU_PropertyType0 = 5,
};
typedef U32 ELF_GnuABITag;
enum
{
ELF_GnuABITag_Linux = 0,
ELF_GnuABITag_Hurd = 1,
ELF_GnuABITag_Solaris = 2,
ELF_GnuABITag_FreeBsd = 3,
ELF_GnuABITag_NetBsd = 4,
ELF_GnuABITag_Syllable = 5,
ELF_GnuABITag_Nacl = 6,
};
typedef S32 ELF_GnuProperty;
enum
{
ELF_GnuProperty_LoProc = 0xc0000000,
// processor-specific range
ELF_GnuProperty_HiProc = 0xdfffffff,
ELF_GnuProperty_LoUser = 0xe0000000,
// application-specific range
ELF_GnuProperty_HiUser = 0xffffffff,
ELF_GnuProperty_StackSize = 1,
ELF_GnuProperty_NoCopyOnProtected = 2,
};
typedef U32 ELF_GnuPropertyX86Isa1;
enum
{
ELF_GnuPropertyX86Isa1_BaseLine = (1 << 0),
ELF_GnuPropertyX86Isa1_V2 = (1 << 1),
ELF_GnuPropertyX86Isa1_V3 = (1 << 2),
ELF_GnuPropertyX86Isa1_V4 = (1 << 3),
};
typedef U32 ELF_GnuPropertyX86Compat1Isa1;
enum
{
ELF_GnuPropertyX86Compat1Isa1_486 = (1 << 0),
ELF_GnuPropertyX86Compat1Isa1_586 = (1 << 1),
ELF_GnuPropertyX86Compat1Isa1_686 = (1 << 2),
ELF_GnuPropertyX86Compat1Isa1_SSE = (1 << 3),
ELF_GnuPropertyX86Compat1Isa1_SSE2 = (1 << 4),
ELF_GnuPropertyX86Compat1Isa1_SSE3 = (1 << 5),
ELF_GnuPropertyX86Compat1Isa1_SSSE3 = (1 << 6),
ELF_GnuPropertyX86Compat1Isa1_SSE4_1 = (1 << 7),
ELF_GnuPropertyX86Compat1Isa1_SSE4_2 = (1 << 8),
ELF_GnuPropertyX86Compat1Isa1_AVX = (1 << 9),
ELF_GnuPropertyX86Compat1Isa1_AVX2 = (1 << 10),
ELF_GnuPropertyX86Compat1Isa1_AVX512F = (1 << 11),
ELF_GnuPropertyX86Compat1Isa1_AVX512ER = (1 << 12),
ELF_GnuPropertyX86Compat1Isa1_AVX512PF = (1 << 13),
ELF_GnuPropertyX86Compat1Isa1_AVX512VL = (1 << 14),
ELF_GnuPropertyX86Compat1Isa1_AVX512DQ = (1 << 15),
ELF_GnuPropertyX86Compat1Isa1_AVX512BW = (1 << 16),
};
typedef U32 ELF_GnuPropertyX86Compat2Isa1;
enum
{
ELF_GnuPropertyX86Compat2Isa1_CMOVE = (1 << 0),
ELF_GnuPropertyX86Compat2Isa1_SSE = (1 << 1),
ELF_GnuPropertyX86Compat2Isa1_SSE2 = (1 << 2),
ELF_GnuPropertyX86Compat2Isa1_SSE3 = (1 << 3),
ELF_GnuPropertyX86Compat2Isa1_SSE4_1 = (1 << 4),
ELF_GnuPropertyX86Compat2Isa1_SSE4_2 = (1 << 5),
ELF_GnuPropertyX86Compat2Isa1_AVX = (1 << 6),
ELF_GnuPropertyX86Compat2Isa1_AVX2 = (1 << 7),
ELF_GnuPropertyX86Compat2Isa1_FMA = (1 << 8),
ELF_GnuPropertyX86Compat2Isa1_AVX512F = (1 << 9),
ELF_GnuPropertyX86Compat2Isa1_AVX512CD = (1 << 10),
ELF_GnuPropertyX86Compat2Isa1_AVX512ER = (1 << 11),
ELF_GnuPropertyX86Compat2Isa1_AVX512PF = (1 << 12),
ELF_GnuPropertyX86Compat2Isa1_AVX512VL = (1 << 13),
ELF_GnuPropertyX86Compat2Isa1_AVX512DQ = (1 << 14),
ELF_GnuPropertyX86Compat2Isa1_AVX512BW = (1 << 15),
ELF_GnuPropertyX86Compat2Isa1_AVX512_4FMAPS = (1 << 16),
ELF_GnuPropertyX86Compat2Isa1_AVX512_4VNNIW = (1 << 17),
ELF_GnuPropertyX86Compat2Isa1_AVX512_BITALG = (1 << 18),
ELF_GnuPropertyX86Compat2Isa1_AVX512_IFMA = (1 << 19),
ELF_GnuPropertyX86Compat2Isa1_AVX512_VBMI = (1 << 20),
ELF_GnuPropertyX86Compat2Isa1_AVX512_VBMI2 = (1 << 21),
ELF_GnuPropertyX86Compat2Isa1_AVX512_VNNI = (1 << 22),
ELF_GnuPropertyX86Compat2Isa1_AVX512_BF16 = (1 << 23),
};
typedef S32 ELF_GnuPropertyX86;
enum
{
ELF_GnuPropertyX86_Feature1And = 0xc0000002,
ELF_GnuPropertyX86_Feature2Used = 0xc0010001,
ELF_GnuPropertyX86_Isa1needed = 0xc0008002,
ELF_GnuPropertyX86_Isa2Needed = 0xc0008001,
ELF_GnuPropertyX86_Isa1Used = 0xc0010002,
ELF_GnuPropertyX86_Compat_isa_1_used = 0xc0000000,
ELF_GnuPropertyX86_Compat_isa_1_needed = 0xc0000001,
ELF_GnuPropertyX86_UInt32AndLo = ELF_GnuPropertyX86_Feature1And,
ELF_GnuPropertyX86_UInt32AndHi = 0xc0007fff,
ELF_GnuPropertyX86_UInt32OrLo = 0xc0008000,
ELF_GnuPropertyX86_UInt32OrHi = 0xc000ffff,
ELF_GnuPropertyX86_UInt32OrAndLo = 0xc0010000,
ELF_GnuPropertyX86_UInt32OrAndHi = 0xc0017fff,
};
typedef U32 ELF_GnuPropertyX86Feature1;
enum
{
ELF_GnuPropertyX86Feature1_Ibt = (1 << 0),
ELF_GnuPropertyX86Feature1_Shstk = (1 << 1),
ELF_GnuPropertyX86Feature1_LamU48 = (1 << 2),
ELF_GnuPropertyX86Feature1_LamU57 = (1 << 3),
};
typedef U32 ELF_GnuPropertyX86Feature2;
enum
{
ELF_GnuPropertyX86Feature2_X86 = (1 << 0),
ELF_GnuPropertyX86Feature2_X87 = (1 << 1),
ELF_GnuPropertyX86Feature2_MMX = (1 << 2),
ELF_GnuPropertyX86Feature2_XMM = (1 << 3),
ELF_GnuPropertyX86Feature2_YMM = (1 << 4),
ELF_GnuPropertyX86Feature2_ZMM = (1 << 5),
ELF_GnuPropertyX86Feature2_FXSR = (1 << 6),
ELF_GnuPropertyX86Feature2_XSAVE = (1 << 7),
ELF_GnuPropertyX86Feature2_XSAVEOPT = (1 << 8),
ELF_GnuPropertyX86Feature2_XSAVEC = (1 << 9),
ELF_GnuPropertyX86Feature2_TMM = (1 << 10),
ELF_GnuPropertyX86Feature2_MASK = (1 << 11),
};
#define ELF_HdrIs64Bit(e_ident) (e_ident[ELF_Identifier_Class] == ELF_Class_64)
#define ELF_HdrIs32Bit(e_ident) (e_ident[ELF_Identifier_Class] == ELF_Class_32)
typedef enum ELF_Identifier
{
ELF_Identifier_Mag0 = 0,
ELF_Identifier_Mag1 = 1,
ELF_Identifier_Mag2 = 2,
ELF_Identifier_Mag3 = 3,
ELF_Identifier_Class = 4,
ELF_Identifier_Data = 5,
ELF_Identifier_Version = 6,
ELF_Identifier_OsAbi = 7,
ELF_Identfiier_AbiBersion = 8,
ELF_Identifier_Max = 16,
} ELF_Identifier;
typedef U16 ELF_Type;
typedef enum ELF_TypeEnum
{
ELF_Type_None = 0,
ELF_Type_Rel = 1,
ELF_Type_Exec = 2,
ELF_Type_Dyn = 3,
ELF_Type_Core = 4,
ELF_Type_LoOs = 0xfe00,
ELF_Type_HiOs = 0xfeff,
ELF_Type_LoProc = 0xff00,
ELF_Type_HiProc = 0xffff,
} ELF_TypeEnum;
typedef struct ELF_Hdr64
{
U8 e_ident[ELF_Identifier_Max];
ELF_Type e_type;
ELF_MachineKind e_machine;
U32 e_version;
U64 e_entry;
U64 e_phoff;
U64 e_shoff;
U32 e_flags;
U16 e_ehsize;
U16 e_phentsize;
U16 e_phnum;
U16 e_shentsize;
U16 e_shnum;
U16 e_shstrndx;
} ELF_Hdr64;
typedef struct ELF_Hdr32
{
U8 e_ident[ELF_Identifier_Max];
ELF_Type e_type;
ELF_MachineKind e_machine;
U32 e_version;
U32 e_entry;
U32 e_phoff;
U32 e_shoff;
U32 e_flags;
U16 e_ehsize;
U16 e_phentsize;
U16 e_phnum;
U16 e_shentsize;
U16 e_shnum;
U16 e_shstrndx;
} ELF_Hdr32;
typedef struct ELF_Shdr64
{
U32 sh_name;
U32 sh_type;
U64 sh_flags;
U64 sh_addr;
U64 sh_offset;
U64 sh_size;
U32 sh_link;
U32 sh_info;
U64 sh_addralign;
U64 sh_entsize;
} ELF_Shdr64;
typedef struct ELF_Shdr32
{
U32 sh_name;
U32 sh_type;
U32 sh_flags;
U32 sh_addr;
U32 sh_offset;
U32 sh_size;
U32 sh_link;
U32 sh_info;
U32 sh_addralign;
U32 sh_entsize;
} ELF_Shdr32;
typedef struct ELF_Phdr64
{
U32 p_type;
U32 p_flags;
U64 p_offset;
U64 p_vaddr;
U64 p_paddr;
U64 p_filesz;
U64 p_memsz;
U64 p_align;
} ELF_Phdr64;
typedef struct ELF_Phdr32
{
U32 p_type;
U32 p_offset;
U32 p_vaddr;
U32 p_paddr;
U32 p_filesz;
U32 p_memsz;
U32 p_flags;
U32 p_align;
} ELF_Phdr32;
////////////////////////////////
// Auxiliary Vectors
// these appear in /proc/<pid>/auxv of a process, they are not in elf files
typedef struct ELF_Auxv32
{
U32 a_type;
U32 a_val;
} ELF_Auxv32;
typedef struct ELF_Auxv64
{
U64 a_type;
U64 a_val;
} ELF_Auxv64;
////////////////////////////////
// Dynamic Structures
// these appear in the virtual address space of a process, they are not in elf files
typedef struct ELF_Dyn32
{
U32 tag;
U32 val;
} ELF_Dyn32;
typedef struct ELF_Dyn64
{
U64 tag;
U64 val;
} ELF_Dyn64;
typedef struct ELF_LinkMap32
{
U32 base;
U32 name;
U32 ld;
U32 next;
} ELF_LinkMap32;
typedef struct ELF_LinkMap64
{
U64 base;
U64 name;
U64 ld;
U64 next;
} ELF_LinkMap64;
////////////////////////////////
// Imports and Exports
typedef struct
{
U32 st_name; // Holds index into files string table.
U32 st_value; // Depending on the context, this may be address, size, etc.
U32 st_size; // Data size in bytes. Zero when size is unknown.
U8 st_info; // Contains symbols type and binding.
U8 st_other; // Reserved for future use, currenly zero.
U16 st_shndx; // Section index to which symbol is relevant.
} ELF_Sym32;
typedef struct
{
U32 st_name;
U8 st_info;
U8 st_other;
U16 st_shndx;
U64 st_value;
U64 st_size;
} ELF_Sym64;
#define ELF_ST_INFO(b,t) (((b) << 4) + ((t) & 0xF))
#define ELF_ST_BIND(x) ((x) >> 4)
#define ELF_ST_TYPE(x) ((x) & 0xF)
#define ELF_ST_VISIBILITY(v) ((v) & 0x3)
typedef struct
{
U32 r_offset;
U32 r_info;
} ELF_Rel32;
typedef struct
{
U32 r_offset;
U32 r_info;
S32 r_addend;
} ELF_Rela32;
typedef struct
{
U64 r_offset;
U64 r_info;
} ELF_Rel64;
typedef struct
{
U64 r_offset;
U64 r_info;
S64 r_addend;
} ELF_Rela64;
#define ELF32_R_SYM(x) ((x) >> 8)
#define ELF32_R_TYPE(x) ((x) & 0xFF)
#define ELF64_R_INFO(s,t) (((U64)(s) << 32) | (U64)t)
#define ELF64_R_SYM(x) ((x) >> 32)
#define ELF64_R_TYPE(x) ((x) & 0xffffffff)
// This flag is set to indicate that symbol is not available outside shared object
#define ELF_EXTERNAL_VERSYM_HIDDEN 0x8000
#define ELF_EXTERNAL_VERSYM_MASK 0x7FFF
// Appears in .gnu.verdef (SHT_GNU_verdef)
typedef struct
{
U16 vd_version;
U16 vd_flags;
U16 vd_ndx;
U16 vd_cnt;
U32 vd_hash;
U32 vd_aux;
U32 vd_next;
} ELF_ExternalVerdef;
// Appears in .gnu.verdef (SHT_GNU_verdef)
typedef struct
{
U32 vda_name;
U32 vda_next;
} ELF_ExternalVerdaux;
// Appears in .gnu.verneed (SHT_GNU_verneed)
typedef struct
{
U16 vn_version;
U16 vn_cnt;
U32 vn_file;
U32 vn_aux;
U32 vn_next;
} ELF_ExternalVerneed;
// Appears in .gnu.verneed (SHT_GNU_verneed)
typedef struct
{
U32 vna_hash;
U16 vna_flags;
U16 vna_other;
U32 vna_name;
U32 vna_next;
} ELF_ExternalVernaux;
// Appears in .gnu.version (SHT_GNU_versym)
typedef struct
{
U16 vs_vers;
} ELF_ExternalVersym;
typedef struct
{
U32 name_size;
U32 desc_size;
U32 type;
// name + desc
// U8 data[1];
} ELF_Note;
////////////////////////////////
// Extensions
typedef U8 ELF_CompressType;
enum ELF_CompressTypeEnum
{
ELF_CompressType_None = 0,
ELF_CompressType_ZLib = 1,
ELF_CompressType_ZStd = 2,
ELF_CompressType_LoOs = 0x60000000,
ELF_CompressType_HiOs = 0x6fffffff,
ELF_CompressType_LoProc = 0x70000000,
ELF_CompressType_HiProc = 0x7fffffff,
};
typedef struct ELF_Chdr32
{
U32 ch_type;
U32 ch_size;
U32 ch_addr_align;
} ELF_Chdr32;
typedef struct ELF_Chdr64
{
U64 ch_type;
U64 ch_size;
U64 ch_addr_align;
} ELF_Chdr64;
////////////////////////////////
internal ELF_Hdr64 elf_hdr64_from_ehdr32(ELF_Hdr32 h32);
internal ELF_Shdr64 elf_shdr64_from_shdr32(ELF_Shdr32 h32);
internal ELF_Phdr64 elf_phdr64_from_phdr32(ELF_Phdr32 h32);
internal ELF_Dyn64 elf_dyn64_from_dyn32 (ELF_Dyn32 h32);
internal ELF_Sym64 elf_sym64_from_sym32 (ELF_Sym32 sym32);
internal ELF_Rel64 elf_rel64_from_rel32 (ELF_Rel32 rel32);
internal ELF_Rela64 elf_rela64_from_rela32(ELF_Rela32 rela32);
internal ELF_Chdr64 elf_chdr64_from_chdr32(ELF_Chdr32 chdr32);
////////////////////////////////
internal String8 elf_string_from_class(Arena *arena, ELF_Class v);
////////////////////////////////
internal Arch arch_from_elf_machine(ELF_MachineKind machine);
#endif // ELF_H
+143
View File
@@ -0,0 +1,143 @@
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal B32
elf_check_magic(String8 data)
{
U8 sig[ELF_Identifier_Max] = {0};
str8_deserial_read(data, 0, &sig[0], sizeof(sig), 1);
B32 is_magic_valid = (sig[ELF_Identifier_Mag0] == 0x7f && sig[ELF_Identifier_Mag1] == 'E' && sig[ELF_Identifier_Mag2] == 'L' && sig[ELF_Identifier_Mag3] == 'F');
return is_magic_valid;
}
internal ELF_BinInfo
elf_bin_from_data(String8 data)
{
ELF_Hdr64 hdr64 = {0};
Rng1U64 sh_name_range = rng_1u64(0,0);
if (elf_check_magic(data)) {
U8 sig[ELF_Identifier_Max] = {0};
str8_deserial_read(data, 0, &sig[0], sizeof(sig), 1);
switch (sig[ELF_Identifier_Class]) {
case ELF_Class_None: break;
case ELF_Class_32: {
ELF_Hdr32 hdr32 = {0};
U64 hdr_size = str8_deserial_read_struct(data, 0, &hdr32);
if (hdr_size == sizeof(hdr32)) {
hdr64 = elf_hdr64_from_hdr32(hdr32);
U64 shstr_off = hdr32.e_shoff + hdr32.e_shentsize*hdr32.e_shstrndx;
ELF_Shdr32 shdr = {0};
U64 shdr_size = str8_deserial_read_struct(data, shstr_off, &shdr);
if (shdr_size == sizeof(shdr)) {
sh_name_range = rng_1u64(shdr.sh_offset, shdr.sh_offset + shdr.sh_size);
}
}
} break;
case ELF_Class_64: {
U64 hdr_size = str8_deserial_read_struct(data, 0, &hdr64);
if (hdr_size == sizeof(hdr64)) {
U64 shstr_off = hdr64.e_shoff + hdr64.e_shentsize*hdr64.e_shstrndx;
ELF_Shdr64 shdr = {0};
U64 shdr_size = str8_deserial_read_struct(data, shstr_off, &shdr);
if (shdr_size == sizeof(shdr)) {
sh_name_range = rng_1u64(shdr.sh_offset, shdr.sh_offset + shdr.sh_size);
}
}
} break;
default: Assert(!"invalid elf header"); break;
}
}
ELF_BinInfo info = {0};
info.hdr = hdr64;
info.sh_name_range = sh_name_range;
return info;
}
internal ELF_Shdr64Array
elf_shdr64_array_from_bin(Arena *arena, String8 raw_data, ELF_Hdr64 *hdr)
{
Rng1U64 shdr_range = rng_1u64(hdr->e_shoff, hdr->e_shoff + hdr->e_shentsize*hdr->e_shnum);
String8 shdr_data = str8_substr(raw_data, shdr_range);
ELF_Shdr64Array result = {0};
result.count = hdr->e_shnum;
result.v = push_array(arena, ELF_Shdr64, hdr->e_shnum);
for(U64 shdr_idx = 0; shdr_idx < hdr->e_shnum; ++shdr_idx) {
switch (hdr->e_ident[ELF_Identifier_Class]) {
case ELF_Class_None: break;
case ELF_Class_32: {
ELF_Shdr32 shdr32 = {0};
str8_deserial_read_struct(shdr_data, shdr_idx * sizeof(ELF_Shdr32), &shdr32);
result.v[shdr_idx] = elf_shdr64_from_shdr32(shdr32);
} break;
case ELF_Class_64: {
str8_deserial_read_struct(shdr_data, shdr_idx * sizeof(ELF_Shdr64), &result.v[shdr_idx]);
} break;
default: InvalidPath; break;
}
}
return result;
}
internal String8
elf_name_from_shdr64(String8 raw_data, ELF_Hdr64 *hdr, Rng1U64 sh_name_range, ELF_Shdr64 *shdr)
{
String8 sh_names = str8_substr(raw_data, sh_name_range);
String8 name = {0};
str8_deserial_read_cstr(sh_names, shdr->sh_name, &name);
return name;
}
internal U64
elf_base_addr_from_bin(ELF_Hdr64 *hdr)
{
NotImplemented;
return 0;
}
internal B32
elf_parse_debug_link(String8 raw_data, ELF_BinInfo *elf, ELF_GnuDebugLink *debug_link_out)
{
Temp scratch = scratch_begin(0,0);
B32 is_debug_link_present = 0;
ELF_Shdr64Array sections = elf_shdr64_array_from_bin(scratch.arena, raw_data, &elf->hdr);
for (U64 i = 0; i < sections.count; ++i) {
ELF_Shdr64 *shdr = &sections.v[i];
String8 name = elf_name_from_shdr64(raw_data, &elf->hdr, elf->sh_name_range, shdr);
if (str8_match(name, str8_lit(".gnu_debuglink"), 0)) {
Rng1U64 raw_data_range = rng_1u64(shdr->sh_offset, shdr->sh_offset + shdr->sh_size);
String8 data = str8_substr(raw_data, raw_data_range);
String8 path = {0};
U32 checksum = 0;
{
U64 cursor = 0;
cursor += str8_deserial_read_cstr(data, cursor, &path);
cursor = AlignPow2(cursor, 4);
cursor += str8_deserial_read_struct(data, cursor, &checksum);
}
debug_link_out->path = path;
debug_link_out->checksum = checksum;
is_debug_link_present = 1;
break;
}
}
scratch_end(scratch);
return is_debug_link_present;
}
+36
View File
@@ -0,0 +1,36 @@
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef ELF_PARSE_H
#define ELF_PARSE_H
////////////////////////////////
typedef struct ELF_BinInfo
{
ELF_Hdr64 hdr;
Rng1U64 sh_name_range;
} ELF_BinInfo;
typedef struct ELF_Shdr64Array
{
U64 count;
ELF_Shdr64 *v;
} ELF_Shdr64Array;
typedef struct ELF_GnuDebugLink
{
String8 path;
U32 checksum;
} ELF_GnuDebugLink;
////////////////////////////////
internal B32 elf_check_magic(String8 data);
internal ELF_BinInfo elf_bin_from_data(String8 data);
internal ELF_Shdr64Array elf_shdr64_array_from_bin(Arena *arena, String8 raw_data, ELF_Hdr64 *hdr);
internal String8 elf_name_from_shdr64(String8 raw_data, ELF_Hdr64 *hdr, Rng1U64 sh_name_range, ELF_Shdr64 *shdr);
internal U64 elf_base_addr_from_bin(ELF_Hdr64 *hdr);
#endif // ELF_PARSE_H
+111 -102
View File
@@ -26,32 +26,32 @@ E_TypeKindTable:
{UChar8 "uchar8" 1 }
{UChar16 "uchar16" 2 }
{UChar32 "uchar32" 4 }
{U8 "U8" 1 }
{U16 "U16" 2 }
{U32 "U32" 4 }
{U64 "U64" 8 }
{U128 "U128" 16 }
{U256 "U256" 32 }
{U512 "U512" 64 }
{S8 "S8" 1 }
{S16 "S16" 2 }
{S32 "S32" 4 }
{S64 "S64" 8 }
{S128 "S128" 16 }
{S256 "S256" 32 }
{S512 "S512" 64 }
{U8 "uint8" 1 }
{U16 "uint16" 2 }
{U32 "uint32" 4 }
{U64 "uint64" 8 }
{U128 "uint128" 16 }
{U256 "uint256" 32 }
{U512 "uint512" 64 }
{S8 "int8" 1 }
{S16 "int16" 2 }
{S32 "int32" 4 }
{S64 "int64" 8 }
{S128 "int128" 16 }
{S256 "int256" 32 }
{S512 "int512" 64 }
{Bool "bool" 1 }
{F16 "F16" 2 }
{F32 "F32" 4 }
{F32PP "F32PP" 4 }
{F48 "F48" 6 }
{F64 "F64" 8 }
{F80 "F80" 10 }
{F128 "F128" 16 }
{ComplexF32 "ComplexF32" 8 }
{ComplexF64 "ComplexF64" 16 }
{ComplexF80 "ComplexF80" 20 }
{ComplexF128 "ComplexF128" 32 }
{F16 "float16" 2 }
{F32 "float32" 4 }
{F32PP "float32PP" 4 }
{F48 "float48" 6 }
{F64 "float64" 8 }
{F80 "float80" 10 }
{F128 "float128" 16 }
{ComplexF32 "complex_float32" 8 }
{ComplexF64 "complex_float64" 16 }
{ComplexF80 "complex_float80" 20 }
{ComplexF128 "complex_float128" 32 }
{Modifier "modifier" 0 }
{Ptr "ptr" 0 }
{LRef "lref" 0 }
@@ -71,68 +71,75 @@ E_TypeKindTable:
{IncompleteEnum "enum" 0 }
{Bitfield "bitfield" 0 }
{Variadic "variadic" 0 }
{Collection "collection" 0 }
{Set "set" 0 }
{Lens "lens" 0 }
{LensSpec "lens_spec" 0 }
{MetaExpr "meta_expr" 0 }
{MetaDisplayName "meta_display_name" 0 }
{MetaDescription "meta_description" 0 }
}
@table(name op_kind precedence string op_pre op_sep op_pos)
@table(name op_kind precedence op_pre op_sep op_pos op_chain)
E_ExprKindTable:
{
{ Nil Null 0 "" "" "" "" }
{ Ref Null 0 "" "" "" "" }
{ Nil Null 0 "" "" "" "" }
{ Ref Null 0 "" "" "" "" }
{ ArrayIndex Null 0 "[]" "" "[" "]"}
{ MemberAccess Null 0 "." "" "." "" }
{ Deref UnaryPrefix 2 "*" "*" "" "" }
{ Address UnaryPrefix 2 "&" "&" "" "" }
{ ArrayIndex Null 0 "" "[" "]" "" }
{ MemberAccess Null 0 "" "." "" "" }
{ Deref UnaryPrefix 2 "*" "" "" "" }
{ Address UnaryPrefix 2 "&" "" "" "" }
{ Cast Null 1 "cast" "(" ")" "" }
{ Sizeof UnaryPrefix 1 "sizeof" "sizeof" "(" ")"}
{ Typeof UnaryPrefix 1 "typeof" "typeof" "(" ")"}
{ ByteSwap UnaryPrefix 1 "bswap" "bswap" "(" ")"}
{ Cast Null 1 "cast(" ")" "" "" }
{ Sizeof UnaryPrefix 1 "sizeof " "" "" "" }
{ Typeof UnaryPrefix 1 "typeof " "" "" "" }
{ ByteSwap UnaryPrefix 1 "bswap " "" "" "" }
{ Pos UnaryPrefix 2 "+" "+" "" "" }
{ Neg UnaryPrefix 2 "-" "-" "" "" }
{ LogNot UnaryPrefix 2 "!" "!" "" "" }
{ BitNot UnaryPrefix 2 "~" "~" "" "" }
{ Mul Binary 3 "*" "" "*" "" }
{ Div Binary 3 "/" "" "/" "" }
{ Mod Binary 3 "%" "" "%" "" }
{ Add Binary 4 "+" "" "+" "" }
{ Sub Binary 4 "-" "" "-" "" }
{ LShift Binary 5 "<<" "" "<<" "" }
{ RShift Binary 5 ">>" "" ">>" "" }
{ Less Binary 6 "<" "" "<" "" }
{ LsEq Binary 6 "<=" "" "<=" "" }
{ Grtr Binary 6 ">" "" ">" "" }
{ GrEq Binary 6 ">=" "" ">=" "" }
{ EqEq Binary 7 "==" "" "==" "" }
{ NtEq Binary 7 "!=" "" "!=" "" }
{ Pos UnaryPrefix 2 "+" "" "" "" }
{ Neg UnaryPrefix 2 "-" "" "" "" }
{ LogNot UnaryPrefix 2 "!" "" "" "" }
{ BitNot UnaryPrefix 2 "~" "" "" "" }
{ Mul Binary 3 "" " * " "" "" }
{ Div Binary 3 "" " / " "" "" }
{ Mod Binary 3 "" " % " "" "" }
{ Add Binary 4 "" " + " "" "" }
{ Sub Binary 4 "" " - " "" "" }
{ LShift Binary 5 "" " << " "" "" }
{ RShift Binary 5 "" " >> " "" "" }
{ Less Binary 6 "" " < " "" "" }
{ LsEq Binary 6 "" " <= " "" "" }
{ Grtr Binary 6 "" " > " "" "" }
{ GrEq Binary 6 "" " >= " "" "" }
{ EqEq Binary 7 "" " == " "" "" }
{ NtEq Binary 7 "" " != " "" "" }
{ BitAnd Binary 8 "&" "" "&" "" }
{ BitXor Binary 9 "^" "" "^" "" }
{ BitOr Binary 10 "|" "" "|" "" }
{ LogAnd Binary 11 "&&" "" "&&" "" }
{ LogOr Binary 12 "||" "" "||" "" }
{ BitAnd Binary 8 "" " & " "" "" }
{ BitXor Binary 9 "" " ^ " "" "" }
{ BitOr Binary 10 "" " | " "" "" }
{ LogAnd Binary 11 "" " && " "" "" }
{ LogOr Binary 12 "" " || " "" "" }
{ Ternary Null 0 "? " "" "?" ":"}
{ Ternary Null 0 "" " ? " "" " : "}
{ LeafBytecode Null 0 "bytecode" "" "" "" }
{ LeafMember Null 0 "member" "" "" "" }
{ LeafStringLiteral Null 0 "string_literal" "" "" "" }
{ LeafBool Null 0 "B32" "" "" "" }
{ LeafU64 Null 0 "U64" "" "" "" }
{ LeafF64 Null 0 "F64" "" "" "" }
{ LeafF32 Null 0 "F32" "" "" "" }
{ LeafIdent Null 0 "leaf_ident" "" "" "" }
{ LeafOffset Null 0 "leaf_offset" "" "" "" }
{ LeafFilePath Null 0 "leaf_filepath" "" "" "" }
{ Call Null 15 "" "(" ")" ", "}
{ TypeIdent Null 0 "type_ident" "" "" "" }
{ Ptr Null 0 "ptr" "" "" "" }
{ Array Null 0 "array" "" "" "" }
{ Func Null 0 "function" "" "" "" }
{ LeafBytecode Null 0 "" "" "" "" }
{ LeafStringLiteral Null 0 "" "" "" "" }
{ LeafU64 Null 0 "" "" "" "" }
{ LeafF64 Null 0 "" "" "" "" }
{ LeafF32 Null 0 "" "" "" "" }
{ LeafIdentifier Null 0 "" "" "" "" }
{ LeafOffset Null 0 "" "" "" "" }
{ LeafValue Null 0 "" "" "" "" }
{ LeafFilePath Null 0 "" "" "" "" }
{ Define Binary 13 "=" "" "=" "" }
{ TypeIdent Null 0 "" "" "" "" }
{ Ptr Null 0 "" "" "" "" }
{ Array Null 0 "" "" "" "" }
{ Func Null 0 "" "" "" "" }
{ Unsigned Null 0 "unsigned " "" "" "" }
{ Define Binary 13 "" " = " "" "" }
}
@table(name display_string)
@@ -157,6 +164,12 @@ E_InterpretationCodeTable:
COUNT,
}
@data(String8)
e_token_kind_strings:
{
@expand(E_TokenKindTable a) `str8_lit_comp("$(a.name)")`
}
@enum E_TypeKind:
{
@expand(E_TypeKindTable a) `$(a.name)`,
@@ -171,6 +184,18 @@ E_InterpretationCodeTable:
`LastSigned2 = E_TypeKind_S512`,
`FirstIncomplete = E_TypeKind_IncompleteStruct`,
`LastIncomplete = E_TypeKind_IncompleteEnum`,
`FirstMeta = E_TypeKind_MetaExpr`,
`LastMeta = E_TypeKind_MetaDescription`,
}
@data(String8) e_type_kind_basic_string_table:
{
@expand(E_TypeKindTable a) `str8_lit_comp("$(a.basic_string)")`;
}
@data(U8) e_type_kind_basic_byte_size_table:
{
@expand(E_TypeKindTable a) `$(a.basic_byte_size)`;
}
@enum(U32) E_ExprKind:
@@ -179,40 +204,24 @@ E_InterpretationCodeTable:
COUNT,
}
@enum E_InterpretationCode:
{
@expand(E_InterpretationCodeTable a) `$(a.name)`,
COUNT,
}
@data(String8)
e_token_kind_strings:
{
@expand(E_TokenKindTable a) `str8_lit_comp("$(a.name)")`
}
@data(String8)
e_expr_kind_strings:
{
@expand(E_ExprKindTable a) `str8_lit_comp("$(a.name)")`
}
@data(E_OpInfo) e_expr_kind_op_info_table:
{
@expand(E_ExprKindTable a) `{ E_OpKind_$(a.op_kind), $(a.precedence), str8_lit_comp("$(a.op_pre)"), str8_lit_comp("$(a.op_sep)"), str8_lit_comp("$(a.op_pos)"), str8_lit_comp("$(a.op_chain)") }`
}
@enum E_InterpretationCode:
{
@expand(E_InterpretationCodeTable a) `$(a.name)`,
COUNT,
}
@data(String8) e_interpretation_code_display_strings:
{
@expand(E_InterpretationCodeTable a) `str8_lit_comp("$(a.display_string)")`
}
@data(E_OpInfo) e_expr_kind_op_info_table:
{
@expand(E_ExprKindTable a) `{ E_OpKind_$(a.op_kind), $(a.precedence), str8_lit_comp("$(a.op_pre)"), str8_lit_comp("$(a.op_sep)"), str8_lit_comp("$(a.op_pos)") }`
}
@data(U8) e_kind_basic_byte_size_table:
{
@expand(E_TypeKindTable a) `$(a.basic_byte_size)`;
}
@data(String8) e_kind_basic_string_table:
{
@expand(E_TypeKindTable a) `str8_lit_comp("$(a.basic_string)")`;
}
-262
View File
@@ -1,262 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Bundled Evaluation Functions
internal E_Eval
e_eval_from_expr(Arena *arena, E_Expr *expr)
{
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(arena, expr);
E_OpList oplist = e_oplist_from_irtree(arena, irtree.root);
String8 bytecode = e_bytecode_from_oplist(arena, &oplist);
E_Interpretation interp = e_interpret(bytecode);
E_Space zero_space = {0};
E_Space space = (MemoryMatchStruct(&zero_space, &irtree.space) ? e_interpret_ctx->primary_space : irtree.space);
E_Eval eval =
{
.value = interp.value,
.mode = irtree.mode,
.space = space,
.expr = expr,
.type_key = irtree.type_key,
.code = interp.code,
};
e_msg_list_concat_in_place(&eval.msgs, &irtree.msgs);
if(E_InterpretationCode_Good < eval.code && eval.code < E_InterpretationCode_COUNT)
{
e_msg(arena, &eval.msgs, E_MsgKind_InterpretationError, 0, e_interpretation_code_display_strings[eval.code]);
}
return eval;
}
internal E_Eval
e_eval_from_string(Arena *arena, String8 string)
{
E_TokenArray tokens = e_token_array_from_text(arena, string);
E_Parse parse = e_parse_expr_from_text_tokens(arena, string, &tokens);
E_Eval eval = e_eval_from_expr(arena, parse.expr);
e_msg_list_concat_in_place(&eval.msgs, &parse.msgs);
return eval;
}
internal E_Eval
e_autoresolved_eval_from_eval(E_Eval eval)
{
if(e_parse_ctx &&
e_interpret_ctx &&
e_parse_ctx->modules_count > 0 &&
e_interpret_ctx->module_base != 0 &&
(e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_S64)) ||
e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_U64)) ||
e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_S32)) ||
e_type_key_match(eval.type_key, e_type_key_basic(E_TypeKind_U32))))
{
U64 vaddr = eval.value.u64;
U64 voff = vaddr - e_interpret_ctx->module_base[0];
RDI_Parsed *rdi = e_parse_ctx->primary_module->rdi;
RDI_Scope *scope = rdi_scope_from_voff(rdi, voff);
RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, voff);
RDI_GlobalVariable *gvar = rdi_global_variable_from_voff(rdi, voff);
U32 string_idx = 0;
if(string_idx == 0) { string_idx = procedure->name_string_idx; }
if(string_idx == 0) { string_idx = gvar->name_string_idx; }
if(string_idx != 0)
{
eval.type_key = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, e_type_key_basic(E_TypeKind_Void), 0);
}
}
return eval;
}
internal E_Eval
e_dynamically_typed_eval_from_eval(E_Eval eval)
{
E_TypeKey type_key = eval.type_key;
E_TypeKind type_kind = e_type_kind_from_key(type_key);
if(e_type_state != 0 &&
e_interpret_ctx != 0 &&
e_interpret_ctx->space_read != 0 &&
e_interpret_ctx->module_base != 0 &&
type_kind == E_TypeKind_Ptr)
{
Temp scratch = scratch_begin(0, 0);
E_TypeKey ptee_type_key = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(type_key)));
E_TypeKind ptee_type_kind = e_type_kind_from_key(ptee_type_key);
if(ptee_type_kind == E_TypeKind_Struct || ptee_type_kind == E_TypeKind_Class)
{
E_Type *ptee_type = e_type_from_key(scratch.arena, ptee_type_key);
B32 has_vtable = 0;
for(U64 idx = 0; idx < ptee_type->count; idx += 1)
{
if(ptee_type->members[idx].kind == E_MemberKind_VirtualMethod)
{
has_vtable = 1;
break;
}
}
if(has_vtable)
{
U64 ptr_vaddr = eval.value.u64;
U64 addr_size = e_type_byte_size_from_key(e_type_unwrap(type_key));
U64 class_base_vaddr = 0;
U64 vtable_vaddr = 0;
if(e_space_read(eval.space, &class_base_vaddr, r1u64(ptr_vaddr, ptr_vaddr+addr_size)) &&
e_space_read(eval.space, &vtable_vaddr, r1u64(class_base_vaddr, class_base_vaddr+addr_size)))
{
Arch arch = e_type_state->ctx->primary_module->arch;
U32 rdi_idx = 0;
RDI_Parsed *rdi = 0;
U64 module_base = 0;
for(U64 idx = 0; idx < e_type_state->ctx->modules_count; idx += 1)
{
if(contains_1u64(e_type_state->ctx->modules[idx].vaddr_range, vtable_vaddr))
{
arch = e_type_state->ctx->modules[idx].arch;
rdi_idx = (U32)idx;
rdi = e_type_state->ctx->modules[idx].rdi;
module_base = e_type_state->ctx->modules[idx].vaddr_range.min;
break;
}
}
if(rdi != 0)
{
U64 vtable_voff = vtable_vaddr - module_base;
U64 global_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_GlobalVMap, vtable_voff);
RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, global_idx);
if(global_var->link_flags & RDI_LinkFlag_TypeScoped)
{
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, global_var->container_idx);
RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx);
E_TypeKey derived_type_key = e_type_key_ext(e_type_kind_from_rdi(type->kind), udt->self_type_idx, rdi_idx);
E_TypeKey ptr_to_derived_type_key = e_type_key_cons_ptr(arch, derived_type_key, 0);
eval.type_key = ptr_to_derived_type_key;
}
}
}
}
}
scratch_end(scratch);
}
return eval;
}
internal E_Eval
e_value_eval_from_eval(E_Eval eval)
{
ProfBeginFunction();
if(eval.mode == E_Mode_Offset)
{
E_TypeKey type_key = e_type_unwrap(eval.type_key);
E_TypeKind type_kind = e_type_kind_from_key(type_key);
if(type_kind == E_TypeKind_Array)
{
eval.mode = E_Mode_Value;
}
else
{
U64 type_byte_size = e_type_byte_size_from_key(type_key);
Rng1U64 value_vaddr_range = r1u64(eval.value.u64, eval.value.u64 + type_byte_size);
MemoryZeroStruct(&eval.value);
if(!e_type_key_match(type_key, e_type_key_zero()) &&
type_byte_size <= sizeof(E_Value) &&
e_space_read(eval.space, &eval.value, value_vaddr_range))
{
eval.mode = E_Mode_Value;
// rjf: mask&shift, for bitfields
if(type_kind == E_TypeKind_Bitfield && type_byte_size <= sizeof(U64))
{
Temp scratch = scratch_begin(0, 0);
E_Type *type = e_type_from_key(scratch.arena, type_key);
U64 valid_bits_mask = 0;
for(U64 idx = 0; idx < type->count; idx += 1)
{
valid_bits_mask |= (1ull<<idx);
}
eval.value.u64 = eval.value.u64 >> type->off;
eval.value.u64 = eval.value.u64 & valid_bits_mask;
eval.type_key = type->direct_type_key;
scratch_end(scratch);
}
// rjf: manually sign-extend
switch(type_kind)
{
default: break;
case E_TypeKind_Char8:
case E_TypeKind_S8: {eval.value.s64 = (S64)*((S8 *)&eval.value.u64);}break;
case E_TypeKind_Char16:
case E_TypeKind_S16: {eval.value.s64 = (S64)*((S16 *)&eval.value.u64);}break;
case E_TypeKind_Char32:
case E_TypeKind_S32: {eval.value.s64 = (S64)*((S32 *)&eval.value.u64);}break;
}
}
}
}
ProfEnd();
return eval;
}
internal E_Eval
e_element_eval_from_array_eval_index(E_Eval eval, U64 index)
{
E_Eval result = {0};
result.mode = eval.mode;
result.space = eval.space;
result.type_key = e_type_direct_from_key(eval.type_key);
result.code = eval.code;
result.msgs = eval.msgs;
U64 element_size = e_type_byte_size_from_key(result.type_key);
switch(eval.mode)
{
default:{}break;
case E_Mode_Value:
if(element_size <= sizeof(E_Value) &&
index < sizeof(E_Value)/element_size)
{
MemoryCopy((U8 *)(&result.value.u512[0]),
(U8 *)(&eval.value.u512[0]) + index*element_size,
element_size);
}break;
case E_Mode_Offset:
{
result.value.u64 = eval.value.u64 + element_size*index;
}break;
}
return result;
}
internal E_Eval
e_member_eval_from_eval_member_name(E_Eval eval, String8 member_name)
{
E_Eval result = {0};
{
E_Member member = e_type_member_from_key_name__cached(eval.type_key, member_name);
if(member.kind != E_MemberKind_Null)
{
result.mode = eval.mode;
result.space = eval.space;
result.type_key = member.type_key;
result.code = eval.code;
result.msgs = eval.msgs;
switch(eval.mode)
{
default:{}break;
case E_Mode_Value:
if(member.off < sizeof(eval.value))
{
U64 member_size = e_type_byte_size_from_key(member.type_key);
MemoryCopy((U8 *)(&result.value.u512[0]),
(U8 *)(&eval.value.u512[0]) + member.off,
Min(member_size, sizeof(eval.value) - member.off));
}break;
case E_Mode_Offset:
{
result.value.u64 = eval.value.u64 + member.off;
}break;
}
}
}
return result;
}
-33
View File
@@ -1,33 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef EVAL_BUNDLES_H
#define EVAL_BUNDLES_H
////////////////////////////////
//~ rjf: Bundled Evaluation Path Types
typedef struct E_Eval E_Eval;
struct E_Eval
{
E_Value value;
E_Mode mode;
E_Space space;
E_Expr *expr;
E_TypeKey type_key;
E_InterpretationCode code;
E_MsgList msgs;
};
////////////////////////////////
//~ rjf: Bundled Evaluation Functions
internal E_Eval e_eval_from_expr(Arena *arena, E_Expr *expr);
internal E_Eval e_eval_from_string(Arena *arena, String8 string);
internal E_Eval e_autoresolved_eval_from_eval(E_Eval eval);
internal E_Eval e_dynamically_typed_eval_from_eval(E_Eval eval);
internal E_Eval e_value_eval_from_eval(E_Eval eval);
internal E_Eval e_element_eval_from_array_eval_index(E_Eval eval, U64 index);
internal E_Eval e_member_eval_from_eval_member_name(E_Eval eval, String8 member_name);
#endif // EVAL_BUNDLES_H
+1336 -8
View File
File diff suppressed because it is too large Load Diff
+1103 -6
View File
File diff suppressed because it is too large Load Diff
-1
View File
@@ -6,4 +6,3 @@
#include "eval/eval_parse.c"
#include "eval/eval_ir.c"
#include "eval/eval_interpret.c"
#include "eval/eval_bundles.c"
-1
View File
@@ -9,6 +9,5 @@
#include "eval/eval_parse.h"
#include "eval/eval_ir.h"
#include "eval/eval_interpret.h"
#include "eval/eval_bundles.h"
#endif // EVAL_INC_H
+64 -12
View File
@@ -4,21 +4,68 @@
////////////////////////////////
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
internal E_InterpretCtx *
e_selected_interpret_ctx(void)
{
return e_interpret_ctx;
}
internal void
e_select_interpret_ctx(E_InterpretCtx *ctx)
e_select_interpret_ctx(E_InterpretCtx *ctx, RDI_Parsed *primary_rdi, U64 ip_voff)
{
e_interpret_ctx = ctx;
// compute and apply frame base
if(primary_rdi != 0)
{
E_Interpretation frame_base = { .code = ~0 };
RDI_Procedure *proc = rdi_procedure_from_voff(primary_rdi, ip_voff);
for(U64 loc_block_idx = proc->frame_base_location_first; loc_block_idx < proc->frame_base_location_opl; loc_block_idx += 1)
{
RDI_LocationBlock *block = rdi_element_from_name_idx(primary_rdi, LocationBlocks, loc_block_idx);
if (block->scope_off_first <= ip_voff && ip_voff < block->scope_off_opl) {
U64 all_location_data_size = 0;
U8 *all_location_data = rdi_table_from_name(primary_rdi, LocationData, &all_location_data_size);
if(block->location_data_off + sizeof(RDI_LocationKind) <= all_location_data_size)
{
RDI_LocationKind loc_kind = *(RDI_LocationKind *)(all_location_data + block->location_data_off);
if(loc_kind == RDI_LocationKind_ValBytecodeStream || loc_kind == RDI_LocationKind_AddrBytecodeStream)
{
U8 *bytecode_ptr = all_location_data + block->location_data_off + sizeof(RDI_LocationKind);
U8 *bytecode_opl = all_location_data + all_location_data_size;
U64 bytecode_size = rdi_size_from_bytecode_stream(bytecode_ptr, bytecode_opl);
String8 bytecode = str8(bytecode_ptr, bytecode_size);
frame_base = e_interpret(bytecode);
}
else if(loc_kind != RDI_LocationKind_NULL)
{
NotImplemented;
}
}
break;
}
}
if(frame_base.code == E_InterpretationCode_Good)
{
*ctx->frame_base = frame_base.value.u64;
}
else
{
ctx->frame_base = 0;
}
}
}
////////////////////////////////
//~ rjf: Space Reading Helpers
internal U64
e_space_gen(E_Space space)
{
U64 result = 0;
if(e_base_ctx->space_gen != 0)
{
result = e_base_ctx->space_gen(e_base_ctx->space_rw_user_data, space);
}
return result;
}
internal B32
e_space_read(E_Space space, void *out, Rng1U64 range)
{
@@ -58,7 +105,11 @@ e_interpret(String8 bytecode)
U64 stack_cap = 128; // TODO(rjf): scan bytecode; determine maximum stack depth
E_Value *stack = push_array_no_zero(scratch.arena, E_Value, stack_cap);
U64 stack_count = 0;
E_Space selected_space = e_interpret_ctx->primary_space;
E_Space selected_space = {0};
if(bytecode.size != 0)
{
selected_space = e_interpret_ctx->primary_space;
}
//- rjf: iterate bytecode & perform ops
U8 *ptr = bytecode.str;
@@ -74,7 +125,7 @@ e_interpret(String8 bytecode)
}
else switch(op)
{
case E_IRExtKind_SetSpace:{ctrlbits = RDI_EVAL_CTRLBITS(32, 0, 0);}break;
case E_IRExtKind_SetSpace: {ctrlbits = RDI_EVAL_CTRLBITS(32, 0, 0);}break;
default:
{
result.code = E_InterpretationCode_BadOp;
@@ -526,13 +577,13 @@ e_interpret(String8 bytecode)
case RDI_EvalOp_EqEq:
{
B32 result = MemoryMatchArray(svals[0].u512, svals[1].u512);
B32 result = MemoryMatchArray(svals[0].u512.u64, svals[1].u512.u64);
nval.u64 = !!result;
}break;
case RDI_EvalOp_NtEq:
{
B32 result = MemoryMatchArray(svals[0].u512, svals[1].u512);
B32 result = MemoryMatchArray(svals[0].u512.u64, svals[1].u512.u64);
nval.u64 = !result;
}break;
@@ -767,7 +818,7 @@ e_interpret(String8 bytecode)
if(offset + bytes_to_read <= sizeof(E_Value))
{
E_Value src_val = svals[1];
MemoryCopy(&nval.u512[0], (U8 *)(&src_val.u512[0]) + offset, bytes_to_read);
MemoryCopy(&nval.u512.u64[0], (U8 *)(&src_val.u512.u64[0]) + offset, bytes_to_read);
}
}break;
@@ -812,6 +863,7 @@ e_interpret(String8 bytecode)
{
result.value = stack[0];
}
result.space = selected_space;
scratch_end(scratch);
return result;
}
+2 -14
View File
@@ -4,21 +4,9 @@
#ifndef EVAL_INTERPRET_H
#define EVAL_INTERPRET_H
////////////////////////////////
//~ rjf: Bytecode Interpretation Types
typedef struct E_Interpretation E_Interpretation;
struct E_Interpretation
{
E_Value value;
E_InterpretationCode code;
};
////////////////////////////////
//~ rjf: Interpretation Context
typedef B32 E_SpaceRWFunction(void *user_data, E_Space space, void *out, Rng1U64 offset_range);
typedef struct E_InterpretCtx E_InterpretCtx;
struct E_InterpretCtx
{
@@ -42,12 +30,12 @@ thread_static E_InterpretCtx *e_interpret_ctx = 0;
////////////////////////////////
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
internal E_InterpretCtx *e_selected_interpret_ctx(void);
internal void e_select_interpret_ctx(E_InterpretCtx *ctx);
internal void e_select_interpret_ctx(E_InterpretCtx *ctx, RDI_Parsed *primary_rdi, U64 ip_voff);
////////////////////////////////
//~ rjf: Space Reading Helpers
internal U64 e_space_gen(E_Space space);
internal B32 e_space_read(E_Space space, void *out, Rng1U64 range);
internal B32 e_space_write(E_Space space, void *in, Rng1U64 range);
+1983 -879
View File
File diff suppressed because it is too large Load Diff
+108 -60
View File
@@ -5,83 +5,121 @@
#define EVAL_IR_H
////////////////////////////////
//~ rjf: Bytecode Operation Types
//~ rjf: Identifier Resolution Rule Types
enum
typedef enum E_IdentifierResolutionPath
{
E_IRExtKind_Bytecode = RDI_EvalOp_COUNT,
E_IRExtKind_SetSpace,
E_IRExtKind_COUNT
};
E_IdentifierResolutionPath_ParentExpr,
E_IdentifierResolutionPath_ParentExprMember,
E_IdentifierResolutionPath_ImplicitThisMember,
E_IdentifierResolutionPath_Local,
E_IdentifierResolutionPath_Globals,
E_IdentifierResolutionPath_ThreadLocals,
E_IdentifierResolutionPath_Procedures,
E_IdentifierResolutionPath_Types,
E_IdentifierResolutionPath_Registers,
E_IdentifierResolutionPath_RegisterAliases,
E_IdentifierResolutionPath_Constants,
E_IdentifierResolutionPath_Macros,
}
E_IdentifierResolutionPath;
typedef struct E_Op E_Op;
struct E_Op
typedef struct E_IdentifierResolutionRule E_IdentifierResolutionRule;
struct E_IdentifierResolutionRule
{
E_Op *next;
RDI_EvalOp opcode;
E_Value value;
String8 string;
};
typedef struct E_OpList E_OpList;
struct E_OpList
{
E_Op *first;
E_Op *last;
U64 op_count;
U64 encoded_size;
E_IdentifierResolutionPath *paths;
U64 count;
};
////////////////////////////////
//~ rjf: IR Tree Types
//~ rjf: IR State
typedef struct E_IRNode E_IRNode;
struct E_IRNode
typedef struct E_IRCacheNode E_IRCacheNode;
struct E_IRCacheNode
{
E_IRNode *first;
E_IRNode *last;
E_IRNode *next;
RDI_EvalOp op;
String8 string;
E_Value value;
E_IRCacheNode *next;
E_Expr *expr;
E_IRNode *overridden_node;
E_IRTreeAndType irtree;
};
typedef struct E_IRTreeAndType E_IRTreeAndType;
struct E_IRTreeAndType
typedef struct E_IRCacheSlot E_IRCacheSlot;
struct E_IRCacheSlot
{
E_IRNode *root;
E_TypeKey type_key;
E_Mode mode;
E_Space space;
E_MsgList msgs;
E_IRCacheNode *first;
E_IRCacheNode *last;
};
////////////////////////////////
//~ rjf: Parse Context
typedef struct E_IRCtx E_IRCtx;
struct E_IRCtx
typedef struct E_IRState E_IRState;
struct E_IRState
{
E_String2ExprMap *macro_map;
Arena *arena;
U64 arena_eval_start_pos;
// rjf: ir context
E_IRCtx *ctx;
// rjf: unpacked ctx
RDI_Procedure *thread_ip_procedure;
// rjf: overridden irtree
E_IRTreeAndType *overridden_irtree;
B32 disallow_autohooks;
B32 disallow_chained_fastpaths;
// rjf: caches
E_UsedExprMap *used_expr_map;
E_TypeAutoHookCacheMap *type_auto_hook_cache_map;
U64 string_id_gen;
E_StringIDMap *string_id_map;
U64 ir_cache_slots_count;
E_IRCacheSlot *ir_cache_slots;
};
////////////////////////////////
//~ rjf: Globals
global read_only E_IRNode e_irnode_nil = {&e_irnode_nil, &e_irnode_nil, &e_irnode_nil};
thread_static E_IRCtx *e_ir_ctx = 0;
E_IdentifierResolutionPath e_default_identifier_resolution_paths[] =
{
E_IdentifierResolutionPath_ParentExpr,
E_IdentifierResolutionPath_ParentExprMember,
E_IdentifierResolutionPath_ImplicitThisMember,
E_IdentifierResolutionPath_Local,
E_IdentifierResolutionPath_Globals,
E_IdentifierResolutionPath_ThreadLocals,
E_IdentifierResolutionPath_Procedures,
E_IdentifierResolutionPath_Types,
E_IdentifierResolutionPath_Registers,
E_IdentifierResolutionPath_RegisterAliases,
E_IdentifierResolutionPath_Constants,
E_IdentifierResolutionPath_Macros,
};
E_IdentifierResolutionRule e_default_identifier_resolution_rule =
{
e_default_identifier_resolution_paths,
ArrayCount(e_default_identifier_resolution_paths),
};
////////////////////////////////
//~ rjf: Expr Kind Enum Functions
internal RDI_EvalOp e_opcode_from_expr_kind(E_ExprKind kind);
internal B32 e_expr_kind_is_comparison(E_ExprKind kind);
////////////////////////////////
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
internal E_IRCtx *e_selected_ir_ctx(void);
internal void e_select_ir_ctx(E_IRCtx *ctx);
E_IdentifierResolutionPath e_callable_identifier_resolution_paths[] =
{
E_IdentifierResolutionPath_Macros,
E_IdentifierResolutionPath_ParentExpr,
E_IdentifierResolutionPath_ParentExprMember,
E_IdentifierResolutionPath_ImplicitThisMember,
E_IdentifierResolutionPath_Local,
E_IdentifierResolutionPath_Globals,
E_IdentifierResolutionPath_ThreadLocals,
E_IdentifierResolutionPath_Procedures,
E_IdentifierResolutionPath_Types,
E_IdentifierResolutionPath_Registers,
E_IdentifierResolutionPath_RegisterAliases,
E_IdentifierResolutionPath_Constants,
};
E_IdentifierResolutionRule e_callable_identifier_resolution_rule =
{
e_callable_identifier_resolution_paths,
ArrayCount(e_callable_identifier_resolution_paths),
};
////////////////////////////////
//~ rjf: IR-ization Functions
@@ -101,6 +139,7 @@ internal void e_irnode_push_child(E_IRNode *parent, E_IRNode *child);
//- rjf: ir subtree building helpers
internal E_IRNode *e_irtree_const_u(Arena *arena, U64 v);
internal E_IRNode *e_irtree_leaf_u128(Arena *arena, U128 u128);
internal E_IRNode *e_irtree_unary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, E_IRNode *c);
internal E_IRNode *e_irtree_binary_op(Arena *arena, RDI_EvalOp op, RDI_EvalTypeGroup group, E_IRNode *l, E_IRNode *r);
internal E_IRNode *e_irtree_binary_op_u(Arena *arena, RDI_EvalOp op, E_IRNode *l, E_IRNode *r);
@@ -108,18 +147,27 @@ internal E_IRNode *e_irtree_conditional(Arena *arena, E_IRNode *c, E_IRNode *l,
internal E_IRNode *e_irtree_bytecode_no_copy(Arena *arena, String8 bytecode);
internal E_IRNode *e_irtree_string_literal(Arena *arena, String8 string);
internal E_IRNode *e_irtree_set_space(Arena *arena, E_Space space, E_IRNode *c);
internal E_IRNode *e_irtree_mem_read_type(Arena *arena, E_Space space, E_IRNode *c, E_TypeKey type_key);
internal E_IRNode *e_irtree_mem_read_type(Arena *arena, E_IRNode *c, E_TypeKey type_key);
internal E_IRNode *e_irtree_convert_lo(Arena *arena, E_IRNode *c, RDI_EvalTypeGroup out, RDI_EvalTypeGroup in);
internal E_IRNode *e_irtree_trunc(Arena *arena, E_IRNode *c, E_TypeKey type_key);
internal E_IRNode *e_irtree_convert_hi(Arena *arena, E_IRNode *c, E_TypeKey out, E_TypeKey in);
internal E_IRNode *e_irtree_resolve_to_value(Arena *arena, E_Space from_space, E_Mode from_mode, E_IRNode *tree, E_TypeKey type_key);
internal E_IRNode *e_irtree_resolve_to_value(Arena *arena, E_Mode from_mode, E_IRNode *tree, E_TypeKey type_key);
//- rjf: expression poison checking
internal B32 e_expr_is_poisoned(E_Expr *expr);
internal void e_expr_poison(E_Expr *expr);
internal void e_expr_unpoison(E_Expr *expr);
//- rjf: top-level irtree/type extraction
internal E_IRTreeAndType e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr);
E_TYPE_ACCESS_FUNCTION_DEF(default);
internal E_IRTreeAndType e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_IdentifierResolutionRule *identifier_resolution_rule, B32 disallow_autohooks, B32 disallow_chained_fastpaths, E_Expr *root_expr);
//- rjf: irtree -> linear ops/bytecode
internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_OpList *out);
internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_Space *current_space, E_OpList *out);
internal E_OpList e_oplist_from_irtree(Arena *arena, E_IRNode *root);
internal String8 e_bytecode_from_oplist(Arena *arena, E_OpList *oplist);
//- rjf: leaf-bytecode expression extensions
internal E_Expr *e_expr_irext_member_access(Arena *arena, E_Expr *lhs, E_IRTreeAndType *lhs_irtree, String8 member_name);
#endif // EVAL_IR_H
+890 -1465
View File
File diff suppressed because it is too large Load Diff
+10 -213
View File
@@ -4,243 +4,40 @@
#ifndef EVAL_PARSE_H
#define EVAL_PARSE_H
////////////////////////////////
//~ rjf: Generated Code
#include "generated/eval.meta.h"
////////////////////////////////
//~ rjf: Token Types
typedef struct E_Token E_Token;
struct E_Token
{
E_TokenKind kind;
Rng1U64 range;
};
typedef struct E_TokenChunkNode E_TokenChunkNode;
struct E_TokenChunkNode
{
E_TokenChunkNode *next;
E_Token *v;
U64 count;
U64 cap;
};
typedef struct E_TokenChunkList E_TokenChunkList;
struct E_TokenChunkList
{
E_TokenChunkNode *first;
E_TokenChunkNode *last;
U64 node_count;
U64 total_count;
};
typedef struct E_TokenArray E_TokenArray;
struct E_TokenArray
{
E_Token *v;
U64 count;
};
////////////////////////////////
//~ rjf: Expression Tree Types
typedef struct E_Expr E_Expr;
struct E_Expr
{
E_Expr *first;
E_Expr *last;
E_Expr *next;
E_Expr *prev;
E_Expr *ref;
void *location;
E_ExprKind kind;
E_Mode mode;
E_Space space;
E_TypeKey type_key;
E_Value value;
String8 string;
String8 bytecode;
};
////////////////////////////////
//~ rjf: Map Types
//- rjf: string -> num
typedef struct E_String2NumMapNode E_String2NumMapNode;
struct E_String2NumMapNode
{
E_String2NumMapNode *order_next;
E_String2NumMapNode *hash_next;
String8 string;
U64 num;
};
typedef struct E_String2NumMapNodeArray E_String2NumMapNodeArray;
struct E_String2NumMapNodeArray
{
E_String2NumMapNode **v;
U64 count;
};
typedef struct E_String2NumMapSlot E_String2NumMapSlot;
struct E_String2NumMapSlot
{
E_String2NumMapNode *first;
E_String2NumMapNode *last;
};
typedef struct E_String2NumMap E_String2NumMap;
struct E_String2NumMap
{
U64 slots_count;
U64 node_count;
E_String2NumMapSlot *slots;
E_String2NumMapNode *first;
E_String2NumMapNode *last;
};
//- rjf: string -> expr
typedef struct E_String2ExprMapNode E_String2ExprMapNode;
struct E_String2ExprMapNode
{
E_String2ExprMapNode *hash_next;
String8 string;
E_Expr *expr;
U64 poison_count;
};
typedef struct E_String2ExprMapSlot E_String2ExprMapSlot;
struct E_String2ExprMapSlot
{
E_String2ExprMapNode *first;
E_String2ExprMapNode *last;
};
typedef struct E_String2ExprMap E_String2ExprMap;
struct E_String2ExprMap
{
U64 slots_count;
E_String2ExprMapSlot *slots;
};
////////////////////////////////
//~ rjf: Parse Context
typedef struct E_ParseCtx E_ParseCtx;
struct E_ParseCtx
{
// rjf: instruction pointer info
U64 ip_vaddr;
U64 ip_voff;
E_Space ip_thread_space;
// rjf: modules
E_Module *modules;
U64 modules_count;
E_Module *primary_module;
// rjf: local identifier resolution maps
E_String2NumMap *regs_map;
E_String2NumMap *reg_alias_map;
E_String2NumMap *locals_map; // (within `rdis[rdis_primary_idx]`)
E_String2NumMap *member_map; // (within `rdis[rdis_primary_idx]`)
};
////////////////////////////////
//~ rjf: Parse Results
typedef struct E_Parse E_Parse;
struct E_Parse
{
E_Token *last_token;
E_Expr *expr;
E_MsgList msgs;
};
////////////////////////////////
//~ rjf: Globals
global read_only E_String2NumMap e_string2num_map_nil = {0};
global read_only E_String2ExprMap e_string2expr_map_nil = {0};
global read_only E_Expr e_expr_nil = {&e_expr_nil, &e_expr_nil, &e_expr_nil};
thread_static E_ParseCtx *e_parse_ctx = 0;
////////////////////////////////
//~ rjf: Basic Map Functions
//- rjf: string -> num
internal E_String2NumMap e_string2num_map_make(Arena *arena, U64 slot_count);
internal void e_string2num_map_insert(Arena *arena, E_String2NumMap *map, String8 string, U64 num);
internal U64 e_num_from_string(E_String2NumMap *map, String8 string);
internal E_String2NumMapNodeArray e_string2num_map_node_array_from_map(Arena *arena, E_String2NumMap *map);
internal int e_string2num_map_node_qsort_compare__num_ascending(E_String2NumMapNode **a, E_String2NumMapNode **b);
internal void e_string2num_map_node_array_sort__in_place(E_String2NumMapNodeArray *array);
//- rjf: string -> expr
internal E_String2ExprMap e_string2expr_map_make(Arena *arena, U64 slot_count);
internal void e_string2expr_map_insert(Arena *arena, E_String2ExprMap *map, String8 string, E_Expr *expr);
internal void e_string2expr_map_inc_poison(E_String2ExprMap *map, String8 string);
internal void e_string2expr_map_dec_poison(E_String2ExprMap *map, String8 string);
internal E_Expr *e_string2expr_lookup(E_String2ExprMap *map, String8 string);
////////////////////////////////
//~ rjf: Debug-Info-Driven Map Building Functions
internal E_String2NumMap *e_push_locals_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff);
internal E_String2NumMap *e_push_member_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff);
////////////////////////////////
//~ rjf: Tokenization Functions
#define e_token_at_it(it, arr) (((it) < (arr)->v+(arr)->count) ? (*(it)) : e_token_zero())
#define e_token_at_it(it, arr) (((arr)->v <= (it) && (it) < (arr)->v+(arr)->count) ? (*(it)) : e_token_zero())
internal E_Token e_token_zero(void);
internal void e_token_chunk_list_push(Arena *arena, E_TokenChunkList *list, U64 chunk_size, E_Token *token);
internal E_TokenArray e_token_array_from_chunk_list(Arena *arena, E_TokenChunkList *list);
internal E_TokenArray e_token_array_from_text(Arena *arena, String8 text);
internal E_TokenArray e_token_array_make_first_opl(E_Token *first, E_Token *opl);
////////////////////////////////
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
internal E_ParseCtx *e_selected_parse_ctx(void);
internal void e_select_parse_ctx(E_ParseCtx *ctx);
internal U32 e_parse_ctx_module_idx_from_rdi(RDI_Parsed *rdi);
////////////////////////////////
//~ rjf: Expression Tree Building Functions
internal E_Expr *e_push_expr(Arena *arena, E_ExprKind kind, void *location);
internal E_Expr *e_push_expr(Arena *arena, E_ExprKind kind, Rng1U64 range);
internal void e_expr_insert_child(E_Expr *parent, E_Expr *prev, E_Expr *child);
internal void e_expr_push_child(E_Expr *parent, E_Expr *child);
internal void e_expr_remove_child(E_Expr *parent, E_Expr *child);
internal E_Expr *e_expr_ref(Arena *arena, E_Expr *ref);
internal E_Expr *e_expr_ref_addr(Arena *arena, E_Expr *rhs);
internal E_Expr *e_expr_ref_member_access(Arena *arena, E_Expr *lhs, String8 member_name);
internal E_Expr *e_expr_ref_array_index(Arena *arena, E_Expr *lhs, U64 index);
internal E_Expr *e_expr_ref_deref(Arena *arena, E_Expr *rhs);
internal E_Expr *e_expr_ref_cast(Arena *arena, E_TypeKey type_key, E_Expr *rhs);
internal E_Expr *e_expr_ref_bswap(Arena *arena, E_Expr *rhs);
internal E_Expr *e_expr_copy(Arena *arena, E_Expr *src);
internal void e_expr_list_push(Arena *arena, E_ExprList *list, E_Expr *expr);
////////////////////////////////
//~ rjf: Expression Tree -> String Conversions
internal void e_append_strings_from_expr(Arena *arena, E_Expr *expr, String8List *out);
internal String8 e_string_from_expr(Arena *arena, E_Expr *expr);
internal void e_append_strings_from_expr(Arena *arena, E_Expr *expr, String8 parent_expr_string, String8List *out);
internal String8 e_string_from_expr(Arena *arena, E_Expr *expr, String8 parent_expr_string);
////////////////////////////////
//~ rjf: Parsing Functions
internal E_TypeKey e_leaf_type_from_name(String8 name);
internal E_TypeKey e_type_from_expr(E_Expr *expr);
internal void e_push_leaf_ident_exprs_from_expr__in_place(Arena *arena, E_String2ExprMap *map, E_Expr *expr);
internal E_Parse e_parse_type_from_text_tokens(Arena *arena, String8 text, E_TokenArray *tokens);
internal E_Parse e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *tokens, S64 max_precedence);
internal E_Parse e_parse_expr_from_text_tokens(Arena *arena, String8 text, E_TokenArray *tokens);
internal E_Expr *e_parse_expr_from_text(Arena *arena, String8 text);
internal E_TypeKey e_type_key_from_expr(E_Expr *expr);
internal E_Parse e_push_type_parse_from_text_tokens(Arena *arena, String8 text, E_TokenArray tokens);
internal E_Parse e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray tokens, S64 max_precedence, U64 max_chain_count);
internal E_Parse e_push_parse_from_string(Arena *arena, String8 text);
#endif // EVAL_PARSE_H
+1495 -442
View File
File diff suppressed because it is too large Load Diff
+115 -256
View File
@@ -5,250 +5,37 @@
#define EVAL_TYPES_H
////////////////////////////////
//~ rjf: Implicit Type Graph Key Types
//~ rjf: Type Unwrapping
typedef enum E_TypeKeyKind
{
E_TypeKeyKind_Null,
E_TypeKeyKind_Basic,
E_TypeKeyKind_Ext,
E_TypeKeyKind_Cons,
E_TypeKeyKind_Reg,
E_TypeKeyKind_RegAlias,
}
E_TypeKeyKind;
typedef struct E_TypeKey E_TypeKey;
struct E_TypeKey
{
E_TypeKeyKind kind;
U32 u32[3];
// [0] -> E_TypeKind (Basic, Cons, Ext); Arch (Reg, RegAlias)
// [1] -> Type Index In RDI (Ext); Code (Reg, RegAlias); Type Index In Constructed (Cons)
// [2] -> RDI Index (Ext)
};
typedef struct E_TypeKeyNode E_TypeKeyNode;
struct E_TypeKeyNode
{
E_TypeKeyNode *next;
E_TypeKey v;
};
typedef struct E_TypeKeyList E_TypeKeyList;
struct E_TypeKeyList
{
E_TypeKeyNode *first;
E_TypeKeyNode *last;
U64 count;
};
////////////////////////////////
//~ rjf: Full Extracted Type Information Types
typedef enum E_MemberKind
{
E_MemberKind_Null,
E_MemberKind_DataField,
E_MemberKind_StaticData,
E_MemberKind_Method,
E_MemberKind_StaticMethod,
E_MemberKind_VirtualMethod,
E_MemberKind_VTablePtr,
E_MemberKind_Base,
E_MemberKind_VirtualBase,
E_MemberKind_NestedType,
E_MemberKind_Padding,
E_MemberKind_COUNT
}
E_MemberKind;
typedef U32 E_TypeFlags;
typedef U32 E_TypeUnwrapFlags;
enum
{
E_TypeFlag_Const = (1<<0),
E_TypeFlag_Volatile = (1<<1),
E_TypeFlag_External = (1<<2),
E_TypeFlag_IsPlainText= (1<<3),
E_TypeFlag_IsCodeText = (1<<4),
E_TypeFlag_IsPathText = (1<<5),
};
typedef struct E_Member E_Member;
struct E_Member
{
E_MemberKind kind;
E_TypeKey type_key;
String8 name;
String8 pretty_name;
U64 off;
E_TypeKeyList inheritance_key_chain;
};
typedef struct E_MemberNode E_MemberNode;
struct E_MemberNode
{
E_MemberNode *next;
E_Member v;
};
typedef struct E_MemberList E_MemberList;
struct E_MemberList
{
E_MemberNode *first;
E_MemberNode *last;
U64 count;
};
typedef struct E_MemberArray E_MemberArray;
struct E_MemberArray
{
E_Member *v;
U64 count;
};
typedef struct E_EnumVal E_EnumVal;
struct E_EnumVal
{
String8 name;
U64 val;
};
typedef struct E_EnumValArray E_EnumValArray;
struct E_EnumValArray
{
E_EnumVal *v;
U64 count;
};
typedef struct E_Type E_Type;
struct E_Type
{
E_TypeKind kind;
E_TypeFlags flags;
String8 name;
U64 byte_size;
U64 count;
U32 off;
E_TypeKey direct_type_key;
E_TypeKey owner_type_key;
E_TypeKey *param_type_keys;
E_Member *members;
E_EnumVal *enum_vals;
};
////////////////////////////////
//~ rjf: Evaluation Context
//- rjf: constructed type cache types
typedef struct E_ConsTypeParams E_ConsTypeParams;
struct E_ConsTypeParams
{
Arch arch;
E_TypeKind kind;
E_TypeFlags flags;
String8 name;
E_TypeKey direct_key;
U64 count;
E_Member *members;
E_EnumVal *enum_vals;
};
typedef struct E_ConsTypeNode E_ConsTypeNode;
struct E_ConsTypeNode
{
E_ConsTypeNode *key_next;
E_ConsTypeNode *content_next;
E_TypeKey key;
E_ConsTypeParams params;
U64 byte_size;
};
typedef struct E_ConsTypeSlot E_ConsTypeSlot;
struct E_ConsTypeSlot
{
E_ConsTypeNode *first;
E_ConsTypeNode *last;
};
//- rjf: member lookup cache types
typedef struct E_MemberHashNode E_MemberHashNode;
struct E_MemberHashNode
{
E_MemberHashNode *next;
U64 member_idx;
};
typedef struct E_MemberHashSlot E_MemberHashSlot;
struct E_MemberHashSlot
{
E_MemberHashNode *first;
E_MemberHashNode *last;
};
typedef struct E_MemberCacheNode E_MemberCacheNode;
struct E_MemberCacheNode
{
E_MemberCacheNode *next;
E_TypeKey key;
E_MemberArray members;
U64 member_hash_slots_count;
E_MemberHashSlot *member_hash_slots;
};
typedef struct E_MemberCacheSlot E_MemberCacheSlot;
struct E_MemberCacheSlot
{
E_MemberCacheNode *first;
E_MemberCacheNode *last;
};
//- rjf: context parameterization
typedef struct E_TypeCtx E_TypeCtx;
struct E_TypeCtx
{
// rjf: instruction pointer info
U64 ip_vaddr;
U64 ip_voff; // (within `primary_module`)
// rjf: debug info
E_Module *modules;
U64 modules_count;
E_Module *primary_module;
};
//- rjf: stateful machine part of context (not provided by user)
typedef struct E_TypeState E_TypeState;
struct E_TypeState
{
Arena *arena;
U64 arena_eval_start_pos;
// rjf: evaluation context
E_TypeCtx *ctx;
// rjf: JIT-constructed types tables
U64 cons_id_gen;
U64 cons_content_slots_count;
U64 cons_key_slots_count;
E_ConsTypeSlot *cons_content_slots;
E_ConsTypeSlot *cons_key_slots;
// rjf: member cache table
U64 member_cache_slots_count;
E_MemberCacheSlot *member_cache_slots;
E_TypeUnwrapFlag_Modifiers = (1<<0),
E_TypeUnwrapFlag_Pointers = (1<<1),
E_TypeUnwrapFlag_Lenses = (1<<2),
E_TypeUnwrapFlag_Meta = (1<<3),
E_TypeUnwrapFlag_Enums = (1<<4),
E_TypeUnwrapFlag_Aliases = (1<<5),
E_TypeUnwrapFlag_All = 0xffffffff,
E_TypeUnwrapFlag_AllDecorative = (E_TypeUnwrapFlag_All & ~E_TypeUnwrapFlag_Pointers)
};
////////////////////////////////
//~ rjf: Globals
global read_only E_Member e_member_nil = {E_MemberKind_Null, zero_struct, {0}, {0}, 0, {0}};
global read_only E_Member e_member_nil = {E_MemberKind_Null};
global read_only E_Type e_type_nil = {E_TypeKind_Null};
thread_static E_TypeState *e_type_state = 0;
E_TYPE_EXPAND_INFO_FUNCTION_DEF(default);
E_TYPE_EXPAND_RANGE_FUNCTION_DEF(default);
E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(identity);
E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(identity);
global read_only E_TypeExpandRule e_type_expand_rule__default =
{
E_TYPE_EXPAND_INFO_FUNCTION_NAME(default),
E_TYPE_EXPAND_RANGE_FUNCTION_NAME(default),
E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity),
E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity),
};
////////////////////////////////
//~ rjf: Type Kind Enum Functions
@@ -270,10 +57,11 @@ internal void e_member_list_push(Arena *arena, E_MemberList *list, E_Member *mem
internal E_MemberArray e_member_array_from_list(Arena *arena, E_MemberList *list);
////////////////////////////////
//~ rjf: Context Selection Functions (Selection Required For All Subsequent APIs)
//~ rjf: Enum Value Functions
internal E_TypeCtx *e_selected_type_ctx(void);
internal void e_select_type_ctx(E_TypeCtx *ctx);
internal void e_enum_val_list_push(Arena *arena, E_EnumValList *list, E_EnumVal *enum_val);
#define e_enum_val_list_push_new(arena, list, ...) e_enum_val_list_push((arena), (list), &(E_EnumVal){.val = 0, __VA_ARGS__})
internal E_EnumValArray e_enum_val_array_from_list(Arena *arena, E_EnumValList *list);
////////////////////////////////
//~ rjf: Type Operation Functions
@@ -292,42 +80,113 @@ internal E_TypeKey e_type_key_cons_(E_ConsTypeParams *params);
#define e_type_key_cons(...) e_type_key_cons_(&(E_ConsTypeParams){.kind = E_TypeKind_Null, __VA_ARGS__})
//- rjf: constructed type construction helpers
internal E_TypeKey e_type_key_cons_array(E_TypeKey element_type_key, U64 count);
internal E_TypeKey e_type_key_cons_ptr(Arch arch, E_TypeKey element_type_key, E_TypeFlags flags);
internal E_TypeKey e_type_key_cons_array(E_TypeKey element_type_key, U64 count, E_TypeFlags flags);
internal E_TypeKey e_type_key_cons_ptr(Arch arch, E_TypeKey element_type_key, U64 count, E_TypeFlags flags);
internal E_TypeKey e_type_key_cons_meta_expr(E_TypeKey type_key, String8 expr);
internal E_TypeKey e_type_key_cons_meta_display_name(E_TypeKey type_key, String8 name);
internal E_TypeKey e_type_key_cons_meta_description(E_TypeKey type_key, String8 desc);
internal E_TypeKey e_type_key_cons_base(Type *type);
internal E_TypeKey e_type_key_file(void);
internal E_TypeKey e_type_key_folder(void);
//- rjf: basic type key functions
internal B32 e_type_key_match(E_TypeKey l, E_TypeKey r);
//- rjf: key -> info extraction
internal U64 e_hash_from_type_key(E_TypeKey key);
//- rjf: type key -> info extraction
internal U64 e_hash_from_type(E_Type *type);
internal E_TypeKind e_type_kind_from_key(E_TypeKey key);
internal U64 e_type_byte_size_from_key(E_TypeKey key);
internal E_Type *e_type_from_key(Arena *arena, E_TypeKey key);
internal E_TypeKey e_type_direct_from_key(E_TypeKey key);
internal E_TypeKey e_type_owner_from_key(E_TypeKey key);
internal E_TypeKey e_type_ptee_from_key(E_TypeKey key);
internal E_TypeKey e_type_unwrap_enum(E_TypeKey key);
internal E_TypeKey e_type_unwrap(E_TypeKey key);
internal E_TypeKey e_type_promote(E_TypeKey key);
internal B32 e_type_match(E_TypeKey l, E_TypeKey r);
internal E_Member *e_type_member_copy(Arena *arena, E_Member *src);
internal E_Type *e_push_type_from_key(Arena *arena, E_TypeKey key);
internal int e_type_qsort_compare_members_offset(E_Member *a, E_Member *b);
internal E_MemberArray e_type_data_members_from_key(Arena *arena, E_TypeKey key);
internal E_Member *e_type_member_from_array_name(E_MemberArray *members, String8 name);
internal E_TypeExpandRule *e_expand_rule_from_type_key(E_TypeKey key);
//- rjf: type key traversal
internal E_TypeKey e_type_key_direct(E_TypeKey key);
internal E_TypeKey e_type_key_owner(E_TypeKey key);
internal E_TypeKey e_type_key_promote(E_TypeKey key);
internal E_TypeKey e_type_key_unwrap(E_TypeKey key, E_TypeUnwrapFlags flags);
//- rjf: type comparisons
internal B32 e_type_match(E_TypeKey l, E_TypeKey r);
//- rjf: type key -> string
internal void e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 prec, B32 skip_return);
internal void e_type_rhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 prec);
internal String8 e_type_string_from_key(Arena *arena, E_TypeKey key);
//- rjf: type key data structures
internal void e_type_key_list_push(Arena *arena, E_TypeKeyList *list, E_TypeKey key);
internal E_TypeKeyList e_type_key_list_copy(Arena *arena, E_TypeKeyList *src);
internal E_TypeKey e_default_expansion_type_from_key(E_TypeKey key);
////////////////////////////////
//~ rjf: Cache Lookups
internal E_Type *e_type_from_key(E_TypeKey key);
//- rjf: member lookups
internal E_MemberCacheNode *e_member_cache_node_from_type_key(E_TypeKey key);
internal E_MemberArray e_type_data_members_from_key_filter__cached(E_TypeKey key, String8 filter);
internal E_MemberArray e_type_data_members_from_key__cached(E_TypeKey key);
internal E_Member e_type_member_from_key_name__cached(E_TypeKey key, String8 name);
//- rjf: enum val lookups
internal E_EnumValCacheNode *e_enum_val_cache_node_from_type_key(E_TypeKey key);
internal E_EnumValArray e_type_enum_vals_from_key_filter__cached(E_TypeKey key, String8 filter);
internal E_EnumValArray e_type_enum_vals_from_key__cached(E_TypeKey key);
internal E_EnumVal e_type_enum_val_from_key_name__cached(E_TypeKey key, String8 name);
////////////////////////////////
//~ rjf: (Built-In Type Hooks) Default Hooks
E_TYPE_EXPAND_INFO_FUNCTION_DEF(default);
E_TYPE_EXPAND_RANGE_FUNCTION_DEF(default);
E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(identity);
E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(identity);
////////////////////////////////
//~ rjf: (Built-In Type Hooks) `rows` lens
E_TYPE_EXPAND_INFO_FUNCTION_DEF(rows);
E_TYPE_EXPAND_RANGE_FUNCTION_DEF(rows);
////////////////////////////////
//~ rjf: (Built-In Type Hooks) `sequence` lens
E_TYPE_EXPAND_INFO_FUNCTION_DEF(sequence);
E_TYPE_EXPAND_RANGE_FUNCTION_DEF(sequence);
////////////////////////////////
//~ rjf: (Built-In Type Hooks) `array` lens
E_TYPE_EXPAND_INFO_FUNCTION_DEF(array);
E_TYPE_EXPAND_RANGE_FUNCTION_DEF(array);
////////////////////////////////
//~ rjf: (Built-In Type Hooks) `slice` lens
E_TYPE_IREXT_FUNCTION_DEF(slice);
E_TYPE_ACCESS_FUNCTION_DEF(slice);
E_TYPE_EXPAND_INFO_FUNCTION_DEF(slice);
E_TYPE_EXPAND_RANGE_FUNCTION_DEF(slice);
////////////////////////////////
//~ rjf: (Built-In Type Hooks) `only`, `omit` lenses
E_TYPE_EXPAND_INFO_FUNCTION_DEF(only_and_omit);
E_TYPE_EXPAND_RANGE_FUNCTION_DEF(only_and_omit);
////////////////////////////////
//~ rjf: (Built-In Type Hooks) `folder` type
E_TYPE_EXPAND_INFO_FUNCTION_DEF(folder);
E_TYPE_EXPAND_RANGE_FUNCTION_DEF(folder);
E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(folder);
E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(folder);
////////////////////////////////
//~ rjf: (Built-In Type Hooks) `file` type
E_TYPE_IREXT_FUNCTION_DEF(file);
E_TYPE_ACCESS_FUNCTION_DEF(file);
E_TYPE_EXPAND_INFO_FUNCTION_DEF(file);
E_TYPE_EXPAND_RANGE_FUNCTION_DEF(file);
#endif // EVAL_TYPES_H
+184 -172
View File
@@ -14,126 +14,72 @@ str8_lit_comp("CharLiteral"),
str8_lit_comp("Symbol"),
};
String8 e_expr_kind_strings[48] =
{
str8_lit_comp("Nil"),
str8_lit_comp("Ref"),
str8_lit_comp("ArrayIndex"),
str8_lit_comp("MemberAccess"),
str8_lit_comp("Deref"),
str8_lit_comp("Address"),
str8_lit_comp("Cast"),
str8_lit_comp("Sizeof"),
str8_lit_comp("Typeof"),
str8_lit_comp("ByteSwap"),
str8_lit_comp("Pos"),
str8_lit_comp("Neg"),
str8_lit_comp("LogNot"),
str8_lit_comp("BitNot"),
str8_lit_comp("Mul"),
str8_lit_comp("Div"),
str8_lit_comp("Mod"),
str8_lit_comp("Add"),
str8_lit_comp("Sub"),
str8_lit_comp("LShift"),
str8_lit_comp("RShift"),
str8_lit_comp("Less"),
str8_lit_comp("LsEq"),
str8_lit_comp("Grtr"),
str8_lit_comp("GrEq"),
str8_lit_comp("EqEq"),
str8_lit_comp("NtEq"),
str8_lit_comp("BitAnd"),
str8_lit_comp("BitXor"),
str8_lit_comp("BitOr"),
str8_lit_comp("LogAnd"),
str8_lit_comp("LogOr"),
str8_lit_comp("Ternary"),
str8_lit_comp("LeafBytecode"),
str8_lit_comp("LeafMember"),
str8_lit_comp("LeafStringLiteral"),
str8_lit_comp("LeafBool"),
str8_lit_comp("LeafU64"),
str8_lit_comp("LeafF64"),
str8_lit_comp("LeafF32"),
str8_lit_comp("LeafIdent"),
str8_lit_comp("LeafOffset"),
str8_lit_comp("LeafFilePath"),
str8_lit_comp("TypeIdent"),
str8_lit_comp("Ptr"),
str8_lit_comp("Array"),
str8_lit_comp("Func"),
str8_lit_comp("Define"),
};
String8 e_interpretation_code_display_strings[11] =
String8 e_type_kind_basic_string_table[61] =
{
str8_lit_comp(""),
str8_lit_comp("Cannot divide by zero."),
str8_lit_comp("Invalid operation."),
str8_lit_comp("Invalid operation types."),
str8_lit_comp("Failed memory read."),
str8_lit_comp("Failed register read."),
str8_lit_comp("Invalid frame base address."),
str8_lit_comp("Invalid module base address."),
str8_lit_comp("Invalid thread-local storage base address."),
str8_lit_comp("Insufficient evaluation machine stack space."),
str8_lit_comp("Malformed bytecode."),
str8_lit_comp("void"),
str8_lit_comp("HANDLE"),
str8_lit_comp("HRESULT"),
str8_lit_comp("char8"),
str8_lit_comp("char16"),
str8_lit_comp("char32"),
str8_lit_comp("uchar8"),
str8_lit_comp("uchar16"),
str8_lit_comp("uchar32"),
str8_lit_comp("uint8"),
str8_lit_comp("uint16"),
str8_lit_comp("uint32"),
str8_lit_comp("uint64"),
str8_lit_comp("uint128"),
str8_lit_comp("uint256"),
str8_lit_comp("uint512"),
str8_lit_comp("int8"),
str8_lit_comp("int16"),
str8_lit_comp("int32"),
str8_lit_comp("int64"),
str8_lit_comp("int128"),
str8_lit_comp("int256"),
str8_lit_comp("int512"),
str8_lit_comp("bool"),
str8_lit_comp("float16"),
str8_lit_comp("float32"),
str8_lit_comp("float32PP"),
str8_lit_comp("float48"),
str8_lit_comp("float64"),
str8_lit_comp("float80"),
str8_lit_comp("float128"),
str8_lit_comp("complex_float32"),
str8_lit_comp("complex_float64"),
str8_lit_comp("complex_float80"),
str8_lit_comp("complex_float128"),
str8_lit_comp("modifier"),
str8_lit_comp("ptr"),
str8_lit_comp("lref"),
str8_lit_comp("rref"),
str8_lit_comp("array"),
str8_lit_comp("function"),
str8_lit_comp("method"),
str8_lit_comp("member_ptr"),
str8_lit_comp("struct"),
str8_lit_comp("class"),
str8_lit_comp("union"),
str8_lit_comp("enum"),
str8_lit_comp("typedef"),
str8_lit_comp("struct"),
str8_lit_comp("union"),
str8_lit_comp("class"),
str8_lit_comp("enum"),
str8_lit_comp("bitfield"),
str8_lit_comp("variadic"),
str8_lit_comp("set"),
str8_lit_comp("lens"),
str8_lit_comp("lens_spec"),
str8_lit_comp("meta_expr"),
str8_lit_comp("meta_display_name"),
str8_lit_comp("meta_description"),
};
E_OpInfo e_expr_kind_op_info_table[48] =
{
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp("["), str8_lit_comp("]") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp("."), str8_lit_comp("") },
{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("*"), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("&"), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 1, str8_lit_comp("("), str8_lit_comp(")"), str8_lit_comp("") },
{ E_OpKind_UnaryPrefix, 1, str8_lit_comp("sizeof"), str8_lit_comp("("), str8_lit_comp(")") },
{ E_OpKind_UnaryPrefix, 1, str8_lit_comp("typeof"), str8_lit_comp("("), str8_lit_comp(")") },
{ E_OpKind_UnaryPrefix, 1, str8_lit_comp("bswap"), str8_lit_comp("("), str8_lit_comp(")") },
{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("+"), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("-"), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("!"), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("~"), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 3, str8_lit_comp(""), str8_lit_comp("*"), str8_lit_comp("") },
{ E_OpKind_Binary, 3, str8_lit_comp(""), str8_lit_comp("/"), str8_lit_comp("") },
{ E_OpKind_Binary, 3, str8_lit_comp(""), str8_lit_comp("%"), str8_lit_comp("") },
{ E_OpKind_Binary, 4, str8_lit_comp(""), str8_lit_comp("+"), str8_lit_comp("") },
{ E_OpKind_Binary, 4, str8_lit_comp(""), str8_lit_comp("-"), str8_lit_comp("") },
{ E_OpKind_Binary, 5, str8_lit_comp(""), str8_lit_comp("<<"), str8_lit_comp("") },
{ E_OpKind_Binary, 5, str8_lit_comp(""), str8_lit_comp(">>"), str8_lit_comp("") },
{ E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp("<"), str8_lit_comp("") },
{ E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp("<="), str8_lit_comp("") },
{ E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp(">"), str8_lit_comp("") },
{ E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp(">="), str8_lit_comp("") },
{ E_OpKind_Binary, 7, str8_lit_comp(""), str8_lit_comp("=="), str8_lit_comp("") },
{ E_OpKind_Binary, 7, str8_lit_comp(""), str8_lit_comp("!="), str8_lit_comp("") },
{ E_OpKind_Binary, 8, str8_lit_comp(""), str8_lit_comp("&"), str8_lit_comp("") },
{ E_OpKind_Binary, 9, str8_lit_comp(""), str8_lit_comp("^"), str8_lit_comp("") },
{ E_OpKind_Binary, 10, str8_lit_comp(""), str8_lit_comp("|"), str8_lit_comp("") },
{ E_OpKind_Binary, 11, str8_lit_comp(""), str8_lit_comp("&&"), str8_lit_comp("") },
{ E_OpKind_Binary, 12, str8_lit_comp(""), str8_lit_comp("||"), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp("?"), str8_lit_comp(":") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 13, str8_lit_comp(""), str8_lit_comp("="), str8_lit_comp("") },
};
U8 e_kind_basic_byte_size_table[56] =
U8 e_type_kind_basic_byte_size_table[61] =
{
0,
0,
@@ -191,66 +137,132 @@ U8 e_kind_basic_byte_size_table[56] =
0,
0,
0,
0,
0,
0,
0,
0,
};
String8 e_kind_basic_string_table[56] =
String8 e_expr_kind_strings[49] =
{
str8_lit_comp("Nil"),
str8_lit_comp("Ref"),
str8_lit_comp("ArrayIndex"),
str8_lit_comp("MemberAccess"),
str8_lit_comp("Deref"),
str8_lit_comp("Address"),
str8_lit_comp("Cast"),
str8_lit_comp("Sizeof"),
str8_lit_comp("Typeof"),
str8_lit_comp("ByteSwap"),
str8_lit_comp("Pos"),
str8_lit_comp("Neg"),
str8_lit_comp("LogNot"),
str8_lit_comp("BitNot"),
str8_lit_comp("Mul"),
str8_lit_comp("Div"),
str8_lit_comp("Mod"),
str8_lit_comp("Add"),
str8_lit_comp("Sub"),
str8_lit_comp("LShift"),
str8_lit_comp("RShift"),
str8_lit_comp("Less"),
str8_lit_comp("LsEq"),
str8_lit_comp("Grtr"),
str8_lit_comp("GrEq"),
str8_lit_comp("EqEq"),
str8_lit_comp("NtEq"),
str8_lit_comp("BitAnd"),
str8_lit_comp("BitXor"),
str8_lit_comp("BitOr"),
str8_lit_comp("LogAnd"),
str8_lit_comp("LogOr"),
str8_lit_comp("Ternary"),
str8_lit_comp("Call"),
str8_lit_comp("LeafBytecode"),
str8_lit_comp("LeafStringLiteral"),
str8_lit_comp("LeafU64"),
str8_lit_comp("LeafF64"),
str8_lit_comp("LeafF32"),
str8_lit_comp("LeafIdentifier"),
str8_lit_comp("LeafOffset"),
str8_lit_comp("LeafValue"),
str8_lit_comp("LeafFilePath"),
str8_lit_comp("TypeIdent"),
str8_lit_comp("Ptr"),
str8_lit_comp("Array"),
str8_lit_comp("Func"),
str8_lit_comp("Unsigned"),
str8_lit_comp("Define"),
};
E_OpInfo e_expr_kind_op_info_table[49] =
{
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp("["), str8_lit_comp("]"), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp("."), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("*"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("&"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 1, str8_lit_comp("cast("), str8_lit_comp(")"), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_UnaryPrefix, 1, str8_lit_comp("sizeof "), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_UnaryPrefix, 1, str8_lit_comp("typeof "), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_UnaryPrefix, 1, str8_lit_comp("bswap "), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("+"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("-"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("!"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("~"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 3, str8_lit_comp(""), str8_lit_comp(" * "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 3, str8_lit_comp(""), str8_lit_comp(" / "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 3, str8_lit_comp(""), str8_lit_comp(" % "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 4, str8_lit_comp(""), str8_lit_comp(" + "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 4, str8_lit_comp(""), str8_lit_comp(" - "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 5, str8_lit_comp(""), str8_lit_comp(" << "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 5, str8_lit_comp(""), str8_lit_comp(" >> "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp(" < "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp(" <= "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp(" > "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp(" >= "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 7, str8_lit_comp(""), str8_lit_comp(" == "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 7, str8_lit_comp(""), str8_lit_comp(" != "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 8, str8_lit_comp(""), str8_lit_comp(" & "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 9, str8_lit_comp(""), str8_lit_comp(" ^ "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 10, str8_lit_comp(""), str8_lit_comp(" | "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 11, str8_lit_comp(""), str8_lit_comp(" && "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 12, str8_lit_comp(""), str8_lit_comp(" || "), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(" ? "), str8_lit_comp(""), str8_lit_comp(" : ") },
{ E_OpKind_Null, 15, str8_lit_comp(""), str8_lit_comp("("), str8_lit_comp(")"), str8_lit_comp(", ") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp("unsigned "), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 13, str8_lit_comp(""), str8_lit_comp(" = "), str8_lit_comp(""), str8_lit_comp("") },
};
String8 e_interpretation_code_display_strings[11] =
{
str8_lit_comp(""),
str8_lit_comp("void"),
str8_lit_comp("HANDLE"),
str8_lit_comp("HRESULT"),
str8_lit_comp("char8"),
str8_lit_comp("char16"),
str8_lit_comp("char32"),
str8_lit_comp("uchar8"),
str8_lit_comp("uchar16"),
str8_lit_comp("uchar32"),
str8_lit_comp("U8"),
str8_lit_comp("U16"),
str8_lit_comp("U32"),
str8_lit_comp("U64"),
str8_lit_comp("U128"),
str8_lit_comp("U256"),
str8_lit_comp("U512"),
str8_lit_comp("S8"),
str8_lit_comp("S16"),
str8_lit_comp("S32"),
str8_lit_comp("S64"),
str8_lit_comp("S128"),
str8_lit_comp("S256"),
str8_lit_comp("S512"),
str8_lit_comp("bool"),
str8_lit_comp("F16"),
str8_lit_comp("F32"),
str8_lit_comp("F32PP"),
str8_lit_comp("F48"),
str8_lit_comp("F64"),
str8_lit_comp("F80"),
str8_lit_comp("F128"),
str8_lit_comp("ComplexF32"),
str8_lit_comp("ComplexF64"),
str8_lit_comp("ComplexF80"),
str8_lit_comp("ComplexF128"),
str8_lit_comp("modifier"),
str8_lit_comp("ptr"),
str8_lit_comp("lref"),
str8_lit_comp("rref"),
str8_lit_comp("array"),
str8_lit_comp("function"),
str8_lit_comp("method"),
str8_lit_comp("member_ptr"),
str8_lit_comp("struct"),
str8_lit_comp("class"),
str8_lit_comp("union"),
str8_lit_comp("enum"),
str8_lit_comp("typedef"),
str8_lit_comp("struct"),
str8_lit_comp("union"),
str8_lit_comp("class"),
str8_lit_comp("enum"),
str8_lit_comp("bitfield"),
str8_lit_comp("variadic"),
str8_lit_comp("collection"),
str8_lit_comp("Cannot divide by zero."),
str8_lit_comp("Invalid operation."),
str8_lit_comp("Invalid operation types."),
str8_lit_comp("Failed memory read."),
str8_lit_comp("Failed register read."),
str8_lit_comp("Invalid frame base address."),
str8_lit_comp("Invalid module base address."),
str8_lit_comp("Invalid thread-local storage base address."),
str8_lit_comp("Insufficient evaluation machine stack space."),
str8_lit_comp("Malformed bytecode."),
};
C_LINKAGE_END
+16 -8
View File
@@ -74,7 +74,12 @@ E_TypeKind_IncompleteClass,
E_TypeKind_IncompleteEnum,
E_TypeKind_Bitfield,
E_TypeKind_Variadic,
E_TypeKind_Collection,
E_TypeKind_Set,
E_TypeKind_Lens,
E_TypeKind_LensSpec,
E_TypeKind_MetaExpr,
E_TypeKind_MetaDisplayName,
E_TypeKind_MetaDescription,
E_TypeKind_COUNT,
E_TypeKind_FirstBasic = E_TypeKind_Void,
E_TypeKind_LastBasic = E_TypeKind_ComplexF128,
@@ -86,6 +91,8 @@ E_TypeKind_FirstSigned2 = E_TypeKind_S8,
E_TypeKind_LastSigned2 = E_TypeKind_S512,
E_TypeKind_FirstIncomplete = E_TypeKind_IncompleteStruct,
E_TypeKind_LastIncomplete = E_TypeKind_IncompleteEnum,
E_TypeKind_FirstMeta = E_TypeKind_MetaExpr,
E_TypeKind_LastMeta = E_TypeKind_MetaDescription,
} E_TypeKind;
typedef U32 E_ExprKind;
@@ -124,20 +131,21 @@ E_ExprKind_BitOr,
E_ExprKind_LogAnd,
E_ExprKind_LogOr,
E_ExprKind_Ternary,
E_ExprKind_Call,
E_ExprKind_LeafBytecode,
E_ExprKind_LeafMember,
E_ExprKind_LeafStringLiteral,
E_ExprKind_LeafBool,
E_ExprKind_LeafU64,
E_ExprKind_LeafF64,
E_ExprKind_LeafF32,
E_ExprKind_LeafIdent,
E_ExprKind_LeafIdentifier,
E_ExprKind_LeafOffset,
E_ExprKind_LeafValue,
E_ExprKind_LeafFilePath,
E_ExprKind_TypeIdent,
E_ExprKind_Ptr,
E_ExprKind_Array,
E_ExprKind_Func,
E_ExprKind_Unsigned,
E_ExprKind_Define,
E_ExprKind_COUNT,
} E_ExprKindEnum;
@@ -160,11 +168,11 @@ E_InterpretationCode_COUNT,
C_LINKAGE_BEGIN
extern String8 e_token_kind_strings[6];
extern String8 e_expr_kind_strings[48];
extern String8 e_type_kind_basic_string_table[61];
extern U8 e_type_kind_basic_byte_size_table[61];
extern String8 e_expr_kind_strings[49];
extern E_OpInfo e_expr_kind_op_info_table[49];
extern String8 e_interpretation_code_display_strings[11];
extern E_OpInfo e_expr_kind_op_info_table[48];
extern U8 e_kind_basic_byte_size_table[56];
extern String8 e_kind_basic_string_table[56];
C_LINKAGE_END
@@ -1,127 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Built-In View Rules
//
// @view_rule_info
//
// NOTE(rjf): View rules are subtle in that they may impact any subset of the
// eval visualization pipeline. The "array" view rule, for example, functions
// by tweaking the type of an eval from `X *` to `X (*)[N]` (where N is
// computed from whatever expression is specified by the view rule). The "list"
// view rule, on the other hand, does not require any changes to the actual
// eval nor its type - instead, it follows an alternative path in constructing
// "viz blocks", and then constructing "viz rows" from those blocks. Compare
// these to the simpler 'dec', 'bin', or 'oct' rules, which simply tweak the
// radix used when stringizing numbers, which is something that only occurs in
// single-line eval stringization building.
//
// As such, each view rule specification has a mask, which determines which
// stages it may be used for. For a given view rule specification, if the bit
// corresponding to a particular eval stage is set, then that view rule spec-
// -ification also includes a hook which can be called from that stage.
//
// Below is a list of the stages in the eval visualization pipeline, as well as
// abbreviations which are used in the tables.
//
// expr resolution, "xp" -> provides a chance for a view rule to make
// modifications to expression trees that it is
// applied to
//
// viz block prod, "vb" -> given a resolved eval, produce a list of non-
// windowed "viz blocks", which correspond to one or
// many contiguous rows in a watch-window-style UI.
// one level of expanded struct members, with no sub-
// expansions, would be one viz block. if one of those
// members - in the middle - were expanded too, then
// it would require three viz blocks - one for the
// members before the sub-expansion, one for the
// sub expansion members, and one for the members
// after, and so on. this is done recursively.
//
// viz row prod, "vr" -> given a list of viz blocks, a windowed list of viz
// rows may be produced. each of these rows has info
// for building actual UI in e.g. a watch window -
// whether or not the row can be expanded, whether or
// not the row's value can be edited, what the edit-
// able string is for a row, what the display string
// is for a row, what the expression string is for a
// row, what the type is for a row, and so on.
//
// line stringize, "ls" -> this is the stage used to produce display strings
// in the "viz row prod" stage, as well as basically
// any time UI needs to display the result of an eval
// in a single line. this also occurs recursively,
// descending into members & elements as needed,
// constrained by # of available pixels and font size
// and so on.
//
// row ui build, "ru" -> finally, after the previous stages are completed,
// ui can finally be built according to all of the
// per-row information produced. this is the stage
// where view rules can insert their own arbitrary ui
// on a per-row basis.
//
// view ui build, "vu" -> view rules which want to supply more sophisticated
// visualizers have the ability to provide full
// arbitrary UI hooks, which can either be produced
// in a minified form via watch views, or via a
// standalone tab.
//
// A few other bits are included for various ways in which a view rule may be
// applied throughout the eval visualization pipeline. A list follows:
//
// inherited, "ih" -> is this view rule included, or not included, in
// child expansions?
//
// expandable, "ex" -> does this view rule force the ability to expand
// an expression, even if traditional analysis of type
// info would not allow expansion?
//
// Not all of these stages are specified at this layer, however, since the
// "df_core" layer is for the non-graphical core debugger features. So the
// information pertaining to the eval visualization pipeline stages which
// do require graphical subsystems (e.g. UI, fonts, rendering) are specified
// in the "df_gfx" layer.
//
// For any view rules in this layer which also have graphical features, they
// are specified in both tables under the same name.
@table(coverage_check name name_lower string ih ex xr xe display_name docs schema description)
EV_ViewRuleTable:
{
{x Default default "default" - - - x "Default" - "" "" }
{x Array array "array" - - x - "Array" x "x:{expr}" "Specifies that a pointer points to N elements, rather than only 1." }
{x List list "list" - - - x "Array" x "x:{expr}" "Specifies that a pointer points to N elements, rather than only 1." }
{x Slice slice "slice" - - x - "Slice" x "" "Specifies that a pointer within a struct, also containing an integer, points to the number of elements encoded by the integer." }
{x ByteSwap bswap "bswap" x - x - "Byte Swap" x "" "Specifies that all integral evaluations should be byte-swapped, such that their endianness is reversed." }
{x Cast cast "cast" - - x - "Cast" x "x:{type}" "Specifies that the expression to which the view rule is applied should be casted to the provided type." }
{x Wrap wrap "wrap" - - x - "Wrap" x "x:{expr}" "Specifies that the expression should be wrapped with the view-rule-specified expression, which will refer to the original expression as `$expr`." }
{x Only only "only" x - x - "Only" x "" "Specifies that only the provided member names should be shown in user-defined-type expansions." }
{x Omit omit "omit" x - x - "Omit" x "" "Specifies that the provided member names should not be shown in user-defined-type expansions." }
{x Bin bin "bin" x - - - "Display In Binary" x "" "Specifies that all numeric values should be shown in base 2 (binary)." }
{x Oct oct "oct" x - - - "Display In Octal" x "" "Specifies that all numeric values should be shown in base 8 (octal)." }
{x Dec dec "dec" x - - - "Display In Decimal" x "" "Specifies that all numeric values should be shown in base 10 (decimal)." }
{x Hex hex "hex" x - - - "Display In Hexadecimal" x "" "Specifies that all numeric values should be shown in base 16 (hexadecimal)." }
{x NoAddress no_addr "no_addr" x - - - "Omit Addresses" x "" "Specifies that addresses should be omitted from visualizations, if possible." }
}
@enum EV_ViewRuleKind:
{
@expand(EV_ViewRuleTable a) `$(a.name)`,
COUNT,
}
@gen
{
@expand(EV_ViewRuleTable a) `$(a.xr == "x" -> "EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(" .. a.name_lower .. ");")`;
@expand(EV_ViewRuleTable a) `$(a.xe == "x" -> "EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_DEF(" .. a.name_lower .. ");")`;
@expand(EV_ViewRuleTable a) `$(a.xe == "x" -> "EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_DEF(" .. a.name_lower .. ");")`;
}
@data(EV_ViewRuleInfo) @c_file ev_builtin_view_rule_info_table:
{
@expand(EV_ViewRuleTable a)
```{str8_lit_comp("$(a.string)"), (EV_ViewRuleInfoFlag_Inherited*$(a.ih == "x"))|(EV_ViewRuleInfoFlag_Expandable*$(a.ex == "x")), $(a.xr == "x" -> "EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME("..a.name_lower..")") $(a.xr != "x" -> "EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity)"), $(a.xe == "x" -> "EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME("..a.name_lower..")") $(a.xe != "x" -> "EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil)"), $(a.xe == "x" -> "EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME("..a.name_lower..")") $(a.xe != "x" -> "EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil)"), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) }```;
}
@@ -1,557 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: View Rule Tree Info Extraction Helpers
internal U64
ev_base_offset_from_eval(E_Eval eval)
{
if(e_type_kind_is_pointer_or_ref(e_type_kind_from_key(eval.type_key)))
{
eval = e_value_eval_from_eval(eval);
}
return eval.value.u64;
}
internal E_Value
ev_value_from_params(MD_Node *params)
{
Temp scratch = scratch_begin(0, 0);
String8 expr = md_string_from_children(scratch.arena, params);
E_Eval eval = e_eval_from_string(scratch.arena, expr);
E_Eval value_eval = e_value_eval_from_eval(eval);
scratch_end(scratch);
return value_eval.value;
}
internal E_TypeKey
ev_type_key_from_params(MD_Node *params)
{
Temp scratch = scratch_begin(0, 0);
String8 expr = md_string_from_children(scratch.arena, params);
E_TokenArray tokens = e_token_array_from_text(scratch.arena, expr);
E_Parse parse = e_parse_type_from_text_tokens(scratch.arena, expr, &tokens);
E_TypeKey type_key = e_type_from_expr(parse.expr);
scratch_end(scratch);
return type_key;
}
internal E_Value
ev_value_from_params_key(MD_Node *params, String8 key)
{
Temp scratch = scratch_begin(0, 0);
MD_Node *key_node = md_child_from_string(params, key, 0);
String8 expr = md_string_from_children(scratch.arena, key_node);
E_Eval eval = e_eval_from_string(scratch.arena, expr);
E_Eval value_eval = e_value_eval_from_eval(eval);
scratch_end(scratch);
return value_eval.value;
}
internal Rng1U64
ev_range_from_eval_params(E_Eval eval, MD_Node *params)
{
Temp scratch = scratch_begin(0, 0);
U64 size = ev_value_from_params_key(params, str8_lit("size")).u64;
E_TypeKey type_key = e_type_unwrap(eval.type_key);
E_TypeKind type_kind = e_type_kind_from_key(type_key);
E_TypeKey direct_type_key = e_type_unwrap(e_type_direct_from_key(eval.type_key));
E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key);
if(size == 0 && e_type_kind_is_pointer_or_ref(type_kind) && (direct_type_kind == E_TypeKind_Struct ||
direct_type_kind == E_TypeKind_Union ||
direct_type_kind == E_TypeKind_Class ||
direct_type_kind == E_TypeKind_Array))
{
size = e_type_byte_size_from_key(e_type_direct_from_key(e_type_unwrap(eval.type_key)));
}
if(size == 0 && eval.mode == E_Mode_Offset && (type_kind == E_TypeKind_Struct ||
type_kind == E_TypeKind_Union ||
type_kind == E_TypeKind_Class ||
type_kind == E_TypeKind_Array))
{
size = e_type_byte_size_from_key(e_type_unwrap(eval.type_key));
}
if(size == 0)
{
size = 16384;
}
Rng1U64 result = {0};
result.min = ev_base_offset_from_eval(eval);
result.max = result.min + size;
scratch_end(scratch);
return result;
}
internal Arch
ev_arch_from_eval_params(E_Eval eval, MD_Node *params)
{
Arch arch = Arch_Null;
MD_Node *arch_node = md_child_from_string(params, str8_lit("arch"), 0);
String8 arch_kind_string = arch_node->first->string;
if(str8_match(arch_kind_string, str8_lit("x64"), StringMatchFlag_CaseInsensitive))
{
arch = Arch_x64;
}
return arch;
}
////////////////////////////////
//~ rjf: default
typedef struct EV_DefaultExpandAccel EV_DefaultExpandAccel;
struct EV_DefaultExpandAccel
{
E_MemberArray members;
E_EnumValArray enum_vals;
U64 array_count;
B32 array_need_extra_deref;
B32 is_ptr2ptr;
};
EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_DEF(default)
{
Temp scratch = scratch_begin(&arena, 1);
U64 total_row_count = 0;
EV_DefaultExpandAccel *accel = push_array(arena, EV_DefaultExpandAccel, 1);
////////////////////////////
//- rjf: unpack expression type info
//
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, expr);
E_TypeKey type_key = e_type_unwrap(irtree.type_key);
E_TypeKind type_kind = e_type_kind_from_key(type_key);
E_TypeKey direct_type_key = e_type_unwrap(e_type_direct_from_key(type_key));
E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key);
////////////////////////////
//- rjf: structs/unions/classes -> expansions generate rows for all members
//
if((type_kind == E_TypeKind_Struct ||
type_kind == E_TypeKind_Union ||
type_kind == E_TypeKind_Class) ||
(e_type_kind_is_pointer_or_ref(type_kind) && (direct_type_kind == E_TypeKind_Struct ||
direct_type_kind == E_TypeKind_Union ||
direct_type_kind == E_TypeKind_Class)))
{
E_TypeKey struct_type_key = e_type_kind_is_pointer_or_ref(type_kind) ? direct_type_key : type_key;
accel->members = e_type_data_members_from_key__cached(struct_type_key);
total_row_count = accel->members.count;
}
////////////////////////////
//- rjf: enums -> expansions generate rows for all members
//
else if(type_kind == E_TypeKind_Enum ||
(e_type_kind_is_pointer_or_ref(type_kind) && direct_type_kind == E_TypeKind_Enum))
{
E_Type *type = e_type_from_key(arena, e_type_kind_is_pointer_or_ref(type_kind) ? direct_type_key : type_key);
accel->enum_vals.v = type->enum_vals;
accel->enum_vals.count = type->count;
total_row_count = accel->enum_vals.count;
}
////////////////////////////
//- rjf: arrays -> expansions generate rows for all elements
//
else if(type_kind == E_TypeKind_Array ||
(e_type_kind_is_pointer_or_ref(type_kind) && direct_type_kind == E_TypeKind_Array))
{
B32 need_extra_deref = e_type_kind_is_pointer_or_ref(type_kind);
E_Expr *array_expr = need_extra_deref ? e_expr_ref_deref(arena, expr) : expr;
E_Type *type = e_type_from_key(arena, need_extra_deref ? direct_type_key : type_key);
total_row_count = type->count;
accel->array_count = type->count;
accel->array_need_extra_deref = need_extra_deref;
}
////////////////////////////
//- rjf: pointer-to-pointer -> expansions generate dereference
//
else if(e_type_kind_is_pointer_or_ref(type_kind) && e_type_kind_is_pointer_or_ref(direct_type_kind))
{
total_row_count = 1;
accel->is_ptr2ptr = 1;
}
////////////////////////////
//- rjf: package result
//
EV_ExpandInfo result = {0};
{
result.user_data = accel;
result.row_count = total_row_count;
}
scratch_end(scratch);
return result;
}
EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_DEF(default)
{
EV_DefaultExpandAccel *accel = (EV_DefaultExpandAccel *)user_data;
EV_ExpandRangeInfo result = {0};
U64 needed_row_count = dim_1u64(idx_range);
////////////////////////////
//- rjf: fill with members
//
if(accel->members.count != 0)
{
E_MemberArray *members = &accel->members;
result.row_exprs_count = Min(needed_row_count, members->count);
result.row_exprs = push_array(arena, E_Expr *, result.row_exprs_count);
result.row_strings = push_array(arena, String8, result.row_exprs_count);
result.row_view_rules = push_array(arena, String8, result.row_exprs_count);
result.row_members = push_array(arena, E_Member *, result.row_exprs_count);
for EachIndex(row_expr_idx, result.row_exprs_count)
{
E_Member *member = &members->v[idx_range.min + row_expr_idx];
result.row_exprs[row_expr_idx] = e_expr_ref_member_access(arena, expr, member->name);
result.row_members[row_expr_idx] = member;
}
}
////////////////////////////
//- rjf: fill with enum vals
//
else if(accel->enum_vals.count != 0)
{
E_EnumValArray *enumvals = &accel->enum_vals;
result.row_exprs_count = Min(needed_row_count, enumvals->count);
result.row_exprs = push_array(arena, E_Expr *, result.row_exprs_count);
result.row_strings = push_array(arena, String8, result.row_exprs_count);
result.row_view_rules = push_array(arena, String8, result.row_exprs_count);
result.row_members = push_array(arena, E_Member *, result.row_exprs_count);
for EachIndex(row_expr_idx, result.row_exprs_count)
{
E_EnumVal *enumval = &enumvals->v[idx_range.min + row_expr_idx];
result.row_exprs[row_expr_idx] = e_expr_ref_member_access(arena, expr, enumval->name);
result.row_members[row_expr_idx] = &e_member_nil;
}
}
////////////////////////////
//- rjf: fill with array indices
//
else if(accel->array_count != 0)
{
E_Expr *array_expr = accel->array_need_extra_deref ? e_expr_ref_deref(arena, expr) : expr;
result.row_exprs_count = Min(needed_row_count, accel->array_count);
result.row_exprs = push_array(arena, E_Expr *, result.row_exprs_count);
result.row_strings = push_array(arena, String8, result.row_exprs_count);
result.row_view_rules = push_array(arena, String8, result.row_exprs_count);
result.row_members = push_array(arena, E_Member *, result.row_exprs_count);
for EachIndex(row_expr_idx, result.row_exprs_count)
{
result.row_exprs[row_expr_idx] = e_expr_ref_array_index(arena, array_expr, idx_range.min + row_expr_idx);
result.row_members[row_expr_idx] = &e_member_nil;
}
}
////////////////////////////
//- rjf: fill with ptr-to-ptr deref
//
else if(accel->is_ptr2ptr)
{
result.row_exprs_count = 1;
result.row_exprs = push_array(arena, E_Expr *, result.row_exprs_count);
result.row_strings = push_array(arena, String8, result.row_exprs_count);
result.row_view_rules = push_array(arena, String8, result.row_exprs_count);
result.row_members = push_array(arena, E_Member *, result.row_exprs_count);
result.row_exprs[0] = e_expr_ref_deref(arena, expr);
result.row_members[0] = &e_member_nil;
}
return result;
}
////////////////////////////////
//~ rjf: "array"
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(array)
{
Temp scratch = scratch_begin(&arena, 1);
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, expr);
E_TypeKey type_key = irtree.type_key;
E_TypeKind type_kind = e_type_kind_from_key(type_key);
if(e_type_kind_is_pointer_or_ref(type_kind))
{
E_Value count = ev_value_from_params(params);
E_TypeKey element_type_key = e_type_ptee_from_key(type_key);
E_TypeKey array_type_key = e_type_key_cons_array(element_type_key, count.u64);
E_TypeKey ptr_type_key = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, array_type_key, 0);
expr = e_expr_ref_cast(arena, ptr_type_key, expr);
}
scratch_end(scratch);
return expr;
}
////////////////////////////////
//~ rjf: "list"
EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_DEF(list)
{
EV_ExpandInfo info = {0};
return info;
}
EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_DEF(list)
{
EV_ExpandRangeInfo info = {0};
return info;
}
////////////////////////////////
//~ rjf: "slice"
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(slice)
{
Temp scratch = scratch_begin(&arena, 1);
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, expr);
E_TypeKind type_kind = e_type_kind_from_key(irtree.type_key);
if(type_kind == E_TypeKind_Struct || type_kind == E_TypeKind_Class)
{
// rjf: unpack members
E_MemberArray members = e_type_data_members_from_key__cached(irtree.type_key);
// rjf: choose base pointer & count members
E_Member *base_ptr_member = 0;
E_Member *count_member = 0;
for(U64 idx = 0; idx < members.count; idx += 1)
{
E_Member *member = &members.v[idx];
E_TypeKey member_type = e_type_unwrap(member->type_key);
E_TypeKind member_type_kind = e_type_kind_from_key(member_type);
if(count_member == 0 && e_type_kind_is_integer(member_type_kind))
{
count_member = member;
}
if(base_ptr_member == 0 && e_type_kind_is_pointer_or_ref(member_type_kind))
{
base_ptr_member = &members.v[idx];
}
if(count_member != 0 && base_ptr_member != 0)
{
break;
}
}
// rjf: evaluate count member, determine count
U64 count = 0;
if(count_member != 0)
{
E_Expr *count_member_expr = e_expr_ref_member_access(scratch.arena, expr, count_member->name);
E_Eval count_member_eval = e_eval_from_expr(scratch.arena, count_member_expr);
E_Eval count_member_value_eval = e_value_eval_from_eval(count_member_eval);
count = count_member_value_eval.value.u64;
}
// rjf: generate new struct slice type
E_TypeKey slice_type_key = zero_struct;
if(base_ptr_member != 0 && count_member != 0)
{
String8 struct_name = e_type_string_from_key(scratch.arena, irtree.type_key);
E_TypeKey element_type_key = e_type_ptee_from_key(base_ptr_member->type_key);
E_TypeKey array_type_key = e_type_key_cons_array(element_type_key, count);
E_TypeKey sized_base_ptr_type_key = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, array_type_key, 0);
E_MemberList slice_type_members = {0};
e_member_list_push(scratch.arena, &slice_type_members, count_member);
e_member_list_push(scratch.arena, &slice_type_members, &(E_Member){.kind = E_MemberKind_DataField, .type_key = sized_base_ptr_type_key, .name = base_ptr_member->name, .pretty_name = base_ptr_member->pretty_name, .off = base_ptr_member->off});
E_MemberArray slice_type_members_array = e_member_array_from_list(scratch.arena, &slice_type_members);
slice_type_key = e_type_key_cons(.arch = e_type_state->ctx->primary_module->arch,
.kind = E_TypeKind_Struct,
.name = struct_name,
.members = slice_type_members_array.v,
.count = slice_type_members_array.count);
}
// rjf: generate new expression tree - addr of struct, cast-to-ptr, deref
if(base_ptr_member != 0 && count_member != 0)
{
expr = e_expr_ref_addr(arena, expr);
expr = e_expr_ref_cast(arena, e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, slice_type_key, 0), expr);
expr = e_expr_ref_deref(arena, expr);
}
}
scratch_end(scratch);
return expr;
}
////////////////////////////////
//~ rjf: "bswap"
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(bswap)
{
expr = e_expr_ref_bswap(arena, expr);
return expr;
}
////////////////////////////////
//~ rjf: "cast"
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(cast)
{
E_TypeKey type_key = ev_type_key_from_params(params);
expr = e_expr_ref_cast(arena, type_key, expr);
return expr;
}
////////////////////////////////
//~ rjf: "wrap"
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(wrap)
{
String8 wrap_string = md_string_from_children(arena, params);
E_Expr *wrap_expr = e_parse_expr_from_text(arena, wrap_string);
E_Expr *new_root_expr = wrap_expr;
if(wrap_expr != &e_expr_nil)
{
Temp scratch = scratch_begin(&arena, 1);
typedef struct Task Task;
struct Task
{
Task *next;
E_Expr *parent;
E_Expr *expr;
};
Task start_task = {0, &e_expr_nil, wrap_expr};
Task *first_task = &start_task;
Task *last_task = first_task;
for(Task *t = first_task; t != 0; t = t->next)
{
if(t->expr->kind == E_ExprKind_LeafIdent && str8_match(t->expr->string, str8_lit("$expr"), 0))
{
E_Expr *original_expr_ref = e_expr_ref(arena, expr);
if(t->parent != &e_expr_nil)
{
e_expr_insert_child(t->parent, t->expr, original_expr_ref);
e_expr_remove_child(t->parent, t->expr);
}
else
{
new_root_expr = original_expr_ref;
}
}
else for(E_Expr *child = t->expr->first; child != &e_expr_nil; child = child->next)
{
Task *task = push_array(scratch.arena, Task, 1);
SLLQueuePush(first_task, last_task, task);
task->parent = t->expr;
task->expr = child;
}
}
scratch_end(scratch);
}
return new_root_expr;
}
////////////////////////////////
//~ rjf: "only"
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(only)
{
Temp scratch = scratch_begin(&arena, 1);
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, expr);
E_TypeKey type_key = irtree.type_key;
E_TypeKind type_kind = e_type_kind_from_key(type_key);
E_TypeKey direct_type_key = e_type_direct_from_key(type_key);
E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key);
B32 is_ptr = e_type_kind_is_pointer_or_ref(type_kind);
E_TypeKey struct_type_key = is_ptr ? direct_type_key : type_key;
E_TypeKind struct_type_kind = is_ptr ? direct_type_kind : type_kind;
if(struct_type_kind == E_TypeKind_Struct ||
struct_type_kind == E_TypeKind_Union ||
struct_type_kind == E_TypeKind_Class)
{
E_MemberArray current_members = e_type_data_members_from_key__cached(struct_type_key);
E_MemberList new_members = {0};
for MD_EachNode(node, params->first)
{
for EachIndex(idx, current_members.count)
{
if(str8_match(node->string, current_members.v[idx].name, 0))
{
e_member_list_push(scratch.arena, &new_members, &current_members.v[idx]);
break;
}
}
}
E_MemberArray new_members_array = e_member_array_from_list(scratch.arena, &new_members);
E_TypeKey new_type = {0};
if(new_members_array.count == 1 && new_members_array.v[0].off == 0)
{
new_type = new_members_array.v[0].type_key;
}
else
{
String8 struct_name = e_type_string_from_key(scratch.arena, struct_type_key);
new_type = e_type_key_cons(.kind = E_TypeKind_Struct, .name = struct_name, .members = new_members_array.v, .count = new_members_array.count);
}
if(!is_ptr)
{
expr = e_expr_ref_addr(arena, expr);
}
expr = e_expr_ref_cast(arena, e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, new_type, 0), expr);
if(!is_ptr)
{
expr = e_expr_ref_deref(arena, expr);
}
}
scratch_end(scratch);
return expr;
}
////////////////////////////////
//~ rjf: "omit"
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(omit)
{
Temp scratch = scratch_begin(&arena, 1);
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, expr);
E_TypeKey type_key = irtree.type_key;
E_TypeKind type_kind = e_type_kind_from_key(type_key);
E_TypeKey direct_type_key = e_type_direct_from_key(type_key);
E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key);
B32 is_ptr = e_type_kind_is_pointer_or_ref(type_kind);
E_TypeKey struct_type_key = is_ptr ? direct_type_key : type_key;
E_TypeKind struct_type_kind = is_ptr ? direct_type_kind : type_kind;
if(struct_type_kind == E_TypeKind_Struct ||
struct_type_kind == E_TypeKind_Union ||
struct_type_kind == E_TypeKind_Class)
{
E_MemberArray current_members = e_type_data_members_from_key__cached(struct_type_key);
E_MemberList new_members = {0};
for EachIndex(idx, current_members.count)
{
B32 include = 1;
for MD_EachNode(node, params->first)
{
if(str8_match(node->string, current_members.v[idx].name, 0))
{
include = 0;
break;
}
}
if(include)
{
e_member_list_push(scratch.arena, &new_members, &current_members.v[idx]);
}
}
E_MemberArray new_members_array = e_member_array_from_list(scratch.arena, &new_members);
E_TypeKey new_type = {0};
String8 struct_name = e_type_string_from_key(scratch.arena, struct_type_key);
new_type = e_type_key_cons(.kind = E_TypeKind_Struct, .name = struct_name, .members = new_members_array.v, .count = new_members_array.count);
if(!is_ptr)
{
expr = e_expr_ref_addr(arena, expr);
}
expr = e_expr_ref_cast(arena, e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, new_type, 0), expr);
if(!is_ptr)
{
expr = e_expr_ref_deref(arena, expr);
}
}
scratch_end(scratch);
return expr;
}
@@ -1,17 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef EVAL_VISUALIZATION_BUILTIN_VIEW_RULES_H
#define EVAL_VISUALIZATION_BUILTIN_VIEW_RULES_H
////////////////////////////////
//~ rjf: View Rule Tree Info Extraction Helpers
internal U64 ev_base_offset_from_eval(E_Eval eval);
internal E_Value ev_value_from_params(MD_Node *params);
internal E_TypeKey ev_type_key_from_params(MD_Node *params);
internal E_Value ev_value_from_params_key(MD_Node *params, String8 key);
internal Rng1U64 ev_range_from_eval_params(E_Eval eval, MD_Node *params);
internal Arch ev_arch_from_eval_params(E_Eval eval, MD_Node *params);
#endif // EVAL_VISUALIZATION_BUILTIN_VIEW_RULES_H
File diff suppressed because it is too large Load Diff
+120 -187
View File
@@ -75,31 +75,7 @@ struct EV_View
};
////////////////////////////////
//~ rjf: View Rule Instance Types
typedef struct EV_ViewRule EV_ViewRule;
struct EV_ViewRule
{
MD_Node *root;
};
typedef struct EV_ViewRuleNode EV_ViewRuleNode;
struct EV_ViewRuleNode
{
EV_ViewRuleNode *next;
EV_ViewRule v;
};
typedef struct EV_ViewRuleList EV_ViewRuleList;
struct EV_ViewRuleList
{
EV_ViewRuleNode *first;
EV_ViewRuleNode *last;
U64 count;
};
////////////////////////////////
//~ rjf: View Rule Info Types
//~ rjf: Expansion Rule Types
typedef struct EV_ExpandInfo EV_ExpandInfo;
struct EV_ExpandInfo
@@ -111,82 +87,46 @@ struct EV_ExpandInfo
B32 rows_default_expanded;
};
typedef struct EV_ExpandRangeInfo EV_ExpandRangeInfo;
struct EV_ExpandRangeInfo
{
U64 row_exprs_count;
String8 *row_strings;
String8 *row_view_rules;
E_Expr **row_exprs;
E_Member **row_members;
};
#define EV_EXPAND_RULE_INFO_FUNCTION_SIG(name) EV_ExpandInfo name(Arena *arena, EV_View *view, String8 filter, E_Expr *expr)
#define EV_EXPAND_RULE_INFO_FUNCTION_NAME(name) ev_expand_rule_info__##name
#define EV_EXPAND_RULE_INFO_FUNCTION_DEF(name) internal EV_EXPAND_RULE_INFO_FUNCTION_SIG(EV_EXPAND_RULE_INFO_FUNCTION_NAME(name))
typedef EV_EXPAND_RULE_INFO_FUNCTION_SIG(EV_ExpandRuleInfoHookFunctionType);
#define EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_SIG(name) E_Expr *name(Arena *arena, E_Expr *expr, MD_Node *params)
#define EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(name) ev_view_rule_expr_resolution__##name
#define EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(name) internal EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_SIG(EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(name))
#define EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_SIG(name) EV_ExpandInfo name(Arena *arena, EV_View *view, String8 filter, E_Expr *expr, MD_Node *params)
#define EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(name) ev_view_rule_expr_expand_info__##name
#define EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_DEF(name) internal EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_SIG(EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(name))
#define EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_SIG(name) EV_ExpandRangeInfo name(Arena *arena, EV_View *view, String8 filter, E_Expr *expr, MD_Node *params, Rng1U64 idx_range, void *user_data)
#define EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(name) ev_view_rule_expr_expand_range_info__##name
#define EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_DEF(name) internal EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_SIG(EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(name))
#define EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_SIG(name) U64 name(U64 num, void *user_data)
#define EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(name) ev_view_rule_expr_expand_id_from_num_##name
#define EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_DEF(name) internal EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_SIG(EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(name))
#define EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_SIG(name) U64 name(U64 id, void *user_data)
#define EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(name) ev_view_rule_expr_expand_num_from_id_##name
#define EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_DEF(name) internal EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_SIG(EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(name))
typedef EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_SIG(EV_ViewRuleExprResolutionHookFunctionType);
typedef EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_SIG(EV_ViewRuleExprExpandInfoHookFunctionType);
typedef EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_SIG(EV_ViewRuleExprExpandRangeInfoHookFunctionType);
typedef EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_SIG(EV_ViewRuleExprExpandIDFromNumHookFunctionType);
typedef EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_SIG(EV_ViewRuleExprExpandNumFromIDHookFunctionType);
typedef U32 EV_ViewRuleInfoFlags; // NOTE(rjf): see @view_rule_info
enum
{
EV_ViewRuleInfoFlag_Inherited = (1<<0),
EV_ViewRuleInfoFlag_Expandable = (1<<1),
};
typedef struct EV_ViewRuleInfo EV_ViewRuleInfo;
struct EV_ViewRuleInfo
typedef struct EV_ExpandRule EV_ExpandRule;
struct EV_ExpandRule
{
String8 string;
EV_ViewRuleInfoFlags flags;
EV_ViewRuleExprResolutionHookFunctionType *expr_resolution;
EV_ViewRuleExprExpandInfoHookFunctionType *expr_expand_info;
EV_ViewRuleExprExpandRangeInfoHookFunctionType *expr_expand_range_info;
EV_ViewRuleExprExpandIDFromNumHookFunctionType *expr_expand_id_from_num;
EV_ViewRuleExprExpandIDFromNumHookFunctionType *expr_expand_num_from_id;
EV_ExpandRuleInfoHookFunctionType *info;
};
typedef struct EV_ViewRuleInfoNode EV_ViewRuleInfoNode;
struct EV_ViewRuleInfoNode
typedef struct EV_ExpandRuleNode EV_ExpandRuleNode;
struct EV_ExpandRuleNode
{
EV_ViewRuleInfoNode *next;
EV_ViewRuleInfo v;
EV_ExpandRuleNode *next;
EV_ExpandRule v;
};
typedef struct EV_ViewRuleInfoSlot EV_ViewRuleInfoSlot;
struct EV_ViewRuleInfoSlot
typedef struct EV_ExpandRuleSlot EV_ExpandRuleSlot;
struct EV_ExpandRuleSlot
{
EV_ViewRuleInfoNode *first;
EV_ViewRuleInfoNode *last;
EV_ExpandRuleNode *first;
EV_ExpandRuleNode *last;
};
typedef struct EV_ViewRuleInfoTable EV_ViewRuleInfoTable;
struct EV_ViewRuleInfoTable
typedef struct EV_ExpandRuleTable EV_ExpandRuleTable;
struct EV_ExpandRuleTable
{
EV_ViewRuleInfoSlot *slots;
EV_ExpandRuleSlot *slots;
U64 slots_count;
};
typedef struct EV_ExpandRuleTagPair EV_ExpandRuleTagPair;
struct EV_ExpandRuleTagPair
{
EV_ExpandRule *rule;
E_Expr *tag;
};
////////////////////////////////
//~ rjf: Blocks
@@ -206,18 +146,17 @@ struct EV_Block
// rjf: split index, relative to parent's space
U64 split_relative_idx;
// rjf: expression / visualization info
// rjf: evaluation info
String8 string;
E_Expr *expr;
EV_ViewRuleList *view_rules;
EV_ViewRuleInfo *expand_view_rule_info;
MD_Node *expand_view_rule_params;
void *expand_view_rule_info_user_data;
E_Eval eval;
String8 filter;
E_TypeExpandInfo type_expand_info;
E_TypeExpandRule *type_expand_rule;
EV_ExpandInfo viz_expand_info;
EV_ExpandRule *viz_expand_rule;
// rjf: expansion info
U64 row_count;
B32 single_item;
B32 rows_default_expanded;
};
typedef struct EV_BlockTree EV_BlockTree;
@@ -256,66 +195,32 @@ struct EV_BlockRangeList
typedef struct EV_Row EV_Row;
struct EV_Row
{
EV_Row *next;
// rjf: block hierarchy info
EV_Block *block;
EV_Key key;
// rjf: row size/scroll info
U64 visual_size;
String8 edit_string;
E_Eval eval;
};
typedef struct EV_WindowedRowNode EV_WindowedRowNode;
struct EV_WindowedRowNode
{
EV_WindowedRowNode *next;
U64 visual_size_skipped;
U64 visual_size_chopped;
// rjf: expression / visualization info
String8 string;
E_Expr *expr;
E_Member *member;
EV_ViewRuleList *view_rules;
EV_Row row;
};
typedef struct EV_WindowedRowList EV_WindowedRowList;
struct EV_WindowedRowList
{
EV_Row *first;
EV_Row *last;
EV_WindowedRowNode *first;
EV_WindowedRowNode *last;
U64 count;
U64 count_before_visual;
U64 count_before_semantic;
};
////////////////////////////////
//~ rjf: Automatic Type -> View Rule Map Types
typedef struct EV_AutoViewRuleNode EV_AutoViewRuleNode;
struct EV_AutoViewRuleNode
{
EV_AutoViewRuleNode *next;
E_TypeKey key;
String8 view_rule;
B32 is_required;
};
typedef struct EV_AutoViewRuleSlot EV_AutoViewRuleSlot;
struct EV_AutoViewRuleSlot
{
EV_AutoViewRuleNode *first;
EV_AutoViewRuleNode *last;
U64 count;
};
typedef struct EV_AutoViewRuleTable EV_AutoViewRuleTable;
struct EV_AutoViewRuleTable
{
EV_AutoViewRuleSlot *slots;
U64 slots_count;
};
////////////////////////////////
//~ rjf: Generated Code
#include "generated/eval_visualization.meta.h"
////////////////////////////////
//~ rjf: String Generation Types
@@ -324,34 +229,74 @@ enum
{
EV_StringFlag_ReadOnlyDisplayRules = (1<<0),
EV_StringFlag_PrettyNames = (1<<1),
EV_StringFlag_DisableAddresses = (1<<2),
EV_StringFlag_DisableStrings = (1<<3),
EV_StringFlag_DisableChars = (1<<4),
EV_StringFlag_DisableStringQuotes = (1<<5),
};
typedef struct EV_StringParams EV_StringParams;
struct EV_StringParams
{
EV_StringFlags flags;
U32 radix;
U32 min_digits;
U8 digit_group_separator;
String8 filter;
B32 limit_strings;
U64 limit_strings_size;
};
typedef struct EV_StringIterTask EV_StringIterTask;
struct EV_StringIterTask
{
EV_StringIterTask *next;
EV_StringParams params;
E_Eval eval;
U64 idx;
S32 depth;
B32 redirect_to_sets_and_structs;
void *user_data;
};
typedef struct EV_StringIter EV_StringIter;
struct EV_StringIter
{
EV_StringIterTask *top_task;
EV_StringIterTask *free_task;
};
////////////////////////////////
//~ rjf: Nil/Identity View Rule Hooks
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(identity);
EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_DEF(nil);
EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_DEF(nil);
EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_DEF(identity);
EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_DEF(identity);
EV_EXPAND_RULE_INFO_FUNCTION_DEF(nil);
////////////////////////////////
//~ rjf: Globals
global read_only EV_ViewRuleInfo ev_nil_view_rule_info =
global read_only EV_ExpandRule ev_nil_expand_rule =
{
{0},
0,
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity),
EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil),
EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil),
EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity),
EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity),
EV_EXPAND_RULE_INFO_FUNCTION_NAME(nil),
};
thread_static EV_ExpandRuleTable *ev_view_rule_info_table = 0;
global read_only EV_Block ev_nil_block =
{
&ev_nil_block,
&ev_nil_block,
&ev_nil_block,
&ev_nil_block,
&ev_nil_block,
{0},
0,
{0},
{{0}, {0}, {0}, &e_expr_nil, &e_irnode_nil},
{0},
{0},
&e_type_expand_rule__default,
{0},
&ev_nil_expand_rule,
};
thread_static EV_ViewRuleInfoTable *ev_view_rule_info_table = 0;
global read_only EV_ViewRuleList ev_nil_view_rule_list = {0};
thread_static EV_AutoViewRuleTable *ev_auto_view_rule_table = 0;
global read_only EV_Block ev_nil_block = {&ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, {0}, 0, {0}, &e_expr_nil, &ev_nil_view_rule_list, &ev_nil_view_rule_info};
////////////////////////////////
//~ rjf: Key Functions
@@ -367,6 +312,7 @@ internal U64 ev_hash_from_key(EV_Key key);
//~ rjf: Type Info Helpers
//- rjf: type info -> expandability/editablity
internal E_TypeKey ev_expansion_type_from_key(E_TypeKey type_key);
internal B32 ev_type_key_and_mode_is_expandable(E_TypeKey type_key, E_Mode mode);
internal B32 ev_type_key_is_editable(E_TypeKey type_key);
@@ -387,54 +333,37 @@ internal void ev_key_set_view_rule(EV_View *view, EV_Key key, String8 view_rule_
////////////////////////////////
//~ rjf: View Rule Info Table Building / Selection / Lookups
internal void ev_view_rule_info_table_push(Arena *arena, EV_ViewRuleInfoTable *table, EV_ViewRuleInfo *info);
internal void ev_view_rule_info_table_push_builtins(Arena *arena, EV_ViewRuleInfoTable *table);
internal void ev_select_view_rule_info_table(EV_ViewRuleInfoTable *table);
internal EV_ViewRuleInfo *ev_view_rule_info_from_string(String8 string);
////////////////////////////////
//~ rjf: Automatic Type -> View Rule Table Building / Selection / Lookups
internal void ev_auto_view_rule_table_push_new(Arena *arena, EV_AutoViewRuleTable *table, E_TypeKey type_key, String8 view_rule, B32 is_required);
internal void ev_select_auto_view_rule_table(EV_AutoViewRuleTable *table);
internal EV_ViewRuleList *ev_auto_view_rules_from_type_key(Arena *arena, E_TypeKey type_key, B32 gather_required, B32 gather_optional);
////////////////////////////////
//~ rjf: View Rule Instance List Building
internal void ev_view_rule_list_push_tree(Arena *arena, EV_ViewRuleList *list, MD_Node *root);
internal void ev_view_rule_list_push_string(Arena *arena, EV_ViewRuleList *list, String8 string);
internal EV_ViewRuleList *ev_view_rule_list_from_string(Arena *arena, String8 string);
internal EV_ViewRuleList *ev_view_rule_list_from_expr_fastpaths(Arena *arena, String8 string);
internal EV_ViewRuleList *ev_view_rule_list_from_inheritance(Arena *arena, EV_ViewRuleList *src);
internal EV_ViewRuleList *ev_view_rule_list_copy(Arena *arena, EV_ViewRuleList *src);
internal void ev_view_rule_list_concat_in_place(EV_ViewRuleList *dst, EV_ViewRuleList **src);
////////////////////////////////
//~ rjf: Expression Resolution (Dynamic Overrides, View Rule Application)
internal E_Expr *ev_resolved_from_expr(Arena *arena, E_Expr *expr, EV_ViewRuleList *view_rules);
internal void ev_expand_rule_table_push(Arena *arena, EV_ExpandRuleTable *table, EV_ExpandRule *info);
#define ev_expand_rule_table_push_new(arena, table, ...) ev_expand_rule_table_push((arena), (table), &(EV_ExpandRule){__VA_ARGS__})
internal void ev_select_expand_rule_table(EV_ExpandRuleTable *table);
internal EV_ExpandRule *ev_expand_rule_from_string(String8 string);
internal EV_ExpandRule *ev_expand_rule_from_type_key(E_TypeKey type_key);
////////////////////////////////
//~ rjf: Block Building
internal EV_BlockTree ev_block_tree_from_expr(Arena *arena, EV_View *view, String8 filter, String8 string, E_Expr *expr, EV_ViewRuleList *view_rules);
internal EV_BlockTree ev_block_tree_from_string(Arena *arena, EV_View *view, String8 filter, String8 string, EV_ViewRuleList *view_rules);
internal EV_BlockTree ev_block_tree_from_eval(Arena *arena, EV_View *view, String8 filter, E_Eval root_eval);
internal U64 ev_depth_from_block(EV_Block *block);
////////////////////////////////
//~ rjf: Block Coordinate Spaces
internal U64 ev_block_id_from_num(EV_Block *block, U64 num);
internal U64 ev_block_num_from_id(EV_Block *block, U64 id);
internal EV_BlockRangeList ev_block_range_list_from_tree(Arena *arena, EV_BlockTree *block_tree);
internal EV_BlockRange ev_block_range_from_num(EV_BlockRangeList *block_ranges, U64 num);
internal EV_Key ev_key_from_num(EV_BlockRangeList *block_ranges, U64 num);
internal U64 ev_num_from_key(EV_BlockRangeList *block_ranges, EV_Key key);
internal U64 ev_vnum_from_num(EV_BlockRangeList *block_ranges, U64 num);
internal U64 ev_num_from_vnum(EV_BlockRangeList *block_ranges, U64 vidx);
////////////////////////////////
//~ rjf: Row Building
internal EV_WindowedRowList ev_windowed_row_list_from_block_range_list(Arena *arena, EV_View *view, String8 filter, EV_BlockRangeList *block_ranges, Rng1U64 visible_range);
internal String8 ev_expr_string_from_row(Arena *arena, EV_Row *row, EV_StringFlags flags);
internal EV_WindowedRowList ev_windowed_row_list_from_block_range_list(Arena *arena, EV_View *view, EV_BlockRangeList *block_ranges, Rng1U64 vnum_range);
internal EV_Row *ev_row_from_num(Arena *arena, EV_View *view, EV_BlockRangeList *block_ranges, U64 num);
internal EV_WindowedRowList ev_rows_from_num_range(Arena *arena, EV_View *view, EV_BlockRangeList *block_ranges, Rng1U64 num_range);
internal B32 ev_eval_is_expandable(E_Eval eval);
internal B32 ev_row_is_expandable(EV_Row *row);
internal B32 ev_row_is_editable(EV_Row *row);
@@ -445,7 +374,11 @@ internal B32 ev_row_is_editable(EV_Row *row);
internal String8 ev_string_from_ascii_value(Arena *arena, U8 val);
internal String8 ev_string_from_hresult_facility_code(U32 code);
internal String8 ev_string_from_hresult_code(U32 code);
internal String8 ev_string_from_simple_typed_eval(Arena *arena, EV_StringFlags flags, U32 radix, U32 min_digits, E_Eval eval);
internal String8 ev_string_from_simple_typed_eval(Arena *arena, EV_StringParams *params, E_Eval eval);
internal String8 ev_escaped_from_raw_string(Arena *arena, String8 raw);
//- rjf: tree stringification iterator
internal EV_StringIter *ev_string_iter_begin(Arena *arena, E_Eval eval, EV_StringParams *params);
internal B32 ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string);
#endif // EVAL_VISUALIZATION_CORE_H
@@ -2,4 +2,3 @@
// Licensed under the MIT license (https://opensource.org/license/mit/)
#include "eval_visualization_core.c"
#include "eval_visualization_builtin_view_rules.c"
@@ -5,6 +5,5 @@
#define EVAL_VISUALIZATION_INC_H
#include "eval_visualization_core.h"
#include "eval_visualization_builtin_view_rules.h"
#endif // EVAL_VISUALIZATION_INC_H
@@ -1,26 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
//- GENERATED CODE
C_LINKAGE_BEGIN
EV_ViewRuleInfo ev_builtin_view_rule_info_table[14] =
{
{str8_lit_comp("default"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(default) , EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(default) , EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
{str8_lit_comp("array"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(array) , EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
{str8_lit_comp("list"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(list) , EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(list) , EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
{str8_lit_comp("slice"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(slice) , EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
{str8_lit_comp("bswap"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(bswap) , EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
{str8_lit_comp("cast"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(cast) , EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
{str8_lit_comp("wrap"), (EV_ViewRuleInfoFlag_Inherited*0)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(wrap) , EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
{str8_lit_comp("only"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(only) , EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
{str8_lit_comp("omit"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(omit) , EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
{str8_lit_comp("bin"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
{str8_lit_comp("oct"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
{str8_lit_comp("dec"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
{str8_lit_comp("hex"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
{str8_lit_comp("no_addr"), (EV_ViewRuleInfoFlag_Inherited*1)|(EV_ViewRuleInfoFlag_Expandable*0), EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_NAME(nil), EV_VIEW_RULE_EXPR_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), EV_VIEW_RULE_EXPR_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity) },
};
C_LINKAGE_END
@@ -1,39 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
//- GENERATED CODE
#ifndef EVAL_VISUALIZATION_META_H
#define EVAL_VISUALIZATION_META_H
typedef enum EV_ViewRuleKind
{
EV_ViewRuleKind_Default,
EV_ViewRuleKind_Array,
EV_ViewRuleKind_List,
EV_ViewRuleKind_Slice,
EV_ViewRuleKind_ByteSwap,
EV_ViewRuleKind_Cast,
EV_ViewRuleKind_Wrap,
EV_ViewRuleKind_Only,
EV_ViewRuleKind_Omit,
EV_ViewRuleKind_Bin,
EV_ViewRuleKind_Oct,
EV_ViewRuleKind_Dec,
EV_ViewRuleKind_Hex,
EV_ViewRuleKind_NoAddress,
EV_ViewRuleKind_COUNT,
} EV_ViewRuleKind;
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(array);
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(slice);
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(bswap);
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(cast);
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(wrap);
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(only);
EV_VIEW_RULE_EXPR_RESOLUTION_FUNCTION_DEF(omit);
EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_DEF(default);
EV_VIEW_RULE_EXPR_EXPAND_INFO_FUNCTION_DEF(list);
EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_DEF(default);
EV_VIEW_RULE_EXPR_EXPAND_RANGE_INFO_FUNCTION_DEF(list);
#endif // EVAL_VISUALIZATION_META_H

Some files were not shown because too many files have changed in this diff Show More