mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-16 17:12:23 -07:00
Merge remote-tracking branch 'EpicGamesExt/dev'
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 -------------------------------------------------------
|
||||
|
||||
Binary file not shown.
+14
-6
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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" }
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
+664
-660
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+271
-327
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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] =
|
||||
|
||||
@@ -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
@@ -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, ¶ms->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, ¶ms->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, ¶ms_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, ¶ms_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, ¶ms);
|
||||
dasm_u2p_dequeue_req(scratch.arena, &root, &hash, ¶ms);
|
||||
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, ¶ms))
|
||||
{
|
||||
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, ¶ms.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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
@@ -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
@@ -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 = ¶ms->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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -21,6 +21,9 @@ DMN_EventKindTable:
|
||||
{Memory}
|
||||
{DebugString}
|
||||
{SetThreadName}
|
||||
{SetThreadColor}
|
||||
{SetBreakpoint}
|
||||
{UnsetBreakpoint}
|
||||
}
|
||||
|
||||
@table(name)
|
||||
|
||||
@@ -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] =
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ®s);
|
||||
{
|
||||
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 = ®s.dr0;
|
||||
switch(trap_idx)
|
||||
{
|
||||
default:{}break;
|
||||
case 0:{addr_reg = ®s.dr0;}break;
|
||||
case 1:{addr_reg = ®s.dr1;}break;
|
||||
case 2:{addr_reg = ®s.dr2;}break;
|
||||
case 3:{addr_reg = ®s.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, ®s);
|
||||
}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, ®s);
|
||||
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, ®s);
|
||||
regs.dr7.u64 = 0;
|
||||
dmn_w32_thread_write_reg_block(child->arch, child->handle, ®s);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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 = §ion_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 = §ion_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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = §ions.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 = §ions.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;
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+305
-346
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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 = §ions.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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)")`;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+1103
-6
File diff suppressed because it is too large
Load Diff
@@ -6,4 +6,3 @@
|
||||
#include "eval/eval_parse.c"
|
||||
#include "eval/eval_ir.c"
|
||||
#include "eval/eval_interpret.c"
|
||||
#include "eval/eval_bundles.c"
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+108
-60
@@ -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
File diff suppressed because it is too large
Load Diff
+10
-213
@@ -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
File diff suppressed because it is too large
Load Diff
+115
-256
@@ -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
@@ -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
|
||||
|
||||
@@ -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, ¤t_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, ¤t_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
@@ -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
Reference in New Issue
Block a user