Merge remote-tracking branch 'EpicGamesExt/master'

This commit is contained in:
2025-08-06 18:45:17 -04:00
240 changed files with 48696 additions and 31890 deletions
+19 -1
View File
@@ -31,4 +31,22 @@ jobs:
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
call build ${{ matrix.target }} ${{ matrix.compiler }} ${{ matrix.mode }} || exit /b 1
call build %${{ matrix.target }}% %${{ matrix.compiler }}% %${{ matrix.mode }}% || exit /b 1
run-torture:
runs-on: windows-2022
steps:
# - name: Install ASAN
# shell: cmd
# run: |
# "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe" modify --installPath "C:\Program Files\Microsoft Visual Studio\2022\Enterprise" --quiet --force --norestart --add Microsoft.VisualStudio.Component.VC.ASAN
- name: checkout
uses: actions/checkout@v2
- name: run-torture
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
call build radlink asan debug no_meta || exit /b 1
call build torture debug no_meta || exit /b 1
cd build
torture -l:radlink || exit /b 1
+1
View File
@@ -123,6 +123,7 @@ if "%strip_lib_debug%"=="1" set didbuild=1 && %compile% ..\src\strip_
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
if "%torture%"=="1" set didbuild=1 && %compile% ..\src\torture\torture.c %compile_link% %out%torture.exe || exit /b1
if "%mule_peb_trample%"=="1" (
set didbuild=1
if exist mule_peb_trample.exe move mule_peb_trample.exe mule_peb_trample_old_%random%.exe
Binary file not shown.
BIN
View File
Binary file not shown.
+10 -2
View File
@@ -46,7 +46,14 @@ load_paths =
commands =
{
//- 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, },
.f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
// .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
//- rjf: [raddbg wsl]
// .f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
//- rjf: [scratch]
.f2 = { .win = "build radbin", .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, },
@@ -55,10 +62,11 @@ commands =
// .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: [radbin]
.f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
// .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .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 = "wsl ./build/raddbg", .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, },
+1 -1
View File
@@ -159,7 +159,7 @@
#endif
#if !defined(BUILD_VERSION_PATCH)
# define BUILD_VERSION_PATCH 20
# define BUILD_VERSION_PATCH 21
#endif
#define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH)
+23
View File
@@ -636,3 +636,26 @@ u64_array_bsearch(U64 *arr, U64 count, U64 value)
return max_U64;
}
////////////////////////////////
internal U64
index_of_zero_u32(U32 *ptr, U64 count)
{
for (U64 i = 0; i < count; i += 1) {
if (ptr[i] == 0) {
return i;
}
}
return max_U64;
}
internal U64
index_of_zero_u64(U64 *ptr, U64 count)
{
for (U64 i = 0; i < count; i += 1) {
if (ptr[i] == 0) {
return i;
}
}
return max_U64;
}
+8 -2
View File
@@ -148,6 +148,7 @@
#define MemoryCopyStruct(d,s) MemoryCopy((d),(s),sizeof(*(d)))
#define MemoryCopyArray(d,s) MemoryCopy((d),(s),sizeof(d))
#define MemoryCopyTyped(d,s,c) MemoryCopy((d),(s),sizeof(*(d))*(c))
#define MemoryCopyStr8(dst, s) MemoryCopy(dst, (s).str, (s).size)
#define MemoryZero(s,z) memset((s),0,(z))
#define MemoryZeroStruct(s) MemoryZero((s),sizeof(*(s)))
@@ -314,7 +315,6 @@ CheckNil(nil,p) ? \
#endif
#if ASAN_ENABLED
#pragma comment(lib, "clang_rt.asan-x86_64.lib")
C_LINKAGE void __asan_poison_memory_region(void const volatile *addr, size_t size);
C_LINKAGE void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
# define AsanPoisonMemoryRegion(addr, size) __asan_poison_memory_region((addr), (size))
@@ -348,7 +348,8 @@ C_LINKAGE void __asan_unpoison_memory_region(void const volatile *addr, size_t s
#endif
#define PtrFromInt(i) (void*)(i)
#define Compose64Bit(a,b) ((((U64)a) << 32) | ((U64)b));
#define Compose64Bit(a,b) ((((U64)a) << 32) | ((U64)b))
#define Compose32Bit(a,b) ((((U32)a) << 16) | ((U32)b))
#define AlignPow2(x,b) (((x) + (b) - 1)&(~((b) - 1)))
#define AlignDownPow2(x,b) ((x)&(~((b) - 1)))
#define AlignPadPow2(x,b) ((0-(x)) & ((b) - 1))
@@ -924,4 +925,9 @@ internal U64 ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_dat
internal U64 u64_array_bsearch(U64 *arr, U64 count, U64 value);
////////////////////////////////
internal U64 index_of_zero_u32(U32 *ptr, U64 count);
internal U64 index_of_zero_u64(U64 *ptr, U64 count);
#endif // BASE_CORE_H
+9 -1
View File
@@ -81,6 +81,14 @@ internal F32 length_3f32(Vec3F32 v) {F32 c = sqrt_f3
internal Vec3F32 normalize_3f32(Vec3F32 v) {v = scale_3f32(v, 1.f/length_3f32(v)); return v;}
internal Vec3F32 mix_3f32(Vec3F32 a, Vec3F32 b, F32 t) {Vec3F32 c = {mix_1f32(a.x, b.x, t), mix_1f32(a.y, b.y, t), mix_1f32(a.z, b.z, t)}; return c;}
internal Vec3F32 cross_3f32(Vec3F32 a, Vec3F32 b) {Vec3F32 c = {a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x}; return c;}
internal Vec3F32 xform_3f32(Vec3F32 v, Mat3x3F32 m)
{
Vec3F32 result;
result.x = v.x*m.v[0][0] + v.y*m.v[1][0] + v.z*m.v[2][0];
result.y = v.x*m.v[0][1] + v.y*m.v[1][1] + v.z*m.v[2][1];
result.z = v.x*m.v[0][2] + v.y*m.v[1][2] + v.z*m.v[2][2];
return result;
}
internal Vec3S32 vec_3s32(S32 x, S32 y, S32 z) {Vec3S32 v = {x, y, z}; return v;}
internal Vec3S32 add_3s32(Vec3S32 a, Vec3S32 b) {Vec3S32 c = {a.x+b.x, a.y+b.y, a.z+b.z}; return c;}
@@ -750,7 +758,7 @@ rng1u64_array_from_list(Arena *arena, Rng1U64List *list)
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)
if(arr.count > 0 && arr.v[0].min < value && value < arr.v[arr.count-1].max)
{
U64 l = 0;
U64 r = arr.count - 1;
+1
View File
@@ -485,6 +485,7 @@ internal F32 length_3f32(Vec3F32 v);
internal Vec3F32 normalize_3f32(Vec3F32 v);
internal Vec3F32 mix_3f32(Vec3F32 a, Vec3F32 b, F32 t);
internal Vec3F32 cross_3f32(Vec3F32 a, Vec3F32 b);
internal Vec3F32 xform_3f32(Vec3F32 v, Mat3x3F32 m);
#define v3s32(x, y, z) vec_3s32((x), (y), (z))
internal Vec3S32 vec_3s32(S32 x, S32 y, S32 z);
+368 -35
View File
@@ -480,28 +480,30 @@ str8_skip_chop_slashes(String8 string)
//~ rjf: String Formatting & Copying
internal String8
push_str8_cat(Arena *arena, String8 s1, String8 s2){
str8_cat(Arena *arena, String8 s1, String8 s2)
{
String8 str;
str.size = s1.size + s2.size;
str.str = push_array_no_zero(arena, U8, str.size + 1);
MemoryCopy(str.str, s1.str, s1.size);
MemoryCopy(str.str + s1.size, s2.str, s2.size);
str.str[str.size] = 0;
return(str);
return str;
}
internal String8
push_str8_copy(Arena *arena, String8 s){
str8_copy(Arena *arena, String8 s)
{
String8 str;
str.size = s.size;
str.str = push_array_no_zero(arena, U8, str.size + 1);
MemoryCopy(str.str, s.str, s.size);
str.str[str.size] = 0;
return(str);
return str;
}
internal String8
push_str8fv(Arena *arena, char *fmt, va_list args){
str8fv(Arena *arena, char *fmt, va_list args){
va_list args2;
va_copy(args2, args);
U32 needed_bytes = raddbg_vsnprintf(0, 0, fmt, args) + 1;
@@ -510,16 +512,28 @@ push_str8fv(Arena *arena, char *fmt, va_list args){
result.size = raddbg_vsnprintf((char*)result.str, needed_bytes, fmt, args2);
result.str[result.size] = 0;
va_end(args2);
return(result);
return result;
}
internal String8
push_str8f(Arena *arena, char *fmt, ...){
str8f(Arena *arena, char *fmt, ...)
{
va_list args;
va_start(args, fmt);
String8 result = push_str8fv(arena, fmt, args);
va_end(args);
return(result);
return result;
}
internal String8
push_cstr(Arena *arena, String8 str)
{
U64 buffer_size = str.size + 1;
U8 *buffer = push_array_no_zero(arena, U8, buffer_size);
MemoryCopy(buffer, str.str, str.size);
buffer[str.size] = 0;
String8 result = str8(buffer, buffer_size);
return result;
}
////////////////////////////////
@@ -605,36 +619,35 @@ s32_from_str8(String8 string, U32 radix)
internal B32
try_u64_from_str8_c_rules(String8 string, U64 *x)
{
B32 is_integer = 0;
if(str8_is_integer(string, 10) && !str8_match(str8_prefix(string, 1), str8_lit("0"), 0))
U64 radix, prefix_size;
// hex
if(str8_match(str8_prefix(string, 2), str8_lit("0x"), StringMatchFlag_CaseInsensitive))
{
is_integer = 1;
*x = u64_from_str8(string, 10);
radix = 0x10, prefix_size = 2;
}
// binary
else if(str8_match(str8_prefix(string, 2), str8_lit("0b"), StringMatchFlag_CaseInsensitive))
{
radix = 2, prefix_size = 2;
}
// octal
else if(str8_match(str8_prefix(string, 1), str8_lit("0"), StringMatchFlag_CaseInsensitive) && string.size > 1)
{
radix = 010, prefix_size = 1;
}
// decimal
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))
{
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))
{
is_integer = 1;
*x = u64_from_str8(hex_string, 2);
}
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))
{
is_integer = 1;
*x = u64_from_str8(oct_string, 010);
}
}
radix = 10, prefix_size = 0;
}
String8 integer = str8_skip(string, prefix_size);
B32 is_integer = str8_is_integer(integer, radix);
if(is_integer)
{
*x = u64_from_str8(integer, radix);
}
return is_integer;
}
@@ -971,6 +984,15 @@ str8_list_push(Arena *arena, String8List *list, String8 string){
return(node);
}
internal String8Node *
str8_list_push_cstr(Arena *arena, String8List *list, String8 string)
{
String8Node *node = str8_list_push(arena, list, string);
local_persist String8 null = str8_lit_comp("\0");
str8_list_push(arena, list, null);
return node;
}
internal String8Node*
str8_list_push_front(Arena *arena, String8List *list, String8 string){
String8Node *node = push_array_no_zero(arena, String8Node, 1);
@@ -1147,6 +1169,23 @@ str8_list_from_flags(Arena *arena, String8List *list,
}
}
////////////////////////////////
//~ rjf: Basic Data Structure Stringification Helpers
internal String8List
numeric_str8_list_from_data(Arena *arena, U32 radix, String8 data, U64 stride)
{
String8List strs = {0};
U64 count = data.size/stride;
for EachIndex(idx, count)
{
U64 val = 0;
MemoryCopy(&val, data.str + idx*stride, stride);
str8_list_push(arena, &strs, str8_from_u64(arena, val, radix, 0, 0));
}
return strs;
}
////////////////////////////////
//~ rjf; String Arrays
@@ -1171,6 +1210,16 @@ str8_array_from_list(Arena *arena, String8List *list)
return array;
}
internal String8Array *
str8_array_from_list_arr(Arena *arena, String8List *lists, U64 count)
{
String8Array *result = push_array(arena, String8Array, count);
for (U64 idx = 0; idx < count; idx += 1) {
result[idx] = str8_array_from_list(arena, &lists[idx]);
}
return result;
}
internal String8Array
str8_array_reserve(Arena *arena, U64 count)
{
@@ -1424,7 +1473,8 @@ str8_path_list_resolve_dots_in_place(String8List *path, PathStyle style)
}
internal String8
str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style){
str8_path_list_join_by_style(Arena *arena, String8List *path, PathStyle style)
{
StringJoin params = {0};
switch(style)
{
@@ -1497,6 +1547,228 @@ str8_txt_pt_pair_from_string(String8 string)
return pair;
}
////////////////////////////////
//~ rjf: Relative <-> Absolute Path
internal String8
path_relative_dst_from_absolute_dst_src(Arena *arena, String8 dst, String8 src)
{
Temp scratch = scratch_begin(&arena, 1);
// rjf: gather path parts
String8 dst_name = str8_skip_last_slash(dst);
String8 src_folder = src;
String8 dst_folder = str8_chop_last_slash(dst);
String8List src_folders = str8_split_path(scratch.arena, src_folder);
String8List dst_folders = str8_split_path(scratch.arena, dst_folder);
// rjf: count # of backtracks to get from src -> dest
U64 num_backtracks = src_folders.node_count;
for(String8Node *src_n = src_folders.first, *bp_n = dst_folders.first;
src_n != 0 && bp_n != 0;
src_n = src_n->next, bp_n = bp_n->next)
{
if(str8_match(src_n->string, bp_n->string, path_match_flags_from_os(operating_system_from_context())))
{
num_backtracks -= 1;
}
else
{
break;
}
}
// rjf: only build relative string if # of backtracks is not the entire `src`.
// if getting to `dst` from `src` requires erasing the entire `src`, then the
// only possible way to get to `dst` from `src` is via absolute path.
String8 dst_path = {0};
if(num_backtracks >= src_folders.node_count)
{
dst_path = dst;
}
else
{
// rjf: build backtrack parts
String8List dst_path_strs = {0};
for(U64 idx = 0; idx < num_backtracks; idx += 1)
{
str8_list_push(scratch.arena, &dst_path_strs, str8_lit(".."));
}
// rjf: build parts of dst which are unique from src
{
B32 unique_from_src = 0;
for(String8Node *src_n = src_folders.first, *bp_n = dst_folders.first;
bp_n != 0;
bp_n = bp_n->next)
{
if(!unique_from_src && (src_n == 0 || !str8_match(src_n->string, bp_n->string, path_match_flags_from_os(operating_system_from_context()))))
{
unique_from_src = 1;
}
if(unique_from_src)
{
str8_list_push(scratch.arena, &dst_path_strs, bp_n->string);
}
if(src_n != 0)
{
src_n = src_n->next;
}
}
}
// rjf: build file name
str8_list_push(scratch.arena, &dst_path_strs, dst_name);
// rjf: join
StringJoin join = {0};
{
join.sep = str8_lit("/");
}
dst_path = str8_list_join(arena, &dst_path_strs, &join);
}
scratch_end(scratch);
return dst_path;
}
internal String8
path_absolute_dst_from_relative_dst_src(Arena *arena, String8 dst, String8 src)
{
String8 result = dst;
PathStyle dst_style = path_style_from_str8(dst);
if(dst.size != 0 && dst_style == PathStyle_Relative)
{
Temp scratch = scratch_begin(&arena, 1);
String8 dst_from_src_absolute = push_str8f(scratch.arena, "%S/%S", src, dst);
String8List dst_from_src_absolute_parts = str8_split_path(scratch.arena, dst_from_src_absolute);
PathStyle dst_from_src_absolute_style = path_style_from_str8(src);
str8_path_list_resolve_dots_in_place(&dst_from_src_absolute_parts, dst_from_src_absolute_style);
result = str8_path_list_join_by_style(arena, &dst_from_src_absolute_parts, dst_from_src_absolute_style);
scratch_end(scratch);
}
return result;
}
////////////////////////////////
//~ rjf: Path Normalization
internal String8List
path_normalized_list_from_string(Arena *arena, String8 path_string, PathStyle *style_out)
{
// rjf: analyze path
PathStyle path_style = path_style_from_str8(path_string);
String8List path = str8_split_path(arena, path_string);
// rjf: resolve dots
str8_path_list_resolve_dots_in_place(&path, path_style);
// rjf: return
if(style_out != 0)
{
*style_out = path_style;
}
return path;
}
internal String8
path_normalized_from_string(Arena *arena, String8 path_string)
{
Temp scratch = scratch_begin(&arena, 1);
PathStyle style = PathStyle_Relative;
String8List path = path_normalized_list_from_string(scratch.arena, path_string, &style);
String8 result = str8_path_list_join_by_style(arena, &path, style);
scratch_end(scratch);
return result;
}
internal B32
path_match_normalized(String8 left, String8 right)
{
Temp scratch = scratch_begin(0, 0);
String8 left_normalized = path_normalized_from_string(scratch.arena, left);
String8 right_normalized = path_normalized_from_string(scratch.arena, right);
B32 result = str8_match(left_normalized, right_normalized, StringMatchFlag_CaseInsensitive);
scratch_end(scratch);
return result;
}
////////////////////////////////
//~ rjf: Misc. Path Helpers
internal PathStyle
path_style_from_string(String8 string)
{
for (U64 i = 0; i < ArrayCount(g_path_style_map); ++i)
{
if(str8_match(g_path_style_map[i].string, string, StringMatchFlag_CaseInsensitive))
{
return g_path_style_map[i].path_style;
}
}
return PathStyle_Null;
}
internal String8
string_from_path_style(PathStyle style)
{
Assert(style < ArrayCount(g_path_style_map));
return g_path_style_map[style].string;
}
internal String8
path_separator_string_from_style(PathStyle style)
{
String8 result = str8_zero();
switch (style)
{
case PathStyle_Null: break;
case PathStyle_Relative: break;
case PathStyle_WindowsAbsolute: result = str8_lit("\\"); break;
case PathStyle_UnixAbsolute: result = str8_lit("/"); break;
}
return result;
}
internal StringMatchFlags
path_match_flags_from_os(OperatingSystem os)
{
StringMatchFlags flags = StringMatchFlag_SlashInsensitive;
switch(os)
{
default:{}break;
case OperatingSystem_Windows:
{
flags |= StringMatchFlag_CaseInsensitive;
}break;
case OperatingSystem_Linux:
case OperatingSystem_Mac:
{
// NOTE(rjf): no-op
}break;
}
return flags;
}
internal String8
path_convert_slashes(Arena *arena, String8 path, PathStyle path_style)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = str8_split_path(scratch.arena, path);
StringJoin join = {0};
join.sep = path_separator_string_from_style(path_style);
String8 result = str8_list_join(arena, &list, &join);
scratch_end(scratch);
return result;
}
internal String8
path_replace_file_extension(Arena *arena, String8 file_name, String8 ext)
{
String8 file_name_no_ext = str8_chop_last_dot(file_name);
String8 result = push_str8f(arena, "%S.%S", file_name_no_ext, ext);
return result;
}
////////////////////////////////
//~ rjf: UTF-8 & UTF-16 Decoding/Encoding
@@ -2219,7 +2491,7 @@ fuzzy_match_find(Arena *arena, String8 needle, String8 haystack)
U64 find_pos = 0;
for(;find_pos < haystack.size;)
{
find_pos = str8_find_needle(haystack, find_pos, needle_n->string, StringMatchFlag_CaseInsensitive);
find_pos = str8_find_needle(haystack, find_pos, needle_n->string, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive);
B32 is_in_gathered_ranges = 0;
for(FuzzyMatchRangeNode *n = result.first; n != 0; n = n->next)
{
@@ -2486,6 +2758,67 @@ str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out)
}
////////////////////////////////
internal int
str8_compar(String8 a, String8 b, B32 ignore_case)
{
int cmp = 0;
U64 size = Min(a.size, b.size);
if (ignore_case) {
for (U64 i = 0; i < size; ++i) {
U8 la = char_to_lower(a.str[i]);
U8 lb = char_to_lower(b.str[i]);
if (la < lb) {
cmp = -1;
break;
} else if (la > lb) {
cmp = +1;
break;
}
}
} else {
for (U64 i = 0; i < size; ++i) {
if (a.str[i] < b.str[i]) {
cmp = -1;
break;
} else if (a.str[i] > b.str[i]) {
cmp = +1;
break;
}
}
}
if (cmp == 0) {
// shorter prefix must precede longer prefixes
if (a.size > b.size) {
cmp = +1;
} else if (b.size > a.size) {
cmp = -1;
}
}
return cmp;
}
internal int
str8_compar_ignore_case(const void *a, const void *b)
{
return str8_compar(*(String8*)a, *(String8*)b, 1);
}
internal int
str8_compar_case_sensitive(const void *a, const void *b)
{
return str8_compar(*(String8*)a, *(String8*)b, 0);
}
internal int
str8_is_before_case_sensitive(const void *a, const void *b)
{
int cmp = str8_compar_case_sensitive(a, b);
return cmp < 0;
}
//~ rjf: Basic String Hashes
#if !defined(XXH_IMPLEMENTATION)
+39 -4
View File
@@ -228,10 +228,16 @@ internal String8 str8_skip_chop_slashes(String8 string);
////////////////////////////////
//~ rjf: String Formatting & Copying
internal String8 push_str8_cat(Arena *arena, String8 s1, String8 s2);
internal String8 push_str8_copy(Arena *arena, String8 s);
internal String8 push_str8fv(Arena *arena, char *fmt, va_list args);
internal String8 push_str8f(Arena *arena, char *fmt, ...);
internal String8 str8_cat(Arena *arena, String8 s1, String8 s2);
internal String8 str8_copy(Arena *arena, String8 s);
internal String8 str8fv(Arena *arena, char *fmt, va_list args);
internal String8 str8f(Arena *arena, char *fmt, ...);
// TODO(rjf): remove these once we're ready to convert all usages:
#define push_str8_cat(arena, s1, s2) str8_cat((arena), (s1), (s2))
#define push_str8_copy(arena, s) str8_copy((arena), (s))
#define push_str8fv(arena, fmt, args) str8fv((arena), (fmt), (args))
#define push_str8f(arena, ...) str8f((arena), __VA_ARGS__)
internal String8 push_cstr(Arena *arena, String8 str); // TODO(rjf): this is unnecessary - this is implied by `push_str8_copy`. need to remove.
////////////////////////////////
//~ rjf: String <=> Integer Conversions
@@ -285,6 +291,11 @@ internal String8List str8_list_split_by_string_chars(Arena *arena, String8List
internal String8 str8_list_join(Arena *arena, String8List *list, StringJoin *optional_params);
internal void str8_list_from_flags(Arena *arena, String8List *list, U32 flags, String8 *flag_string_table, U32 flag_string_count);
////////////////////////////////
//~ rjf: Basic Data Stringification Helpers
internal String8List numeric_str8_list_from_data(Arena *arena, U32 radix, String8 data, U64 stride);
////////////////////////////////
//~ rjf; String Arrays
@@ -328,6 +339,29 @@ internal String8 str8_path_list_join_by_style(Arena *arena, String8List *pat
internal String8TxtPtPair str8_txt_pt_pair_from_string(String8 string);
////////////////////////////////
//~ rjf: Relative <-> Absolute Path
internal String8 path_relative_dst_from_absolute_dst_src(Arena *arena, String8 dst, String8 src);
internal String8 path_absolute_dst_from_relative_dst_src(Arena *arena, String8 dst, String8 src);
////////////////////////////////
//~ rjf: Path Normalization
internal String8List path_normalized_list_from_string(Arena *arena, String8 path, PathStyle *style_out);
internal String8 path_normalized_from_string(Arena *arena, String8 path);
internal B32 path_match_normalized(String8 left, String8 right);
////////////////////////////////
//~ rjf: Misc. Path Helpers
internal PathStyle path_style_from_string(String8 string);
internal String8 string_from_path_style(PathStyle style);
internal String8 path_separator_string_from_style(PathStyle style);
internal StringMatchFlags path_match_flags_from_os(OperatingSystem os);
internal String8 path_convert_slashes(Arena *arena, String8 path, PathStyle path_style);
internal String8 path_replace_file_extension(Arena *arena, String8 file_name, String8 ext);
////////////////////////////////
//~ rjf: UTF-8 & UTF-16 Decoding/Encoding
@@ -418,6 +452,7 @@ internal void str8_serial_push_u16(Arena *arena, String8List *srl, U16 x);
internal void str8_serial_push_u8(Arena *arena, String8List *srl, U8 x);
internal void str8_serial_push_cstr(Arena *arena, String8List *srl, String8 str);
internal void str8_serial_push_string(Arena *arena, String8List *srl, String8 str);
internal void str8_serial_push_cstr(Arena *arena, String8List *srl, String8 str);
#define str8_serial_push_array(arena, srl, ptr, count) str8_serial_push_data(arena, srl, ptr, sizeof(*(ptr)) * (count))
#define str8_serial_push_struct(arena, srl, ptr) str8_serial_push_array(arena, srl, ptr, 1)
+934
View File
@@ -166,6 +166,9 @@ cv_map_encoded_base_pointer(CV_Arch arch, U32 encoded_frame_reg)
}
////////////////////////////////
//~ rjf: Enum -> String
internal String8
cv_string_from_inline_range_kind(CV_InlineRangeKind kind)
{
@@ -176,3 +179,934 @@ cv_string_from_inline_range_kind(CV_InlineRangeKind kind)
return str8_zero();
}
internal String8
cv_string_from_type_index_source(CV_TypeIndexSource ti_source)
{
switch (ti_source) {
case CV_TypeIndexSource_NULL: return str8_lit(""); break;
case CV_TypeIndexSource_TPI: return str8_lit("TPI"); break;
case CV_TypeIndexSource_IPI: return str8_lit("IPI"); break;
case CV_TypeIndexSource_COUNT: break;
}
return str8_zero();
}
internal String8
cv_string_from_language(CV_Language x)
{
switch (x) {
#define X(_n,_i) case _i: return str8_lit(Stringify(_n));
CV_LanguageXList(X)
#undef X
}
return str8_zero();
}
internal String8
cv_string_from_reg_id(Arena *arena, CV_Arch arch, U32 id)
{
String8 result = str8_zero();
switch (arch) {
case CV_Arch_8086: {
switch (id) {
#define X(_N, _ID, ...) case _ID: result = str8_lit(Stringify(_N)); break;
CV_Reg_X86_XList(X)
#undef X
}
} break;
case CV_Arch_X64: {
switch (id) {
#define X(_N, _ID, ...) case _ID: result = str8_lit(Stringify(_N)); break;
CV_Reg_X64_XList(X)
#undef X
}
} break;
default: NotImplemented; break;
}
if (result.size == 0) {
result = push_str8f(arena, "%x", id);
}
return result;
}
internal String8
cv_string_from_member_access(CV_MemberAccess x)
{
switch (x) {
case CV_MemberAccess_Null: break;
case CV_MemberAccess_Private: return str8_lit("Private");
case CV_MemberAccess_Protected: return str8_lit("Protected");
case CV_MemberAccess_Public: return str8_lit("Public");
}
return str8_zero();
}
internal String8
cv_string_from_method_prop(CV_MethodProp x)
{
switch (x) {
case CV_MethodProp_Vanilla: return str8_lit("Vanilla");
case CV_MethodProp_Virtual: return str8_lit("Virtual");
case CV_MethodProp_Static: return str8_lit("Static");
case CV_MethodProp_Friend: return str8_lit("Friend");
case CV_MethodProp_Intro: return str8_lit("Intro");
case CV_MethodProp_PureVirtual: return str8_lit("PureVirtual");
case CV_MethodProp_PureIntro: return str8_lit("PureIntro");
}
return str8_zero();
}
internal String8
cv_string_from_hfa(CV_HFAKind x)
{
switch (x) {
case CV_HFAKind_None: return str8_lit("None");
case CV_HFAKind_Float: return str8_lit("Float");
case CV_HFAKind_Double: return str8_lit("Double");
case CV_HFAKind_Other: return str8_lit("Other");
}
return str8_zero();
}
internal String8
cv_string_from_mcom(CV_MoComUDTKind x)
{
switch (x) {
case CV_MoComUDTKind_None: return str8_lit("None");
case CV_MoComUDTKind_Ref: return str8_lit("Ref");
case CV_MoComUDTKind_Value: return str8_lit("Value");
case CV_MoComUDTKind_Interface: return str8_lit("Interface");
}
return str8_zero();
}
internal String8
cv_string_from_binary_opcode(CV_InlineBinaryAnnotation x)
{
switch (x) {
case CV_InlineBinaryAnnotation_Null: break;
case CV_InlineBinaryAnnotation_CodeOffset: return str8_lit("CodeOffset");
case CV_InlineBinaryAnnotation_ChangeCodeOffsetBase: return str8_lit("ChangeCodeOffsetBase");
case CV_InlineBinaryAnnotation_ChangeCodeOffset: return str8_lit("ChangeCodeOffset");
case CV_InlineBinaryAnnotation_ChangeCodeLength: return str8_lit("ChangeCodeLength");
case CV_InlineBinaryAnnotation_ChangeFile: return str8_lit("ChangeFile");
case CV_InlineBinaryAnnotation_ChangeLineOffset: return str8_lit("ChangeLineOffset");
case CV_InlineBinaryAnnotation_ChangeLineEndDelta: return str8_lit("ChangeLineEndDelta");
case CV_InlineBinaryAnnotation_ChangeRangeKind: return str8_lit("ChangeRangeKind");
case CV_InlineBinaryAnnotation_ChangeColumnStart: return str8_lit("ChangeColumnStart");
case CV_InlineBinaryAnnotation_ChangeColumnEndDelta: return str8_lit("ChangeColumnEndDelta");
case CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset: return str8_lit("ChangeCodeOffsetAndLineOffset");
case CV_InlineBinaryAnnotation_ChangeCodeLengthAndCodeOffset: return str8_lit("ChangeCodeLengthAndCodeOffset");
case CV_InlineBinaryAnnotation_ChangeColumnEnd: return str8_lit("ChangeColumnEnd");
}
return str8_zero();
}
internal String8
cv_string_from_thunk_ordinal(CV_ThunkOrdinal x)
{
switch (x) {
case CV_ThunkOrdinal_NoType: return str8_lit("NoType");
case CV_ThunkOrdinal_Adjustor: return str8_lit("Adjustor");
case CV_ThunkOrdinal_VCall: return str8_lit("VCall");
case CV_ThunkOrdinal_PCode: return str8_lit("PCode");
case CV_ThunkOrdinal_Load: return str8_lit("Load");
case CV_ThunkOrdinal_TrampIncremental: return str8_lit("TrampIncremental");
case CV_ThunkOrdinal_TrampBranchIsland: return str8_lit("TrampBranchIsland");
}
return str8_zero();
}
internal String8
cv_string_from_frame_cookie_kind(CV_FrameCookieKind x)
{
switch (x) {
case CV_FrameCookieKind_Copy: return str8_lit("Copy");
case CV_FrameCookieKind_XorSP: return str8_lit("XorSP");
case CV_FrameCookieKind_XorBP: return str8_lit("XorR13");
}
return str8_zero();
}
internal String8
cv_string_from_generic_style(CV_GenericStyle x)
{
switch (x) {
case CV_GenericStyle_VOID: return str8_lit("VOID");
case CV_GenericStyle_REG: return str8_lit("REG");
case CV_GenericStyle_ICAN: return str8_lit("ICAN");
case CV_GenericStyle_ICAF: return str8_lit("ICAF");
case CV_GenericStyle_IRAN: return str8_lit("IRAN");
case CV_GenericStyle_IRAF: return str8_lit("IRAF");
case CV_GenericStyle_UNUSED: return str8_lit("UNUSED");
}
return str8_zero();
}
internal String8
cv_string_from_trampoline_kind(CV_TrampolineKind x)
{
switch (x) {
case CV_TrampolineKind_Incremental: return str8_lit("Incremental");
case CV_TrampolineKind_BranchIsland: return str8_lit("BranchIsland");
}
return str8_zero();
}
internal String8
cv_string_from_virtual_table_shape_kind(CV_VirtualTableShape x)
{
switch (x) {
case CV_VirtualTableShape_Near: return str8_lit("Near");
case CV_VirtualTableShape_Far: return str8_lit("Far");
case CV_VirtualTableShape_Thin: return str8_lit("Thin");
case CV_VirtualTableShape_Outer: return str8_lit("Outer");
case CV_VirtualTableShape_Meta: return str8_lit("Meta");
case CV_VirtualTableShape_Near32: return str8_lit("Near32");
case CV_VirtualTableShape_Far32: return str8_lit("Far32");
}
return str8_zero();
}
internal String8
cv_string_from_call_kind(CV_CallKind x)
{
switch (x) {
case CV_CallKind_NearC: return str8_lit("NearC");
case CV_CallKind_FarC: return str8_lit("FarC");
case CV_CallKind_NearPascal: return str8_lit("NearPascal");
case CV_CallKind_FarPascal: return str8_lit("FarPascal");
case CV_CallKind_NearFast: return str8_lit("NearFast");
case CV_CallKind_FarFast: return str8_lit("FarFast");
case CV_CallKind_UNUSED: return str8_lit("UNUSED");
case CV_CallKind_NearStd: return str8_lit("NearStd");
case CV_CallKind_FarStd: return str8_lit("FarStd");
case CV_CallKind_NearSys: return str8_lit("NearSys");
case CV_CallKind_FarSys: return str8_lit("FarSys");
case CV_CallKind_This: return str8_lit("This");
case CV_CallKind_Mips: return str8_lit("Mips");
case CV_CallKind_Generic: return str8_lit("Generic");
case CV_CallKind_Alpha: return str8_lit("Alpha");
case CV_CallKind_PPC: return str8_lit("PPC");
case CV_CallKind_HitachiSuperH: return str8_lit("HitachiSuperH");
case CV_CallKind_Arm: return str8_lit("Arm");
case CV_CallKind_AM33: return str8_lit("AM33");
case CV_CallKind_TriCore: return str8_lit("TriCore");
case CV_CallKind_HitachiSuperH5: return str8_lit("HitachiSuperH5");
case CV_CallKind_M32R: return str8_lit("M32R");
case CV_CallKind_Clr: return str8_lit("Clr");
case CV_CallKind_Inline: return str8_lit("Inline");
case CV_CallKind_NearVector: return str8_lit("NearVector");
}
return str8_zero();
}
internal String8
cv_string_from_member_pointer_kind(CV_MemberPointerKind x)
{
switch (x) {
case CV_MemberPointerKind_Undef: return str8_lit("Undef");
case CV_MemberPointerKind_DataSingle: return str8_lit("DataSingle");
case CV_MemberPointerKind_DataMultiple: return str8_lit("DataMultiple");
case CV_MemberPointerKind_DataVirtual: return str8_lit("DataVirtual");
case CV_MemberPointerKind_DataGeneral: return str8_lit("DataGeneral");
case CV_MemberPointerKind_FuncSingle: return str8_lit("FuncSingle");
case CV_MemberPointerKind_FuncMultiple: return str8_lit("FuncMultiple");
case CV_MemberPointerKind_FuncGeneral: return str8_lit("FuncGeneral");
}
return str8_zero();
}
internal String8
cv_string_from_pointer_kind(CV_PointerKind x)
{
switch (x) {
case CV_PointerKind_Near: return str8_lit("Near");
case CV_PointerKind_Far: return str8_lit("Far");
case CV_PointerKind_Huge: return str8_lit("Huge");
case CV_PointerKind_BaseSeg: return str8_lit("BaseSeg");
case CV_PointerKind_BaseVal: return str8_lit("BaseVal");
case CV_PointerKind_BaseSegVal: return str8_lit("BaseSegVal");
case CV_PointerKind_BaseAddr: return str8_lit("BaseAddr");
case CV_PointerKind_BaseSegAddr: return str8_lit("BaseSegAddr");
case CV_PointerKind_BaseType: return str8_lit("BaseType");
case CV_PointerKind_BaseSelf: return str8_lit("BaseSelf");
case CV_PointerKind_Near32: return str8_lit("Near32");
case CV_PointerKind_Far32: return str8_lit("Far32");
case CV_PointerKind_64: return str8_lit("64Bit");
}
return str8_zero();
}
internal String8
cv_string_from_pointer_mode(CV_PointerMode x)
{
switch (x) {
case CV_PointerMode_Ptr: return str8_lit("Ptr");
case CV_PointerMode_LRef: return str8_lit("LRef");
case CV_PointerMode_PtrMem: return str8_lit("PtrMem");
case CV_PointerMode_PtrMethod: return str8_lit("PtrMethod");
case CV_PointerMode_RRef: return str8_lit("RRef");
}
return str8_zero();
}
internal String8
cv_string_from_c13_checksum_kind(CV_C13ChecksumKind x)
{
switch (x) {
case CV_C13ChecksumKind_Null: break;
case CV_C13ChecksumKind_MD5: return str8_lit("MD5");
case CV_C13ChecksumKind_SHA1: return str8_lit("SHA1");
case CV_C13ChecksumKind_SHA256: return str8_lit("SHA256");
}
return str8_zero();
}
internal String8
cv_string_from_label_kind(Arena *arena, CV_LabelKind x)
{
switch (x) {
case CV_LabelKind_Near: return str8_lit("Near");
case CV_LabelKind_Far: return str8_lit("Far");
}
return push_str8f(arena, "%#x", x);
}
internal String8
cv_string_from_c13_subsection_kind(CV_C13SubSectionKind x)
{
switch (x) {
#define X(_N, _ID) case CV_C13SubSectionKind_##_N: return str8_lit(Stringify(_N));
CV_C13SubSectionKindXList(X)
#undef X
}
return str8_zero();
}
internal String8
cv_string_from_modifier_flags(Arena *arena, CV_ModifierFlags x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_ModifierFlag_Const) {
str8_list_pushf(scratch.arena, &list, "Const");
}
if (x & CV_ModifierFlag_Volatile) {
str8_list_pushf(scratch.arena, &list, "Volatile");
}
if (x & CV_ModifierFlag_Unaligned) {
str8_list_pushf(scratch.arena, &list, "Unaligned");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_pointer_attribs(Arena *arena, CV_PointerAttribs x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_PointerAttrib_IsFlat) {
x &= ~CV_PointerAttrib_IsFlat;
str8_list_pushf(scratch.arena, &list, "IsFlat");
}
if (x & CV_PointerAttrib_Volatile) {
x &= ~CV_PointerAttrib_Volatile;
str8_list_pushf(scratch.arena, &list, "Volatile");
}
if (x & CV_PointerAttrib_Const) {
x &= ~CV_PointerAttrib_Const;
str8_list_pushf(scratch.arena, &list, "Const");
}
if (x & CV_PointerAttrib_Unaligned) {
x &= ~CV_PointerAttrib_Unaligned;
str8_list_pushf(scratch.arena, &list, "Unaligned");
}
if (x & CV_PointerAttrib_Restricted) {
x &= ~CV_PointerAttrib_Restricted;
str8_list_pushf(scratch.arena, &list, "Restricted");
}
if (x & CV_PointerAttrib_MOCOM) {
x &= ~CV_PointerAttrib_MOCOM;
str8_list_pushf(scratch.arena, &list, "MOCOM");
}
if (x & CV_PointerAttrib_LRef) {
x &= ~CV_PointerAttrib_LRef;
str8_list_pushf(scratch.arena, &list, "LRef");
}
if (x & CV_PointerAttrib_RRef) {
x &= ~CV_PointerAttrib_RRef;
str8_list_pushf(scratch.arena, &list, "RRef");
}
CV_PointerKind kind = CV_PointerAttribs_Extract_Kind(x);
CV_PointerMode mode = CV_PointerAttribs_Extract_Mode(x);
U64 size = CV_PointerAttribs_Extract_Size(x);
x &= ~(0x1f|(0x7<<5)|(0x3f<<13));
if (kind) {
String8 kind_str = cv_string_from_pointer_kind(kind);
str8_list_pushf(scratch.arena, &list, "Kind=%S", kind_str);
}
if (mode) {
String8 mode_str = cv_string_from_pointer_mode(mode);
str8_list_pushf(scratch.arena, &list, "Mode=%S", mode_str);
}
if (size) {
str8_list_pushf(scratch.arena, &list, "Size=%llu", size);
}
if (x != 0) {
str8_list_pushf(scratch.arena, &list, "Unknown=%x", x);
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_function_attribs(Arena *arena, CV_FunctionAttribs x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_FunctionAttrib_CxxReturnUDT) {
str8_list_pushf(scratch.arena, &list, "CxxReturnUDT");
}
if (x & CV_FunctionAttrib_Constructor) {
str8_list_pushf(scratch.arena, &list, "Constructor");
}
if (x & CV_FunctionAttrib_ConstructorVBase) {
str8_list_pushf(scratch.arena, &list, "ConstructorVBase");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_export_flags(Arena *arena, CV_ExportFlags x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_ExportFlag_Constant) {
str8_list_pushf(scratch.arena, &list, "Constant");
}
if (x & CV_ExportFlag_Data) {
str8_list_pushf(scratch.arena, &list, "Data");
}
if (x & CV_ExportFlag_Private) {
str8_list_pushf(scratch.arena, &list, "Private");
}
if (x & CV_ExportFlag_NoName) {
str8_list_pushf(scratch.arena, &list, "NoName");
}
if (x & CV_ExportFlag_Ordinal) {
str8_list_pushf(scratch.arena, &list, "Ordinal");
}
if (x & CV_ExportFlag_Forwarder) {
str8_list_pushf(scratch.arena, &list, "Forwarder");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_sepcode(Arena *arena, CV_SepcodeFlags x)
{
Temp scratch = scratch_begin(&arena,1);
String8List list = {0};
if (x & CV_SepcodeFlag_IsLexicalScope) {
str8_list_pushf(scratch.arena, &list, "IsLexicalScope");
}
if (x & CV_SepcodeFlag_ReturnsToParent) {
str8_list_pushf(scratch.arena, &list, "ReturnsToParent");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_pub32_flags(Arena *arena, CV_Pub32Flags x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_Pub32Flag_Code) {
str8_list_pushf(scratch.arena, &list, "Code");
}
if (x & CV_Pub32Flag_Function) {
str8_list_pushf(scratch.arena, &list, "Function");
}
if (x & CV_Pub32Flag_ManagedCode) {
str8_list_pushf(scratch.arena, &list, "ManagedCode");
}
if (x & CV_Pub32Flag_MSIL) {
str8_list_pushf(scratch.arena, &list, "MSIL");
}
String8 result = str8_list_join(scratch.arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_generic_flags(Arena *arena, CV_GenericFlags x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_GenericFlags_CSTYLE) {
str8_list_pushf(scratch.arena, &list, "CSTYLE");
}
if (x & CV_GenericFlags_RSCLEAN) {
str8_list_pushf(scratch.arena, &list, "RSCLEAN");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_frame_proc_flags(Arena *arena, CV_FrameprocFlags x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_FrameprocFlag_UsesAlloca) {
str8_list_pushf(scratch.arena, &list, "UsesAlloca");
}
if (x & CV_FrameprocFlag_UsesSetJmp) {
str8_list_pushf(scratch.arena, &list, "UsesSetJmp");
}
if (x & CV_FrameprocFlag_UsesLongJmp) {
str8_list_pushf(scratch.arena, &list, "UsesLongJmp");
}
if (x & CV_FrameprocFlag_UsesInlAsm) {
str8_list_pushf(scratch.arena, &list, "UsesInlAsm");
}
if (x & CV_FrameprocFlag_UsesEH) {
str8_list_pushf(scratch.arena, &list, "UsesEH");
}
if (x & CV_FrameprocFlag_Inline) {
str8_list_pushf(scratch.arena, &list, "Inline");
}
if (x & CV_FrameprocFlag_HasSEH) {
str8_list_pushf(scratch.arena, &list, "HasSEH");
}
if (x & CV_FrameprocFlag_Naked) {
str8_list_pushf(scratch.arena, &list, "Naked");
}
if (x & CV_FrameprocFlag_HasSecurityChecks) {
str8_list_pushf(scratch.arena, &list, "HasSecurityChecks");
}
if (x & CV_FrameprocFlag_AsyncEH) {
str8_list_pushf(scratch.arena, &list, "AsyncEH");
}
if (x & CV_FrameprocFlag_GSNoStackOrdering) {
str8_list_pushf(scratch.arena, &list, "GSNoStackOrdering");
}
if (x & CV_FrameprocFlag_WasInlined) {
str8_list_pushf(scratch.arena, &list, "WasInlined");
}
if (x & CV_FrameprocFlag_GSCheck) {
str8_list_pushf(scratch.arena, &list, "GSCheck");
}
if (x & CV_FrameprocFlag_SafeBuffers) {
str8_list_pushf(scratch.arena, &list, "SafeBuffers");
}
if (x & CV_FrameprocFlag_PogoOn) {
str8_list_pushf(scratch.arena, &list, "PogoOn");
}
if (x & CV_FrameprocFlag_PogoCountsValid) {
str8_list_pushf(scratch.arena, &list, "PogoCountsValid");
}
if (x & CV_FrameprocFlag_OptSpeed) {
str8_list_pushf(scratch.arena, &list, "OptSpeed");
}
if (x & CV_FrameprocFlag_HasCFG) {
str8_list_pushf(scratch.arena, &list, "HasCFG");
}
if (x & CV_FrameprocFlag_HasCFW) {
str8_list_pushf(scratch.arena, &list, "HasCFW");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_type_props(Arena *arena, CV_TypeProps32 x)
{
Temp scratch = scratch_begin(&arena, 1);
U32 hfa = CV_TypeProps_Extract_HFA(x);
U32 mcom = CV_TypeProps_Extract_MOCOM(x);
String8 hfa_str = cv_string_from_hfa(hfa);
String8 mcom_str = cv_string_from_mcom(mcom);
String8 flags_str;
{
String8List list = {0};
if (x & CV_TypeProp_Packed) {
x &= ~CV_TypeProp_Packed;
str8_list_pushf(scratch.arena, &list, "Packed");
}
if (x & CV_TypeProp_HasConstructorsDestructors) {
x &= ~CV_TypeProp_HasConstructorsDestructors;
str8_list_pushf(scratch.arena, &list, "HasConstructorsDestructors");
}
if (x & CV_TypeProp_OverloadedOperators) {
x &= ~CV_TypeProp_OverloadedOperators;
str8_list_pushf(scratch.arena, &list, "OverloadedOperators");
}
if (x & CV_TypeProp_IsNested) {
x &= ~CV_TypeProp_IsNested;
str8_list_pushf(scratch.arena, &list, "IsNested");
}
if (x & CV_TypeProp_ContainsNested) {
x &= ~CV_TypeProp_ContainsNested;
str8_list_pushf(scratch.arena, &list, "ContainsNested");
}
if (x & CV_TypeProp_OverloadedAssignment) {
x &= ~CV_TypeProp_OverloadedAssignment;
str8_list_pushf(scratch.arena, &list, "OverloadedAssignment");
}
if (x & CV_TypeProp_OverloadedCasting) {
x &= ~CV_TypeProp_OverloadedCasting;
str8_list_pushf(scratch.arena, &list, "OverloadedCasting");
}
if (x & CV_TypeProp_FwdRef) {
x &= ~CV_TypeProp_FwdRef;
str8_list_pushf(scratch.arena, &list, "FwdRef");
}
if (x & CV_TypeProp_Scoped) {
x &= ~CV_TypeProp_Scoped;
str8_list_pushf(scratch.arena, &list, "Scoped");
}
if (x & CV_TypeProp_HasUniqueName) {
x &= ~CV_TypeProp_HasUniqueName;
str8_list_pushf(scratch.arena, &list, "HasUniqueName");
}
if (x & CV_TypeProp_Sealed) {
x &= ~CV_TypeProp_Sealed;
str8_list_pushf(scratch.arena, &list, "Sealed");
}
if (x & CV_TypeProp_Intrinsic) {
x &= ~CV_TypeProp_Intrinsic;
str8_list_pushf(scratch.arena, &list, "Intrinsic");
}
if (x != 0) {
str8_list_pushf(scratch.arena, &list, "%x", x);
}
flags_str = str8_list_join(scratch.arena, &list, &(StringJoin){.sep=str8_lit(", ") });
if (hfa) {
str8_list_pushf(scratch.arena, &list, "HFA = %S", hfa_str);
}
if (mcom) {
str8_list_pushf(scratch.arena, &list, "MCOM = %S", mcom_str);
}
}
String8 result = push_str8f(arena, "%S", flags_str);
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_local_flags(Arena *arena, CV_LocalFlags x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_LocalFlag_Param) {
str8_list_pushf(scratch.arena, &list, "Param");
}
if (x & CV_LocalFlag_AddrTaken) {
str8_list_pushf(scratch.arena, &list, "AddrTaken");
}
if (x & CV_LocalFlag_Compgen) {
str8_list_pushf(scratch.arena, &list, "Compgen");
}
if (x & CV_LocalFlag_Aggregate) {
str8_list_pushf(scratch.arena, &list, "Aggregate");
}
if (x & CV_LocalFlag_PartOfAggregate) {
str8_list_pushf(scratch.arena, &list, "PartOfAggregate");
}
if (x & CV_LocalFlag_Aliased) {
str8_list_pushf(scratch.arena, &list, "Aliased");
}
if (x & CV_LocalFlag_Alias) {
str8_list_pushf(scratch.arena, &list, "Alias");
}
if (x & CV_LocalFlag_Retval) {
str8_list_pushf(scratch.arena, &list, "Retval");
}
if (x & CV_LocalFlag_OptOut) {
str8_list_pushf(scratch.arena, &list, "OptOut");
}
if (x & CV_LocalFlag_Global) {
str8_list_pushf(scratch.arena, &list, "Global");
}
if (x & CV_LocalFlag_Static) {
str8_list_pushf(scratch.arena, &list, "Static");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_proc_flags(Arena *arena, CV_ProcFlags x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_ProcFlag_NoFPO) {
x &= ~CV_ProcFlag_NoFPO;
str8_list_pushf(scratch.arena, &list, "NoFPO");
}
if (x & CV_ProcFlag_IntReturn) {
x &= ~CV_ProcFlag_IntReturn;
str8_list_pushf(scratch.arena, &list, "IntReturn");
}
if (x & CV_ProcFlag_FarReturn) {
x &= ~CV_ProcFlag_FarReturn;
str8_list_pushf(scratch.arena, &list, "FarReturn");
}
if (x & CV_ProcFlag_NeverReturn) {
x &= ~CV_ProcFlag_NeverReturn;
str8_list_pushf(scratch.arena, &list, "NeverReturn");
}
if (x & CV_ProcFlag_NotReached) {
x &= ~CV_ProcFlag_NotReached;
str8_list_pushf(scratch.arena, &list, "NotReached");
}
if (x & CV_ProcFlag_CustomCall) {
x &= ~CV_ProcFlag_CustomCall;
str8_list_pushf(scratch.arena, &list, "CustomCall");
}
if (x & CV_ProcFlag_NoInline) {
x &= ~CV_ProcFlag_NoInline;
str8_list_pushf(scratch.arena, &list, "NoInline");
}
if (x & CV_ProcFlag_OptDbgInfo) {
x &= ~CV_ProcFlag_OptDbgInfo;
str8_list_pushf(scratch.arena, &list, "OptDbgInfo");
}
if (x != 0) {
str8_list_pushf(scratch.arena, &list, "%#x", x);
}
String8 result;
if (list.node_count == 0) {
result = str8_lit("None");
} else {
result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
}
temp_end(scratch);
return result;
}
internal String8
cv_string_from_range_attribs(Arena *arena, CV_RangeAttribs x)
{ (void)arena;
String8 result = str8_lit("None");
if (x == CV_RangeAttrib_Maybe) {
result = str8_lit("Maybe");
}
return result;
}
internal String8
cv_string_from_defrange_register_rel_flags(Arena *arena, CV_DefrangeRegisterRelFlags x)
{ (void)arena;
String8 result = str8_lit("None");
if (x == CV_DefrangeRegisterRelFlag_SpilledOutUDTMember) {
result = str8_lit("SpilledOutUDTMember");
}
return result;
}
internal String8
cv_string_from_field_attribs(Arena *arena, CV_FieldAttribs attribs)
{
Temp scratch = scratch_begin(&arena, 1);
U32 access = CV_FieldAttribs_Extract_Access(attribs);
U32 mprop = CV_FieldAttribs_Extract_MethodProp(attribs);
attribs &= ~(0x3 | 0x7);
String8 access_str = cv_string_from_member_access(access);
String8 mprop_str = cv_string_from_method_prop(mprop);
String8List list = {0};
{
if (attribs & CV_FieldAttrib_Pseudo) {
attribs &= ~CV_FieldAttrib_Pseudo;
str8_list_pushf(scratch.arena, &list, "Pseudo");
}
if (attribs & CV_FieldAttrib_NoInherit) {
attribs &= ~CV_FieldAttrib_NoInherit;
str8_list_pushf(scratch.arena, &list, "NoInherit");
}
if (attribs & CV_FieldAttrib_NoConstruct) {
attribs &= ~CV_FieldAttrib_NoConstruct;
str8_list_pushf(scratch.arena, &list, "NoConstruct");
}
if (attribs & CV_FieldAttrib_CompilerGenated) {
attribs &= ~CV_FieldAttrib_CompilerGenated;
str8_list_pushf(scratch.arena, &list, "CompilerGenerated");
}
if (attribs & CV_FieldAttrib_Sealed) {
attribs &= ~CV_FieldAttrib_Sealed;
str8_list_pushf(scratch.arena, &list, "Sealed");
}
if (attribs) {
str8_list_pushf(scratch.arena, &list, "Unknown: %x", attribs);
}
}
if (access) {
str8_list_pushf(scratch.arena, &list, "%S", access_str);
}
if (mprop) {
str8_list_pushf(scratch.arena, &list, "%S", mprop_str);
}
String8 result = str8_list_join(scratch.arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_itype(Arena *arena, CV_TypeIndex min_itype, CV_TypeIndex itype)
{
String8 result = str8_zero();
if (itype < min_itype) {
String8 n = cv_type_name_from_basic_type((CV_BasicType)itype);
if (n.size) {
Temp scratch = scratch_begin(&arena, 1);
U64 type = CV_BasicTypeFromTypeId(itype);
char *type_str = "???";
switch (type) {
case CV_BasicType_NOTYPE: type_str = "NOTYPE"; break;
case CV_BasicType_ABS: type_str = "ABS"; break;
case CV_BasicType_SEGMENT: type_str = "SEGMENT"; break;
case CV_BasicType_VOID: type_str = "VOID"; break;
case CV_BasicType_CURRENCY: type_str = "CURRENCY"; break;
case CV_BasicType_NBASICSTR: type_str = "NBASICSTR"; break;
case CV_BasicType_FBASICSTR: type_str = "FBASICSTR"; break;
case CV_BasicType_NOTTRANS: type_str = "NOTTRANS"; break;
case CV_BasicType_HRESULT: type_str = "HRESULT"; break;
case CV_BasicType_CHAR: type_str = "CHAR"; break;
case CV_BasicType_SHORT: type_str = "SHORT"; break;
case CV_BasicType_LONG: type_str = "LONG"; break;
case CV_BasicType_QUAD: type_str = "QUAD"; break;
case CV_BasicType_OCT: type_str = "OCT"; break;
case CV_BasicType_UCHAR: type_str = "UCHAR"; break;
case CV_BasicType_USHORT: type_str = "USHORT"; break;
case CV_BasicType_ULONG: type_str = "ULONG"; break;
case CV_BasicType_UQUAD: type_str = "UQUAD"; break;
case CV_BasicType_UOCT: type_str = "UOCT"; break;
case CV_BasicType_BOOL8: type_str = "BOOL8"; break;
case CV_BasicType_BOOL16: type_str = "BOOL16"; break;
case CV_BasicType_BOOL32: type_str = "BOOL32"; break;
case CV_BasicType_BOOL64: type_str = "BOOL64"; break;
case CV_BasicType_FLOAT32: type_str = "FLOAT32"; break;
case CV_BasicType_FLOAT64: type_str = "FLOAT64"; break;
case CV_BasicType_FLOAT80: type_str = "FLOAT80"; break;
case CV_BasicType_FLOAT128: type_str = "FLOAT128"; break;
case CV_BasicType_FLOAT48: type_str = "FLOAT48"; break;
case CV_BasicType_FLOAT32PP: type_str = "FLOAT32PP"; break;
case CV_BasicType_FLOAT16: type_str = "FLOAT16"; break;
case CV_BasicType_COMPLEX32: type_str = "COMPLEX32"; break;
case CV_BasicType_COMPLEX64: type_str = "COMPLEX64"; break;
case CV_BasicType_COMPLEX80: type_str = "COMPLEX80"; break;
case CV_BasicType_COMPLEX128: type_str = "COMPLEX128"; break;
case CV_BasicType_BIT: type_str = "BIT"; break;
case CV_BasicType_PASCHAR: type_str = "PASCHAR"; break;
case CV_BasicType_BOOL32FF: type_str = "BOOL32FF"; break;
case CV_BasicType_INT8: type_str = "INT8"; break;
case CV_BasicType_UINT8: type_str = "UINT8"; break;
case CV_BasicType_RCHAR: type_str = "RCHAR"; break;
case CV_BasicType_WCHAR: type_str = "WCHAR"; break;
case CV_BasicType_INT16: type_str = "INT16"; break;
case CV_BasicType_UINT16: type_str = "UINT16"; break;
case CV_BasicType_INT32: type_str = "INT32"; break;
case CV_BasicType_UINT32: type_str = "UINT32"; break;
case CV_BasicType_INT64: type_str = "INT64"; break;
case CV_BasicType_UINT64: type_str = "UINT64"; break;
case CV_BasicType_INT128: type_str = "INT128"; break;
case CV_BasicType_UINT128: type_str = "UINT128"; break;
case CV_BasicType_CHAR16: type_str = "CHAR16"; break;
case CV_BasicType_CHAR32: type_str = "CHAR32"; break;
case CV_BasicType_CHAR8: type_str = "CHAR8"; break;
case CV_BasicType_PTR: type_str = "PTR"; break;
}
U64 ptr = CV_BasicPointerKindFromTypeId(itype);
char *ptr_str = "";
switch (ptr) {
case 0x1: ptr_str = "P"; break;
case 0x2: ptr_str = "PF"; break;
case 0x3: ptr_str = "PH"; break;
case 0x4: ptr_str = "32P"; break;
case 0x5: ptr_str = "32PF"; break;
case 0x6: ptr_str = "64P"; break;
}
n = upper_from_str8(scratch.arena, n);
result = push_str8f(arena, "T_%s%s(%x)", ptr_str, type_str, itype);
scratch_end(scratch);
} else {
result = push_str8f(arena, "%x", itype);
}
} else {
result = push_str8f(arena, "%x", itype);
}
return result;
}
internal String8
cv_string_from_itemid(Arena *arena, CV_ItemId itemid)
{
String8 result = push_str8f(arena, "%x", itemid);
return result;
}
internal String8
cv_string_from_symbol_type(Arena *arena, CV_SymKind symbol_type)
{
String8 str = cv_string_from_sym_kind(symbol_type);
String8 result = push_str8f(arena, "S_%S", str);
return result;
}
internal String8
cv_string_from_symbol_kind(Arena *arena, CV_SymKind kind)
{
String8 str = cv_string_from_sym_kind(kind);
String8 result = push_str8f(arena, "S_%S", str);
return result;
}
internal String8
cv_string_from_leaf_name(Arena *arena, U32 leaf_type)
{
String8 str = cv_string_from_leaf_kind(leaf_type);
String8 result = push_str8f(arena, "LF_%S", str);
return result;
}
internal String8
cv_string_sec_off(Arena *arena, U32 sec, U32 off)
{
return push_str8f(arena, "%04x:%08x", sec, off);
}
+44
View File
@@ -2971,7 +2971,51 @@ internal CV_EncodedFramePtrReg cv_pick_fp_encoding(CV_SymFrameproc *frameproc, B
internal CV_Reg cv_decode_fp_reg(CV_Arch arch, CV_EncodedFramePtrReg encoded_reg);
internal U32 cv_map_encoded_base_pointer(CV_Arch arch, U32 encoded_frame_reg);
////////////////////////////////
//~ rjf: Enum -> String
internal String8 cv_string_from_inline_range_kind(CV_InlineRangeKind kind);
internal String8 cv_string_from_type_index_source(CV_TypeIndexSource ti_source);
internal String8 cv_string_from_language(CV_Language x);
internal String8 cv_string_from_reg_id(Arena *arena, CV_Arch arch, U32 id);
internal String8 cv_string_from_member_access(CV_MemberAccess x);
internal String8 cv_string_from_method_prop(CV_MethodProp x);
internal String8 cv_string_from_hfa(CV_HFAKind x);
internal String8 cv_string_from_mcom(CV_MoComUDTKind x);
internal String8 cv_string_from_binary_opcode(CV_InlineBinaryAnnotation x);
internal String8 cv_string_from_thunk_ordinal(CV_ThunkOrdinal x);
internal String8 cv_string_from_frame_cookie_kind(CV_FrameCookieKind x);
internal String8 cv_string_from_generic_style(CV_GenericStyle x);
internal String8 cv_string_from_trampoline_kind(CV_TrampolineKind x);
internal String8 cv_string_from_virtual_table_shape_kind(CV_VirtualTableShape x);
internal String8 cv_string_from_call_kind(CV_CallKind x);
internal String8 cv_string_from_member_pointer_kind(CV_MemberPointerKind x);
internal String8 cv_string_from_pointer_kind(CV_PointerKind x);
internal String8 cv_string_from_pointer_mode(CV_PointerMode x);
internal String8 cv_string_from_c13_checksum_kind(CV_C13ChecksumKind x);
internal String8 cv_string_from_label_kind(Arena *arena, CV_LabelKind x);
internal String8 cv_string_from_c13_subsection_kind(CV_C13SubSectionKind x);
internal String8 cv_string_from_modifier_flags(Arena *arena, CV_ModifierFlags x);
internal String8 cv_string_from_pointer_attribs(Arena *arena, CV_PointerAttribs x);
internal String8 cv_string_from_function_attribs(Arena *arena, CV_FunctionAttribs x);
internal String8 cv_string_from_export_flags(Arena *arena, CV_ExportFlags x);
internal String8 cv_string_from_sepcode(Arena *arena, CV_SepcodeFlags x);
internal String8 cv_string_from_pub32_flags(Arena *arena, CV_Pub32Flags x);
internal String8 cv_string_from_generic_flags(Arena *arena, CV_GenericFlags x);
internal String8 cv_string_from_frame_proc_flags(Arena *arena, CV_FrameprocFlags x);
internal String8 cv_string_from_type_props(Arena *arena, CV_TypeProps32 x);
internal String8 cv_string_from_local_flags(Arena *arena, CV_LocalFlags x);
internal String8 cv_string_from_proc_flags(Arena *arena, CV_ProcFlags x);
internal String8 cv_string_from_range_attribs(Arena *arena, CV_RangeAttribs x);
internal String8 cv_string_from_defrange_register_rel_flags(Arena *arena, CV_DefrangeRegisterRelFlags x);
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_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);
internal String8 cv_string_sec_off(Arena *arena, U32 sec, U32 off);
#endif // CODEVIEW_H
+24
View File
@@ -0,0 +1,24 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal String8
cv_string_from_numeric(Arena *arena, CV_NumericParsed num)
{
String8 result = str8_zero();
switch (num.kind) {
case CV_NumericKind_FLOAT16: NotImplemented; break; // TODO: format float16
case CV_NumericKind_FLOAT32: result = push_str8f(arena, "%f", (F64)(*(F32*)num.val)); break;
case CV_NumericKind_FLOAT48: NotImplemented; break; // TODO: format float48
case CV_NumericKind_FLOAT64: result = push_str8f(arena, "%f", *(F64*)num.val); break;
case CV_NumericKind_FLOAT80: NotImplemented; break; // TODO: format float80
case CV_NumericKind_FLOAT128: NotImplemented; break; // TODO: format float128
case CV_NumericKind_CHAR: result = push_str8f(arena, "%d", *(S8 *)num.val); break;
case CV_NumericKind_SHORT: result = push_str8f(arena, "%d", *(S16*)num.val); break;
case CV_NumericKind_LONG: result = push_str8f(arena, "%d", *(S32*)num.val); break;
case CV_NumericKind_QUADWORD: result = push_str8f(arena, "%lld", *(S64*)num.val); break;
case CV_NumericKind_USHORT: result = push_str8f(arena, "%u", *(U16*)num.val); break;
case CV_NumericKind_ULONG: result = push_str8f(arena, "%u", *(U32*)num.val); break;
case CV_NumericKind_UQUADWORD: result = push_str8f(arena, "%llu", *(U64*)num.val); break;
}
return result;
}
+9
View File
@@ -0,0 +1,9 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef CODEVIEW_DUMP_H
#define CODEVIEW_DUMP_H
internal String8 cv_string_from_numeric(Arena *arena, CV_NumericParsed num);
#endif // CODEVIEW_DUMP_H
-962
View File
@@ -1,962 +0,0 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal String8
cv_string_from_unknown_value(Arena *arena, U32 x)
{
return push_str8f(arena, "%#x", x);
}
internal String8
cv_string_from_type_index_source(CV_TypeIndexSource ti_source)
{
switch (ti_source) {
case CV_TypeIndexSource_NULL: return str8_lit(""); break;
case CV_TypeIndexSource_TPI: return str8_lit("TPI"); break;
case CV_TypeIndexSource_IPI: return str8_lit("IPI"); break;
case CV_TypeIndexSource_COUNT: break;
}
return str8_zero();
}
internal String8
cv_string_from_language(CV_Language x)
{
switch (x) {
#define X(_n,_i) case _i: return str8_lit(Stringify(_n));
CV_LanguageXList(X)
#undef X
}
return str8_zero();
}
internal String8
cv_string_from_numeric(Arena *arena, CV_NumericParsed num)
{
String8 result = str8_zero();
switch (num.kind) {
case CV_NumericKind_FLOAT16: NotImplemented; break; // TODO: format float16
case CV_NumericKind_FLOAT32: result = push_str8f(arena, "%f", (F64)(*(F32*)num.val)); break;
case CV_NumericKind_FLOAT48: NotImplemented; break; // TODO: format float48
case CV_NumericKind_FLOAT64: result = push_str8f(arena, "%f", *(F64*)num.val); break;
case CV_NumericKind_FLOAT80: NotImplemented; break; // TODO: format float80
case CV_NumericKind_FLOAT128: NotImplemented; break; // TODO: format float128
case CV_NumericKind_CHAR: result = push_str8f(arena, "%d", *(S8 *)num.val); break;
case CV_NumericKind_SHORT: result = push_str8f(arena, "%d", *(S16*)num.val); break;
case CV_NumericKind_LONG: result = push_str8f(arena, "%d", *(S32*)num.val); break;
case CV_NumericKind_QUADWORD: result = push_str8f(arena, "%lld", *(S64*)num.val); break;
case CV_NumericKind_USHORT: result = push_str8f(arena, "%u", *(U16*)num.val); break;
case CV_NumericKind_ULONG: result = push_str8f(arena, "%u", *(U32*)num.val); break;
case CV_NumericKind_UQUADWORD: result = push_str8f(arena, "%llu", *(U64*)num.val); break;
}
return result;
}
internal String8
cv_string_from_reg_id(Arena *arena, CV_Arch arch, U32 id)
{
String8 result = str8_zero();
switch (arch) {
case CV_Arch_8086: {
switch (id) {
#define X(_N, _ID, ...) case _ID: result = str8_lit(Stringify(_N)); break;
CV_Reg_X86_XList(X)
#undef X
}
} break;
case CV_Arch_X64: {
switch (id) {
#define X(_N, _ID, ...) case _ID: result = str8_lit(Stringify(_N)); break;
CV_Reg_X64_XList(X)
#undef X
}
} break;
default: NotImplemented; break;
}
if (result.size == 0) {
result = push_str8f(arena, "%x", id);
}
return result;
}
internal String8
cv_string_from_member_access(CV_MemberAccess x)
{
switch (x) {
case CV_MemberAccess_Null: break;
case CV_MemberAccess_Private: return str8_lit("Private");
case CV_MemberAccess_Protected: return str8_lit("Protected");
case CV_MemberAccess_Public: return str8_lit("Public");
}
return str8_zero();
}
internal String8
cv_string_from_method_prop(CV_MethodProp x)
{
switch (x) {
case CV_MethodProp_Vanilla: return str8_lit("Vanilla");
case CV_MethodProp_Virtual: return str8_lit("Virtual");
case CV_MethodProp_Static: return str8_lit("Static");
case CV_MethodProp_Friend: return str8_lit("Friend");
case CV_MethodProp_Intro: return str8_lit("Intro");
case CV_MethodProp_PureVirtual: return str8_lit("PureVirtual");
case CV_MethodProp_PureIntro: return str8_lit("PureIntro");
}
return str8_zero();
}
internal String8
cv_string_from_hfa(CV_HFAKind x)
{
switch (x) {
case CV_HFAKind_None: return str8_lit("None");
case CV_HFAKind_Float: return str8_lit("Float");
case CV_HFAKind_Double: return str8_lit("Double");
case CV_HFAKind_Other: return str8_lit("Other");
}
return str8_zero();
}
internal String8
cv_string_from_mcom(CV_MoComUDTKind x)
{
switch (x) {
case CV_MoComUDTKind_None: return str8_lit("None");
case CV_MoComUDTKind_Ref: return str8_lit("Ref");
case CV_MoComUDTKind_Value: return str8_lit("Value");
case CV_MoComUDTKind_Interface: return str8_lit("Interface");
}
return str8_zero();
}
internal String8
cv_string_from_binary_opcode(CV_InlineBinaryAnnotation x)
{
switch (x) {
case CV_InlineBinaryAnnotation_Null: break;
case CV_InlineBinaryAnnotation_CodeOffset: return str8_lit("CodeOffset");
case CV_InlineBinaryAnnotation_ChangeCodeOffsetBase: return str8_lit("ChangeCodeOffsetBase");
case CV_InlineBinaryAnnotation_ChangeCodeOffset: return str8_lit("ChangeCodeOffset");
case CV_InlineBinaryAnnotation_ChangeCodeLength: return str8_lit("ChangeCodeLength");
case CV_InlineBinaryAnnotation_ChangeFile: return str8_lit("ChangeFile");
case CV_InlineBinaryAnnotation_ChangeLineOffset: return str8_lit("ChangeLineOffset");
case CV_InlineBinaryAnnotation_ChangeLineEndDelta: return str8_lit("ChangeLineEndDelta");
case CV_InlineBinaryAnnotation_ChangeRangeKind: return str8_lit("ChangeRangeKind");
case CV_InlineBinaryAnnotation_ChangeColumnStart: return str8_lit("ChangeColumnStart");
case CV_InlineBinaryAnnotation_ChangeColumnEndDelta: return str8_lit("ChangeColumnEndDelta");
case CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset: return str8_lit("ChangeCodeOffsetAndLineOffset");
case CV_InlineBinaryAnnotation_ChangeCodeLengthAndCodeOffset: return str8_lit("ChangeCodeLengthAndCodeOffset");
case CV_InlineBinaryAnnotation_ChangeColumnEnd: return str8_lit("ChangeColumnEnd");
}
return str8_zero();
}
internal String8
cv_string_from_thunk_ordinal(CV_ThunkOrdinal x)
{
switch (x) {
case CV_ThunkOrdinal_NoType: return str8_lit("NoType");
case CV_ThunkOrdinal_Adjustor: return str8_lit("Adjustor");
case CV_ThunkOrdinal_VCall: return str8_lit("VCall");
case CV_ThunkOrdinal_PCode: return str8_lit("PCode");
case CV_ThunkOrdinal_Load: return str8_lit("Load");
case CV_ThunkOrdinal_TrampIncremental: return str8_lit("TrampIncremental");
case CV_ThunkOrdinal_TrampBranchIsland: return str8_lit("TrampBranchIsland");
}
return str8_zero();
}
internal String8
cv_string_from_frame_cookie_kind(CV_FrameCookieKind x)
{
switch (x) {
case CV_FrameCookieKind_Copy: return str8_lit("Copy");
case CV_FrameCookieKind_XorSP: return str8_lit("XorSP");
case CV_FrameCookieKind_XorBP: return str8_lit("XorR13");
}
return str8_zero();
}
internal String8
cv_string_from_generic_style(CV_GenericStyle x)
{
switch (x) {
case CV_GenericStyle_VOID: return str8_lit("VOID");
case CV_GenericStyle_REG: return str8_lit("REG");
case CV_GenericStyle_ICAN: return str8_lit("ICAN");
case CV_GenericStyle_ICAF: return str8_lit("ICAF");
case CV_GenericStyle_IRAN: return str8_lit("IRAN");
case CV_GenericStyle_IRAF: return str8_lit("IRAF");
case CV_GenericStyle_UNUSED: return str8_lit("UNUSED");
}
return str8_zero();
}
internal String8
cv_string_from_trampoline_kind(CV_TrampolineKind x)
{
switch (x) {
case CV_TrampolineKind_Incremental: return str8_lit("Incremental");
case CV_TrampolineKind_BranchIsland: return str8_lit("BranchIsland");
}
return str8_zero();
}
internal String8
cv_string_from_virtual_table_shape_kind(CV_VirtualTableShape x)
{
switch (x) {
case CV_VirtualTableShape_Near: return str8_lit("Near");
case CV_VirtualTableShape_Far: return str8_lit("Far");
case CV_VirtualTableShape_Thin: return str8_lit("Thin");
case CV_VirtualTableShape_Outer: return str8_lit("Outer");
case CV_VirtualTableShape_Meta: return str8_lit("Meta");
case CV_VirtualTableShape_Near32: return str8_lit("Near32");
case CV_VirtualTableShape_Far32: return str8_lit("Far32");
}
return str8_zero();
}
internal String8
cv_string_from_call_kind(CV_CallKind x)
{
switch (x) {
case CV_CallKind_NearC: return str8_lit("NearC");
case CV_CallKind_FarC: return str8_lit("FarC");
case CV_CallKind_NearPascal: return str8_lit("NearPascal");
case CV_CallKind_FarPascal: return str8_lit("FarPascal");
case CV_CallKind_NearFast: return str8_lit("NearFast");
case CV_CallKind_FarFast: return str8_lit("FarFast");
case CV_CallKind_UNUSED: return str8_lit("UNUSED");
case CV_CallKind_NearStd: return str8_lit("NearStd");
case CV_CallKind_FarStd: return str8_lit("FarStd");
case CV_CallKind_NearSys: return str8_lit("NearSys");
case CV_CallKind_FarSys: return str8_lit("FarSys");
case CV_CallKind_This: return str8_lit("This");
case CV_CallKind_Mips: return str8_lit("Mips");
case CV_CallKind_Generic: return str8_lit("Generic");
case CV_CallKind_Alpha: return str8_lit("Alpha");
case CV_CallKind_PPC: return str8_lit("PPC");
case CV_CallKind_HitachiSuperH: return str8_lit("HitachiSuperH");
case CV_CallKind_Arm: return str8_lit("Arm");
case CV_CallKind_AM33: return str8_lit("AM33");
case CV_CallKind_TriCore: return str8_lit("TriCore");
case CV_CallKind_HitachiSuperH5: return str8_lit("HitachiSuperH5");
case CV_CallKind_M32R: return str8_lit("M32R");
case CV_CallKind_Clr: return str8_lit("Clr");
case CV_CallKind_Inline: return str8_lit("Inline");
case CV_CallKind_NearVector: return str8_lit("NearVector");
}
return str8_zero();
}
internal String8
cv_string_from_member_pointer_kind(CV_MemberPointerKind x)
{
switch (x) {
case CV_MemberPointerKind_Undef: return str8_lit("Undef");
case CV_MemberPointerKind_DataSingle: return str8_lit("DataSingle");
case CV_MemberPointerKind_DataMultiple: return str8_lit("DataMultiple");
case CV_MemberPointerKind_DataVirtual: return str8_lit("DataVirtual");
case CV_MemberPointerKind_DataGeneral: return str8_lit("DataGeneral");
case CV_MemberPointerKind_FuncSingle: return str8_lit("FuncSingle");
case CV_MemberPointerKind_FuncMultiple: return str8_lit("FuncMultiple");
case CV_MemberPointerKind_FuncGeneral: return str8_lit("FuncGeneral");
}
return str8_zero();
}
internal String8
cv_string_from_pointer_kind(CV_PointerKind x)
{
switch (x) {
case CV_PointerKind_Near: return str8_lit("Near");
case CV_PointerKind_Far: return str8_lit("Far");
case CV_PointerKind_Huge: return str8_lit("Huge");
case CV_PointerKind_BaseSeg: return str8_lit("BaseSeg");
case CV_PointerKind_BaseVal: return str8_lit("BaseVal");
case CV_PointerKind_BaseSegVal: return str8_lit("BaseSegVal");
case CV_PointerKind_BaseAddr: return str8_lit("BaseAddr");
case CV_PointerKind_BaseSegAddr: return str8_lit("BaseSegAddr");
case CV_PointerKind_BaseType: return str8_lit("BaseType");
case CV_PointerKind_BaseSelf: return str8_lit("BaseSelf");
case CV_PointerKind_Near32: return str8_lit("Near32");
case CV_PointerKind_Far32: return str8_lit("Far32");
case CV_PointerKind_64: return str8_lit("64Bit");
}
return str8_zero();
}
internal String8
cv_string_from_pointer_mode(CV_PointerMode x)
{
switch (x) {
case CV_PointerMode_Ptr: return str8_lit("Ptr");
case CV_PointerMode_LRef: return str8_lit("LRef");
case CV_PointerMode_PtrMem: return str8_lit("PtrMem");
case CV_PointerMode_PtrMethod: return str8_lit("PtrMethod");
case CV_PointerMode_RRef: return str8_lit("RRef");
}
return str8_zero();
}
internal String8
cv_string_from_c13_checksum_kind(CV_C13ChecksumKind x)
{
switch (x) {
case CV_C13ChecksumKind_Null: break;
case CV_C13ChecksumKind_MD5: return str8_lit("MD5");
case CV_C13ChecksumKind_SHA1: return str8_lit("SHA1");
case CV_C13ChecksumKind_SHA256: return str8_lit("SHA256");
}
return str8_zero();
}
internal String8
cv_string_from_label_kind(Arena *arena, CV_LabelKind x)
{
switch (x) {
case CV_LabelKind_Near: return str8_lit("Near");
case CV_LabelKind_Far: return str8_lit("Far");
}
return cv_string_from_unknown_value(arena, x);
}
internal String8
cv_string_from_c13_subsection_kind(CV_C13SubSectionKind x)
{
switch (x) {
#define X(_N, _ID) case CV_C13SubSectionKind_##_N: return str8_lit(Stringify(_N));
CV_C13SubSectionKindXList(X)
#undef X
}
return str8_zero();
}
internal String8
cv_string_from_modifier_flags(Arena *arena, CV_ModifierFlags x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_ModifierFlag_Const) {
str8_list_pushf(scratch.arena, &list, "Const");
}
if (x & CV_ModifierFlag_Volatile) {
str8_list_pushf(scratch.arena, &list, "Volatile");
}
if (x & CV_ModifierFlag_Unaligned) {
str8_list_pushf(scratch.arena, &list, "Unaligned");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_pointer_attribs(Arena *arena, CV_PointerAttribs x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_PointerAttrib_IsFlat) {
x &= ~CV_PointerAttrib_IsFlat;
str8_list_pushf(scratch.arena, &list, "IsFlat");
}
if (x & CV_PointerAttrib_Volatile) {
x &= ~CV_PointerAttrib_Volatile;
str8_list_pushf(scratch.arena, &list, "Volatile");
}
if (x & CV_PointerAttrib_Const) {
x &= ~CV_PointerAttrib_Const;
str8_list_pushf(scratch.arena, &list, "Const");
}
if (x & CV_PointerAttrib_Unaligned) {
x &= ~CV_PointerAttrib_Unaligned;
str8_list_pushf(scratch.arena, &list, "Unaligned");
}
if (x & CV_PointerAttrib_Restricted) {
x &= ~CV_PointerAttrib_Restricted;
str8_list_pushf(scratch.arena, &list, "Restricted");
}
if (x & CV_PointerAttrib_MOCOM) {
x &= ~CV_PointerAttrib_MOCOM;
str8_list_pushf(scratch.arena, &list, "MOCOM");
}
if (x & CV_PointerAttrib_LRef) {
x &= ~CV_PointerAttrib_LRef;
str8_list_pushf(scratch.arena, &list, "LRef");
}
if (x & CV_PointerAttrib_RRef) {
x &= ~CV_PointerAttrib_RRef;
str8_list_pushf(scratch.arena, &list, "RRef");
}
CV_PointerKind kind = CV_PointerAttribs_Extract_Kind(x);
CV_PointerMode mode = CV_PointerAttribs_Extract_Mode(x);
U64 size = CV_PointerAttribs_Extract_Size(x);
x &= ~(0x1f|(0x7<<5)|(0x3f<<13));
if (kind) {
String8 kind_str = cv_string_from_pointer_kind(kind);
str8_list_pushf(scratch.arena, &list, "Kind=%S", kind_str);
}
if (mode) {
String8 mode_str = cv_string_from_pointer_mode(mode);
str8_list_pushf(scratch.arena, &list, "Mode=%S", mode_str);
}
if (size) {
str8_list_pushf(scratch.arena, &list, "Size=%llu", size);
}
if (x != 0) {
str8_list_pushf(scratch.arena, &list, "Unknown=%x", x);
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_function_attribs(Arena *arena, CV_FunctionAttribs x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_FunctionAttrib_CxxReturnUDT) {
str8_list_pushf(scratch.arena, &list, "CxxReturnUDT");
}
if (x & CV_FunctionAttrib_Constructor) {
str8_list_pushf(scratch.arena, &list, "Constructor");
}
if (x & CV_FunctionAttrib_ConstructorVBase) {
str8_list_pushf(scratch.arena, &list, "ConstructorVBase");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_export_flags(Arena *arena, CV_ExportFlags x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_ExportFlag_Constant) {
str8_list_pushf(scratch.arena, &list, "Constant");
}
if (x & CV_ExportFlag_Data) {
str8_list_pushf(scratch.arena, &list, "Data");
}
if (x & CV_ExportFlag_Private) {
str8_list_pushf(scratch.arena, &list, "Private");
}
if (x & CV_ExportFlag_NoName) {
str8_list_pushf(scratch.arena, &list, "NoName");
}
if (x & CV_ExportFlag_Ordinal) {
str8_list_pushf(scratch.arena, &list, "Ordinal");
}
if (x & CV_ExportFlag_Forwarder) {
str8_list_pushf(scratch.arena, &list, "Forwarder");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_sepcode(Arena *arena, CV_SepcodeFlags x)
{
Temp scratch = scratch_begin(&arena,1);
String8List list = {0};
if (x & CV_SepcodeFlag_IsLexicalScope) {
str8_list_pushf(scratch.arena, &list, "IsLexicalScope");
}
if (x & CV_SepcodeFlag_ReturnsToParent) {
str8_list_pushf(scratch.arena, &list, "ReturnsToParent");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_pub32_flags(Arena *arena, CV_Pub32Flags x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_Pub32Flag_Code) {
str8_list_pushf(scratch.arena, &list, "Code");
}
if (x & CV_Pub32Flag_Function) {
str8_list_pushf(scratch.arena, &list, "Function");
}
if (x & CV_Pub32Flag_ManagedCode) {
str8_list_pushf(scratch.arena, &list, "ManagedCode");
}
if (x & CV_Pub32Flag_MSIL) {
str8_list_pushf(scratch.arena, &list, "MSIL");
}
String8 result = str8_list_join(scratch.arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_generic_flags(Arena *arena, CV_GenericFlags x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_GenericFlags_CSTYLE) {
str8_list_pushf(scratch.arena, &list, "CSTYLE");
}
if (x & CV_GenericFlags_RSCLEAN) {
str8_list_pushf(scratch.arena, &list, "RSCLEAN");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_frame_proc_flags(Arena *arena, CV_FrameprocFlags x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_FrameprocFlag_UsesAlloca) {
str8_list_pushf(scratch.arena, &list, "UsesAlloca");
}
if (x & CV_FrameprocFlag_UsesSetJmp) {
str8_list_pushf(scratch.arena, &list, "UsesSetJmp");
}
if (x & CV_FrameprocFlag_UsesLongJmp) {
str8_list_pushf(scratch.arena, &list, "UsesLongJmp");
}
if (x & CV_FrameprocFlag_UsesInlAsm) {
str8_list_pushf(scratch.arena, &list, "UsesInlAsm");
}
if (x & CV_FrameprocFlag_UsesEH) {
str8_list_pushf(scratch.arena, &list, "UsesEH");
}
if (x & CV_FrameprocFlag_Inline) {
str8_list_pushf(scratch.arena, &list, "Inline");
}
if (x & CV_FrameprocFlag_HasSEH) {
str8_list_pushf(scratch.arena, &list, "HasSEH");
}
if (x & CV_FrameprocFlag_Naked) {
str8_list_pushf(scratch.arena, &list, "Naked");
}
if (x & CV_FrameprocFlag_HasSecurityChecks) {
str8_list_pushf(scratch.arena, &list, "HasSecurityChecks");
}
if (x & CV_FrameprocFlag_AsyncEH) {
str8_list_pushf(scratch.arena, &list, "AsyncEH");
}
if (x & CV_FrameprocFlag_GSNoStackOrdering) {
str8_list_pushf(scratch.arena, &list, "GSNoStackOrdering");
}
if (x & CV_FrameprocFlag_WasInlined) {
str8_list_pushf(scratch.arena, &list, "WasInlined");
}
if (x & CV_FrameprocFlag_GSCheck) {
str8_list_pushf(scratch.arena, &list, "GSCheck");
}
if (x & CV_FrameprocFlag_SafeBuffers) {
str8_list_pushf(scratch.arena, &list, "SafeBuffers");
}
if (x & CV_FrameprocFlag_PogoOn) {
str8_list_pushf(scratch.arena, &list, "PogoOn");
}
if (x & CV_FrameprocFlag_PogoCountsValid) {
str8_list_pushf(scratch.arena, &list, "PogoCountsValid");
}
if (x & CV_FrameprocFlag_OptSpeed) {
str8_list_pushf(scratch.arena, &list, "OptSpeed");
}
if (x & CV_FrameprocFlag_HasCFG) {
str8_list_pushf(scratch.arena, &list, "HasCFG");
}
if (x & CV_FrameprocFlag_HasCFW) {
str8_list_pushf(scratch.arena, &list, "HasCFW");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_type_props(Arena *arena, CV_TypeProps32 x)
{
Temp scratch = scratch_begin(&arena, 1);
U32 hfa = CV_TypeProps_Extract_HFA(x);
U32 mcom = CV_TypeProps_Extract_MOCOM(x);
String8 hfa_str = cv_string_from_hfa(hfa);
String8 mcom_str = cv_string_from_mcom(mcom);
String8 flags_str;
{
String8List list = {0};
if (x & CV_TypeProp_Packed) {
x &= ~CV_TypeProp_Packed;
str8_list_pushf(scratch.arena, &list, "Packed");
}
if (x & CV_TypeProp_HasConstructorsDestructors) {
x &= ~CV_TypeProp_HasConstructorsDestructors;
str8_list_pushf(scratch.arena, &list, "HasConstructorsDestructors");
}
if (x & CV_TypeProp_OverloadedOperators) {
x &= ~CV_TypeProp_OverloadedOperators;
str8_list_pushf(scratch.arena, &list, "OverloadedOperators");
}
if (x & CV_TypeProp_IsNested) {
x &= ~CV_TypeProp_IsNested;
str8_list_pushf(scratch.arena, &list, "IsNested");
}
if (x & CV_TypeProp_ContainsNested) {
x &= ~CV_TypeProp_ContainsNested;
str8_list_pushf(scratch.arena, &list, "ContainsNested");
}
if (x & CV_TypeProp_OverloadedAssignment) {
x &= ~CV_TypeProp_OverloadedAssignment;
str8_list_pushf(scratch.arena, &list, "OverloadedAssignment");
}
if (x & CV_TypeProp_OverloadedCasting) {
x &= ~CV_TypeProp_OverloadedCasting;
str8_list_pushf(scratch.arena, &list, "OverloadedCasting");
}
if (x & CV_TypeProp_FwdRef) {
x &= ~CV_TypeProp_FwdRef;
str8_list_pushf(scratch.arena, &list, "FwdRef");
}
if (x & CV_TypeProp_Scoped) {
x &= ~CV_TypeProp_Scoped;
str8_list_pushf(scratch.arena, &list, "Scoped");
}
if (x & CV_TypeProp_HasUniqueName) {
x &= ~CV_TypeProp_HasUniqueName;
str8_list_pushf(scratch.arena, &list, "HasUniqueName");
}
if (x & CV_TypeProp_Sealed) {
x &= ~CV_TypeProp_Sealed;
str8_list_pushf(scratch.arena, &list, "Sealed");
}
if (x & CV_TypeProp_Intrinsic) {
x &= ~CV_TypeProp_Intrinsic;
str8_list_pushf(scratch.arena, &list, "Intrinsic");
}
if (x != 0) {
str8_list_pushf(scratch.arena, &list, "%x", x);
}
flags_str = str8_list_join(scratch.arena, &list, &(StringJoin){.sep=str8_lit(", ") });
if (hfa) {
str8_list_pushf(scratch.arena, &list, "HFA = %S", hfa_str);
}
if (mcom) {
str8_list_pushf(scratch.arena, &list, "MCOM = %S", mcom_str);
}
}
String8 result = push_str8f(arena, "%S", flags_str);
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_local_flags(Arena *arena, CV_LocalFlags x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_LocalFlag_Param) {
str8_list_pushf(scratch.arena, &list, "Param");
}
if (x & CV_LocalFlag_AddrTaken) {
str8_list_pushf(scratch.arena, &list, "AddrTaken");
}
if (x & CV_LocalFlag_Compgen) {
str8_list_pushf(scratch.arena, &list, "Compgen");
}
if (x & CV_LocalFlag_Aggregate) {
str8_list_pushf(scratch.arena, &list, "Aggregate");
}
if (x & CV_LocalFlag_PartOfAggregate) {
str8_list_pushf(scratch.arena, &list, "PartOfAggregate");
}
if (x & CV_LocalFlag_Aliased) {
str8_list_pushf(scratch.arena, &list, "Aliased");
}
if (x & CV_LocalFlag_Alias) {
str8_list_pushf(scratch.arena, &list, "Alias");
}
if (x & CV_LocalFlag_Retval) {
str8_list_pushf(scratch.arena, &list, "Retval");
}
if (x & CV_LocalFlag_OptOut) {
str8_list_pushf(scratch.arena, &list, "OptOut");
}
if (x & CV_LocalFlag_Global) {
str8_list_pushf(scratch.arena, &list, "Global");
}
if (x & CV_LocalFlag_Static) {
str8_list_pushf(scratch.arena, &list, "Static");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_proc_flags(Arena *arena, CV_ProcFlags x)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (x & CV_ProcFlag_NoFPO) {
x &= ~CV_ProcFlag_NoFPO;
str8_list_pushf(scratch.arena, &list, "NoFPO");
}
if (x & CV_ProcFlag_IntReturn) {
x &= ~CV_ProcFlag_IntReturn;
str8_list_pushf(scratch.arena, &list, "IntReturn");
}
if (x & CV_ProcFlag_FarReturn) {
x &= ~CV_ProcFlag_FarReturn;
str8_list_pushf(scratch.arena, &list, "FarReturn");
}
if (x & CV_ProcFlag_NeverReturn) {
x &= ~CV_ProcFlag_NeverReturn;
str8_list_pushf(scratch.arena, &list, "NeverReturn");
}
if (x & CV_ProcFlag_NotReached) {
x &= ~CV_ProcFlag_NotReached;
str8_list_pushf(scratch.arena, &list, "NotReached");
}
if (x & CV_ProcFlag_CustomCall) {
x &= ~CV_ProcFlag_CustomCall;
str8_list_pushf(scratch.arena, &list, "CustomCall");
}
if (x & CV_ProcFlag_NoInline) {
x &= ~CV_ProcFlag_NoInline;
str8_list_pushf(scratch.arena, &list, "NoInline");
}
if (x & CV_ProcFlag_OptDbgInfo) {
x &= ~CV_ProcFlag_OptDbgInfo;
str8_list_pushf(scratch.arena, &list, "OptDbgInfo");
}
if (x != 0) {
str8_list_pushf(scratch.arena, &list, "%#x", x);
}
String8 result;
if (list.node_count == 0) {
result = str8_lit("None");
} else {
result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
}
temp_end(scratch);
return result;
}
internal String8
cv_string_from_range_attribs(Arena *arena, CV_RangeAttribs x)
{ (void)arena;
String8 result = str8_lit("None");
if (x == CV_RangeAttrib_Maybe) {
result = str8_lit("Maybe");
}
return result;
}
internal String8
cv_string_from_defrange_register_rel_flags(Arena *arena, CV_DefrangeRegisterRelFlags x)
{ (void)arena;
String8 result = str8_lit("None");
if (x == CV_DefrangeRegisterRelFlag_SpilledOutUDTMember) {
result = str8_lit("SpilledOutUDTMember");
}
return result;
}
internal String8
cv_string_from_field_attribs(Arena *arena, CV_FieldAttribs attribs)
{
Temp scratch = scratch_begin(&arena, 1);
U32 access = CV_FieldAttribs_Extract_Access(attribs);
U32 mprop = CV_FieldAttribs_Extract_MethodProp(attribs);
attribs &= ~(0x3 | 0x7);
String8 access_str = cv_string_from_member_access(access);
String8 mprop_str = cv_string_from_method_prop(mprop);
String8List list = {0};
{
if (attribs & CV_FieldAttrib_Pseudo) {
attribs &= ~CV_FieldAttrib_Pseudo;
str8_list_pushf(scratch.arena, &list, "Pseudo");
}
if (attribs & CV_FieldAttrib_NoInherit) {
attribs &= ~CV_FieldAttrib_NoInherit;
str8_list_pushf(scratch.arena, &list, "NoInherit");
}
if (attribs & CV_FieldAttrib_NoConstruct) {
attribs &= ~CV_FieldAttrib_NoConstruct;
str8_list_pushf(scratch.arena, &list, "NoConstruct");
}
if (attribs & CV_FieldAttrib_CompilerGenated) {
attribs &= ~CV_FieldAttrib_CompilerGenated;
str8_list_pushf(scratch.arena, &list, "CompilerGenerated");
}
if (attribs & CV_FieldAttrib_Sealed) {
attribs &= ~CV_FieldAttrib_Sealed;
str8_list_pushf(scratch.arena, &list, "Sealed");
}
if (attribs) {
str8_list_pushf(scratch.arena, &list, "Unknown: %x", attribs);
}
}
if (access) {
str8_list_pushf(scratch.arena, &list, "%S", access_str);
}
if (mprop) {
str8_list_pushf(scratch.arena, &list, "%S", mprop_str);
}
String8 result = str8_list_join(scratch.arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
cv_string_from_itype(Arena *arena, CV_TypeIndex min_itype, CV_TypeIndex itype)
{
String8 result = str8_zero();
if (itype < min_itype) {
String8 n = cv_type_name_from_basic_type((CV_BasicType)itype);
if (n.size) {
Temp scratch = scratch_begin(&arena, 1);
U64 type = CV_BasicTypeFromTypeId(itype);
char *type_str = "???";
switch (type) {
case CV_BasicType_NOTYPE: type_str = "NOTYPE"; break;
case CV_BasicType_ABS: type_str = "ABS"; break;
case CV_BasicType_SEGMENT: type_str = "SEGMENT"; break;
case CV_BasicType_VOID: type_str = "VOID"; break;
case CV_BasicType_CURRENCY: type_str = "CURRENCY"; break;
case CV_BasicType_NBASICSTR: type_str = "NBASICSTR"; break;
case CV_BasicType_FBASICSTR: type_str = "FBASICSTR"; break;
case CV_BasicType_NOTTRANS: type_str = "NOTTRANS"; break;
case CV_BasicType_HRESULT: type_str = "HRESULT"; break;
case CV_BasicType_CHAR: type_str = "CHAR"; break;
case CV_BasicType_SHORT: type_str = "SHORT"; break;
case CV_BasicType_LONG: type_str = "LONG"; break;
case CV_BasicType_QUAD: type_str = "QUAD"; break;
case CV_BasicType_OCT: type_str = "OCT"; break;
case CV_BasicType_UCHAR: type_str = "UCHAR"; break;
case CV_BasicType_USHORT: type_str = "USHORT"; break;
case CV_BasicType_ULONG: type_str = "ULONG"; break;
case CV_BasicType_UQUAD: type_str = "UQUAD"; break;
case CV_BasicType_UOCT: type_str = "UOCT"; break;
case CV_BasicType_BOOL8: type_str = "BOOL8"; break;
case CV_BasicType_BOOL16: type_str = "BOOL16"; break;
case CV_BasicType_BOOL32: type_str = "BOOL32"; break;
case CV_BasicType_BOOL64: type_str = "BOOL64"; break;
case CV_BasicType_FLOAT32: type_str = "FLOAT32"; break;
case CV_BasicType_FLOAT64: type_str = "FLOAT64"; break;
case CV_BasicType_FLOAT80: type_str = "FLOAT80"; break;
case CV_BasicType_FLOAT128: type_str = "FLOAT128"; break;
case CV_BasicType_FLOAT48: type_str = "FLOAT48"; break;
case CV_BasicType_FLOAT32PP: type_str = "FLOAT32PP"; break;
case CV_BasicType_FLOAT16: type_str = "FLOAT16"; break;
case CV_BasicType_COMPLEX32: type_str = "COMPLEX32"; break;
case CV_BasicType_COMPLEX64: type_str = "COMPLEX64"; break;
case CV_BasicType_COMPLEX80: type_str = "COMPLEX80"; break;
case CV_BasicType_COMPLEX128: type_str = "COMPLEX128"; break;
case CV_BasicType_BIT: type_str = "BIT"; break;
case CV_BasicType_PASCHAR: type_str = "PASCHAR"; break;
case CV_BasicType_BOOL32FF: type_str = "BOOL32FF"; break;
case CV_BasicType_INT8: type_str = "INT8"; break;
case CV_BasicType_UINT8: type_str = "UINT8"; break;
case CV_BasicType_RCHAR: type_str = "RCHAR"; break;
case CV_BasicType_WCHAR: type_str = "WCHAR"; break;
case CV_BasicType_INT16: type_str = "INT16"; break;
case CV_BasicType_UINT16: type_str = "UINT16"; break;
case CV_BasicType_INT32: type_str = "INT32"; break;
case CV_BasicType_UINT32: type_str = "UINT32"; break;
case CV_BasicType_INT64: type_str = "INT64"; break;
case CV_BasicType_UINT64: type_str = "UINT64"; break;
case CV_BasicType_INT128: type_str = "INT128"; break;
case CV_BasicType_UINT128: type_str = "UINT128"; break;
case CV_BasicType_CHAR16: type_str = "CHAR16"; break;
case CV_BasicType_CHAR32: type_str = "CHAR32"; break;
case CV_BasicType_CHAR8: type_str = "CHAR8"; break;
case CV_BasicType_PTR: type_str = "PTR"; break;
}
U64 ptr = CV_BasicPointerKindFromTypeId(itype);
char *ptr_str = "";
switch (ptr) {
case 0x1: ptr_str = "P"; break;
case 0x2: ptr_str = "PF"; break;
case 0x3: ptr_str = "PH"; break;
case 0x4: ptr_str = "32P"; break;
case 0x5: ptr_str = "32PF"; break;
case 0x6: ptr_str = "64P"; break;
}
n = upper_from_str8(scratch.arena, n);
result = push_str8f(arena, "T_%s%s(%x)", ptr_str, type_str, itype);
scratch_end(scratch);
} else {
result = push_str8f(arena, "%x", itype);
}
} else {
result = push_str8f(arena, "%x", itype);
}
return result;
}
internal String8
cv_string_from_itemid(Arena *arena, CV_ItemId itemid)
{
String8 result = push_str8f(arena, "%x", itemid);
return result;
}
internal String8
cv_string_from_symbol_type(Arena *arena, CV_SymKind symbol_type)
{
String8 str = cv_string_from_sym_kind(symbol_type);
String8 result = push_str8f(arena, "S_%S", str);
return result;
}
internal String8
cv_string_from_symbol_kind(Arena *arena, CV_SymKind kind)
{
String8 str = cv_string_from_sym_kind(kind);
String8 result = push_str8f(arena, "S_%S", str);
return result;
}
internal String8
cv_string_from_leaf_name(Arena *arena, U32 leaf_type)
{
String8 str = cv_string_from_leaf_kind(leaf_type);
String8 result = push_str8f(arena, "LF_%S", str);
return result;
}
internal String8
cv_string_sec_off(Arena *arena, U32 sec, U32 off)
{
return push_str8f(arena, "%04x:%08x", sec, off);
}
-51
View File
@@ -1,51 +0,0 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef CODEVIEW_ENUM_H
#define CODEVIEW_ENUM_H
internal String8 cv_string_from_type_index_source(CV_TypeIndexSource ti_source);
internal String8 cv_string_from_language(CV_Language x);
internal String8 cv_string_from_numeric(Arena *arena, CV_NumericParsed num);
internal String8 cv_string_from_reg_id(Arena *arena, CV_Arch arch, U32 id);
internal String8 cv_string_from_member_access(CV_MemberAccess x);
internal String8 cv_string_from_method_prop(CV_MethodProp x);
internal String8 cv_string_from_hfa(CV_HFAKind x);
internal String8 cv_string_from_mcom(CV_MoComUDTKind x);
internal String8 cv_string_from_binary_opcode(CV_InlineBinaryAnnotation x);
internal String8 cv_string_from_thunk_ordinal(CV_ThunkOrdinal x);
internal String8 cv_string_from_frame_cookie_kind(CV_FrameCookieKind x);
internal String8 cv_string_from_generic_style(CV_GenericStyle x);
internal String8 cv_string_from_trampoline_kind(CV_TrampolineKind x);
internal String8 cv_string_from_virtual_table_shape_kind(CV_VirtualTableShape x);
internal String8 cv_string_from_call_kind(CV_CallKind x);
internal String8 cv_string_from_member_pointer_kind(CV_MemberPointerKind x);
internal String8 cv_string_from_pointer_kind(CV_PointerKind x);
internal String8 cv_string_from_pointer_mode(CV_PointerMode x);
internal String8 cv_string_from_c13_checksum_kind(CV_C13ChecksumKind x);
internal String8 cv_string_from_label_kind(Arena *arena, CV_LabelKind x);
internal String8 cv_string_from_c13_subsection_kind(CV_C13SubSectionKind x);
internal String8 cv_string_from_modifier_flags(Arena *arena, CV_ModifierFlags x);
internal String8 cv_string_from_pointer_attribs(Arena *arena, CV_PointerAttribs x);
internal String8 cv_string_from_function_attribs(Arena *arena, CV_FunctionAttribs x);
internal String8 cv_string_from_export_flags(Arena *arena, CV_ExportFlags x);
internal String8 cv_string_from_sepcode(Arena *arena, CV_SepcodeFlags x);
internal String8 cv_string_from_pub32_flags(Arena *arena, CV_Pub32Flags x);
internal String8 cv_string_from_generic_flags(Arena *arena, CV_GenericFlags x);
internal String8 cv_string_from_frame_proc_flags(Arena *arena, CV_FrameprocFlags x);
internal String8 cv_string_from_type_props(Arena *arena, CV_TypeProps32 x);
internal String8 cv_string_from_local_flags(Arena *arena, CV_LocalFlags x);
internal String8 cv_string_from_proc_flags(Arena *arena, CV_ProcFlags x);
internal String8 cv_string_from_range_attribs(Arena *arena, CV_RangeAttribs x);
internal String8 cv_string_from_defrange_register_rel_flags(Arena *arena, CV_DefrangeRegisterRelFlags x);
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_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);
internal String8 cv_string_sec_off(Arena *arena, U32 sec, U32 off);
#endif // CODEVIEW_ENUM_H
+2 -1
View File
@@ -615,7 +615,8 @@ cv_get_symbol_type_index_offsets(Arena *arena, CV_SymKind kind, String8 data)
case CV_SymKind_UDT: {
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymUDT, itype));
} break;
case CV_SymKind_GTHREAD32: {
case CV_SymKind_GTHREAD32:
case CV_SymKind_LTHREAD32: {
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymThread32, itype));
} break;
case CV_SymKind_FILESTATIC: {
+651 -72
View File
@@ -8,7 +8,6 @@ coff_align_size_from_section_flags(COFF_SectionFlags flags)
U32 align_index = COFF_SectionFlags_ExtractAlign(flags);
switch (align_index) {
default: break;
case 0: align = 1; break; // alignment isn't specified, default to 1
case COFF_SectionAlign_1Bytes: align = 1; break;
case COFF_SectionAlign_2Bytes: align = 2; break;
case COFF_SectionAlign_4Bytes: align = 4; break;
@@ -32,20 +31,21 @@ coff_section_flag_from_align_size(U64 align)
{
COFF_SectionFlags flags = 0;
switch (align) {
case 1: flags = COFF_SectionAlign_1Bytes; break;
case 2: flags = COFF_SectionAlign_2Bytes; break;
case 4: flags = COFF_SectionAlign_4Bytes; break;
case 8: flags = COFF_SectionAlign_8Bytes; break;
case 16: flags = COFF_SectionAlign_16Bytes; break;
case 32: flags = COFF_SectionAlign_32Bytes; break;
case 64: flags = COFF_SectionAlign_64Bytes; break;
case 128: flags = COFF_SectionAlign_128Bytes; break;
case 256: flags = COFF_SectionAlign_256Bytes; break;
case 512: flags = COFF_SectionAlign_512Bytes; break;
case 1024: flags = COFF_SectionAlign_1024Bytes; break;
case 2048: flags = COFF_SectionAlign_2048Bytes; break;
case 4096: flags = COFF_SectionAlign_4096Bytes; break;
case 8192: flags = COFF_SectionAlign_8192Bytes; break;
case 0: flags = COFF_SectionAlign_None; break;
case 1: flags = COFF_SectionAlign_1Bytes; break;
case 2: flags = COFF_SectionAlign_2Bytes; break;
case 4: flags = COFF_SectionAlign_4Bytes; break;
case 8: flags = COFF_SectionAlign_8Bytes; break;
case 16: flags = COFF_SectionAlign_16Bytes; break;
case 32: flags = COFF_SectionAlign_32Bytes; break;
case 64: flags = COFF_SectionAlign_64Bytes; break;
case 128: flags = COFF_SectionAlign_128Bytes; break;
case 256: flags = COFF_SectionAlign_256Bytes; break;
case 512: flags = COFF_SectionAlign_512Bytes; break;
case 1024: flags = COFF_SectionAlign_1024Bytes; break;
case 2048: flags = COFF_SectionAlign_2048Bytes; break;
case 4096: flags = COFF_SectionAlign_4096Bytes; break;
case 8192: flags = COFF_SectionAlign_8192Bytes; break;
}
flags <<= COFF_SectionFlag_AlignShift;
return flags;
@@ -79,14 +79,7 @@ coff_parse_section_name(String8 full_name, String8 *name_out, String8 *postfix_o
for (U64 i = 0; i < full_name.size; ++i) {
if (full_name.str[i] == '$') {
*name_out = str8(full_name.str, i);
*postfix_out = str8(full_name.str + i + 1, full_name.size - i - 1);
// TLS sections don't have a postfix but we still have to sort them based
// on dollar sign so they are sloted between CRT's _tls_start and _tls_end sections.
if (str8_match_lit(".tls", *name_out, 0) && postfix_out->size == 0) {
*postfix_out = str8_lit("$");
}
*postfix_out = str8(full_name.str + i, full_name.size - i);
break;
}
}
@@ -179,6 +172,105 @@ coff_apply_size_from_reloc(COFF_MachineType machine, COFF_RelocType x)
return 0;
}
internal COFF_RelocValue
coff_pick_reloc_value_x64(COFF_Reloc_X64 type,
U64 image_base,
U64 reloc_virtual_offset,
U32 symbol_section_number,
U32 symbol_section_offset,
S64 symbol_virtual_offset)
{
U64 reloc_value_size = 0;
S64 reloc_value = 0;
switch (type) {
case COFF_Reloc_X64_Abs: {} break;
case COFF_Reloc_X64_Addr64: {
reloc_value_size = 8;
reloc_value = symbol_virtual_offset + (S64)image_base;
} break;
case COFF_Reloc_X64_Addr32: {
reloc_value_size = 4;
reloc_value = safe_cast_s32(symbol_virtual_offset + (S64)image_base);
} break;
case COFF_Reloc_X64_Addr32Nb: {
reloc_value_size = 4;
reloc_value = symbol_virtual_offset;
} break;
case COFF_Reloc_X64_Rel32: {
reloc_value_size = 4;
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 0));
} break;
case COFF_Reloc_X64_Rel32_1: {
reloc_value_size = 4;
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 1));
} break;
case COFF_Reloc_X64_Rel32_2: {
reloc_value_size = 4;
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 2));
} break;
case COFF_Reloc_X64_Rel32_3: {
reloc_value_size = 4;
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 3));
} break;
case COFF_Reloc_X64_Rel32_4: {
reloc_value_size = 4;
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 4));
} break;
case COFF_Reloc_X64_Rel32_5: {
reloc_value_size = 4;
reloc_value = safe_cast_s32(symbol_virtual_offset - reloc_virtual_offset - (4 + 5));
} break;
case COFF_Reloc_X64_Section: {
reloc_value_size = 4;
reloc_value = symbol_section_number;
} break;
case COFF_Reloc_X64_SecRel: {
reloc_value_size = 4;
reloc_value = symbol_section_offset;
} break;
case COFF_Reloc_X64_SecRel7:
case COFF_Reloc_X64_Token:
case COFF_Reloc_X64_SRel32:
case COFF_Reloc_X64_Pair:
case COFF_Reloc_X64_SSpan32:
case COFF_Reloc_X64_Unknown_11: {
NotImplemented;
} break;
}
COFF_RelocValue result = {0};
result.size = reloc_value_size;
result.value = reloc_value;
return result;
}
internal String8
coff_make_lib_member_header(Arena *arena, String8 name, COFF_TimeStamp time_stamp, U16 user_id, U16 group_id, U16 mode, U32 size)
{
Assert(name.size < 16);
Assert(user_id < 10000);
Assert(group_id < 10000);
Assert(mode < 10000);
Assert(size < 1000000000);
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
str8_list_pushf(scratch.arena, &list, "%-16.*s", str8_varg(name));
str8_list_pushf(scratch.arena, &list, "%-12u", time_stamp);
str8_list_pushf(scratch.arena, &list, "%-6u", user_id);
str8_list_pushf(scratch.arena, &list, "%-6u", group_id);
str8_list_pushf(scratch.arena, &list, "%-8u", mode);
str8_list_pushf(scratch.arena, &list, "%-10u", size);
str8_list_pushf(scratch.arena, &list, "`\n");
String8 result = str8_list_join(arena, &list, 0);
Assert(result.size == sizeof(COFF_ArchiveMemberHeader));
scratch_end(scratch);
return result;
}
internal String8
coff_make_import_lookup(Arena *arena, U16 hint, String8 name)
{
@@ -206,18 +298,40 @@ coff_make_ordinal64(U16 hint)
}
internal String8
coff_make_import_header_by_name(Arena *arena,
String8 dll_name,
COFF_MachineType machine,
COFF_TimeStamp time_stamp,
String8 name,
U16 hint,
COFF_ImportType type)
coff_ordinal_data_from_hint(Arena *arena, COFF_MachineType machine, U16 hint)
{
String8 ordinal_data = {0};
switch (machine) {
case COFF_MachineType_Unknown: break;
case COFF_MachineType_X64: {
U64 *ordinal = push_array(arena, U64, 1);
*ordinal = coff_make_ordinal64(hint);
ordinal_data = str8_struct(ordinal);
} break;
case COFF_MachineType_X86: {
U32 *ordinal = push_array(arena, U32, 1);
*ordinal = coff_make_ordinal32(hint);
ordinal_data = str8_struct(ordinal);
} break;
default: { NotImplemented; } break;
}
return ordinal_data;
}
internal String8
coff_make_import_header(Arena *arena,
COFF_MachineType machine,
COFF_TimeStamp time_stamp,
String8 dll_name,
COFF_ImportByType import_by,
String8 name,
U16 hint_or_ordinal,
COFF_ImportType type)
{
COFF_ImportHeaderFlags flags = 0;
flags |= (type & COFF_ImportHeader_TypeMask) << COFF_ImportHeader_TypeShift;
flags |= COFF_ImportBy_Name << COFF_ImportHeader_ImportByShift;
flags |= import_by << COFF_ImportHeader_ImportByShift;
COFF_ImportHeader header = {0};
header.sig1 = COFF_MachineType_Unknown;
header.sig2 = max_U16;
@@ -225,7 +339,7 @@ coff_make_import_header_by_name(Arena *arena,
header.machine = machine;
header.time_stamp = time_stamp;
header.data_size = safe_cast_u32(name.size + dll_name.size + 2);
header.hint_or_ordinal = hint;
header.hint_or_ordinal = hint_or_ordinal;
header.flags = flags;
// alloc memory
@@ -249,46 +363,33 @@ coff_make_import_header_by_name(Arena *arena,
return import_data;
}
internal String8
coff_make_import_header_by_ordinal(Arena *arena,
String8 dll_name,
COFF_MachineType machine,
COFF_TimeStamp time_stamp,
U16 ordinal,
COFF_ImportType type)
internal U8
coff_code_align_byte_from_machine(COFF_MachineType machine)
{
COFF_ImportHeaderFlags flags = 0;
flags |= (type & COFF_ImportHeader_TypeMask) << COFF_ImportHeader_TypeShift;
flags |= COFF_ImportBy_Ordinal << COFF_ImportHeader_ImportByShift;
COFF_ImportHeader header = {0};
header.sig1 = COFF_MachineType_Unknown;
header.sig2 = max_U16;
header.version = 0;
header.machine = machine;
header.time_stamp = time_stamp;
header.data_size = safe_cast_u32(dll_name.size + 2);
header.hint_or_ordinal = ordinal;
header.flags = flags;
// alloc memory
U64 buffer_size = sizeof(header) + header.data_size;
U8 *buffer = push_array_no_zero(arena, U8, buffer_size);
// copy header
MemoryCopyStruct(buffer, &header);
// no function name write zero
U8 *func_name = buffer + sizeof(header);
func_name[0] = 0;
// copy dll name
U8 *dll_name_buffer = buffer + sizeof(header) + /* name.size */ + 1;
MemoryCopy(dll_name_buffer, dll_name.str, dll_name.size);
dll_name_buffer[dll_name.size] = 0;
String8 import_data = str8(buffer, buffer_size);
return import_data;
U8 align_byte = 0;
switch (machine) {
case COFF_MachineType_Unknown: break;
case COFF_MachineType_X64:
case COFF_MachineType_X86: {
align_byte = 0xCC;
} break;
default: { NotImplemented; } break;
}
return align_byte;
}
internal U16
coff_default_align_from_machine(COFF_MachineType machine)
{
U16 align = 0;
switch (machine) {
case COFF_MachineType_Unknown: break;
case COFF_MachineType_X64: {
align = 16;
} break;
default: { NotImplemented; } break;
}
return align;
}
internal U64
@@ -358,3 +459,481 @@ coff_foff_from_voff(COFF_SectionHeader *sections, U64 section_count, U64 voff)
return foff;
}
////////////////////////////////
//~ rjf: Enum -> String
internal String8
coff_string_from_time_stamp(Arena *arena, COFF_TimeStamp time_stamp)
{
String8 result;
if (time_stamp == 0) {
result = str8_lit("0");
} else if (time_stamp >= max_U32) {
result = str8_lit("-1");
} else {
DateTime dt = date_time_from_unix_time(time_stamp);
result = push_date_time_string(arena, &dt);
}
return result;
}
read_only struct
{
String8 string;
COFF_MachineType machine;
} g_coff_machine_map[] = {
{ 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 {
char * name;
COFF_ImportType type;
} g_coff_import_header_type_map[] = {
{ "Code", COFF_ImportHeader_Code },
{ "Data", COFF_ImportHeader_Data },
{ "Const", COFF_ImportHeader_Const },
};
internal String8
coff_string_from_comdat_select_type(COFF_ComdatSelectType type)
{
String8 result = str8_zero();
switch (type) {
case COFF_ComdatSelect_Null: result = str8_lit("Null"); break;
case COFF_ComdatSelect_NoDuplicates: result = str8_lit("NoDuplicates"); break;
case COFF_ComdatSelect_Any: result = str8_lit("Any"); break;
case COFF_ComdatSelect_SameSize: result = str8_lit("SameSize"); break;
case COFF_ComdatSelect_ExactMatch: result = str8_lit("ExactMatch"); break;
case COFF_ComdatSelect_Associative: result = str8_lit("Associative"); break;
case COFF_ComdatSelect_Largest: result = str8_lit("Largest"); break;
}
return result;
}
internal String8
coff_string_from_machine_type(COFF_MachineType machine)
{
for (U64 i = 0; i < ArrayCount(g_coff_machine_map); ++i) {
if (g_coff_machine_map[i].machine == machine) {
return g_coff_machine_map[i].string;
}
}
return str8_zero();
}
internal String8
coff_string_from_flags(Arena *arena, COFF_FileHeaderFlags flags)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (flags & COFF_FileHeaderFlag_RelocStripped) {
str8_list_pushf(scratch.arena, &list, "Relocs Stripped");
}
if (flags & COFF_FileHeaderFlag_ExecutableImage) {
str8_list_pushf(scratch.arena, &list, "Executable");
}
if (flags & COFF_FileHeaderFlag_LineNumbersStripped) {
str8_list_pushf(scratch.arena, &list, "Line Numbers Stripped");
}
if (flags & COFF_FileHeaderFlag_SymbolsStripped) {
str8_list_pushf(scratch.arena, &list, "Symbols Stripped");
}
if (flags & COFF_FileHeaderFlag_LargeAddressAware) {
str8_list_pushf(scratch.arena, &list, "Large Address Aware");
}
if (flags & COFF_FileHeaderFlag_32BitMachine) {
str8_list_pushf(scratch.arena, &list, "32-Bit Machine");
}
if (flags & COFF_FileHeaderFlag_DebugStripped) {
str8_list_pushf(scratch.arena, &list, "Debug Stripped");
}
if (flags & COFF_FileHeaderFlag_RemovableRunFromSwap) {
str8_list_pushf(scratch.arena, &list, "Removeable Run From Swap");
}
if (flags & COFF_FileHeaderFlag_NetRunFromSwap) {
str8_list_pushf(scratch.arena, &list, "Net Run From Swap");
}
if (flags & COFF_FileHeaderFlag_System) {
str8_list_pushf(scratch.arena, &list, "System");
}
if (flags & COFF_FileHeaderFlag_Dll) {
str8_list_pushf(scratch.arena, &list, "DLL");
}
if (flags & COFF_FileHeaderFlag_UpSystemOnly) {
str8_list_pushf(scratch.arena, &list, "Up System Only");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
coff_string_from_section_flags(Arena *arena, COFF_SectionFlags flags)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (flags & COFF_SectionFlag_TypeNoPad) {
str8_list_pushf(scratch.arena, &list, "TypeNoPad");
}
if (flags & COFF_SectionFlag_CntCode) {
str8_list_pushf(scratch.arena, &list, "CntCode");
}
if (flags & COFF_SectionFlag_CntInitializedData) {
str8_list_pushf(scratch.arena, &list, "CntInitializedData");
}
if (flags & COFF_SectionFlag_CntUninitializedData) {
str8_list_pushf(scratch.arena, &list, "CntUninitializedData");
}
if (flags & COFF_SectionFlag_LnkOther) {
str8_list_pushf(scratch.arena, &list, "LnkOther");
}
if (flags & COFF_SectionFlag_LnkInfo) {
str8_list_pushf(scratch.arena, &list, "LnkInfo");
}
if (flags & COFF_SectionFlag_LnkCOMDAT) {
str8_list_pushf(scratch.arena, &list, "LnkCOMDAT");
}
if (flags & COFF_SectionFlag_GpRel) {
str8_list_pushf(scratch.arena, &list, "GpRel");
}
if (flags & COFF_SectionFlag_Mem16Bit) {
str8_list_pushf(scratch.arena, &list, "Mem16Bit");
}
if (flags & COFF_SectionFlag_MemLocked) {
str8_list_pushf(scratch.arena, &list, "MemLocked");
}
if (flags & COFF_SectionFlag_MemPreload) {
str8_list_pushf(scratch.arena, &list, "MemPreload");
}
if (flags & COFF_SectionFlag_LnkNRelocOvfl) {
str8_list_pushf(scratch.arena, &list, "LnkNRelocOvfl");
}
if (flags & COFF_SectionFlag_MemDiscardable) {
str8_list_pushf(scratch.arena, &list, "MemDiscardable");
}
if (flags & COFF_SectionFlag_MemNotCached) {
str8_list_pushf(scratch.arena, &list, "MemNotCached");
}
if (flags & COFF_SectionFlag_MemNotPaged) {
str8_list_pushf(scratch.arena, &list, "MemNotPaged");
}
if (flags & COFF_SectionFlag_MemShared) {
str8_list_pushf(scratch.arena, &list, "MemShared");
}
if (flags & COFF_SectionFlag_MemExecute) {
str8_list_pushf(scratch.arena, &list, "MemExecute");
}
if (flags & COFF_SectionFlag_MemRead) {
str8_list_pushf(scratch.arena, &list, "MemRead");
}
if (flags & COFF_SectionFlag_MemWrite) {
str8_list_pushf(scratch.arena, &list, "MemWrite");
}
U64 align = coff_align_size_from_section_flags(flags);
if (align) {
str8_list_pushf(scratch.arena, &list, "Align=%u", align);
}
if (!list.node_count) {
str8_list_pushf(scratch.arena, &list, "None");
}
StringJoin join = {0};
join.sep = str8_lit(", ");
String8 result = str8_list_join(arena, &list, &join);
scratch_end(scratch);
return result;
}
internal String8
coff_string_from_resource_memory_flags(Arena *arena, COFF_ResourceMemoryFlags flags)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (flags & COFF_ResourceMemoryFlag_Moveable) {
flags &= COFF_ResourceMemoryFlag_Moveable;
str8_list_pushf(scratch.arena, &list, "Moveable");
}
if (flags & COFF_ResourceMemoryFlag_Pure) {
flags &= COFF_ResourceMemoryFlag_Pure;
str8_list_pushf(scratch.arena, &list, "Pure");
}
if (flags & COFF_ResourceMemoryFlag_Discardable) {
flags &= COFF_ResourceMemoryFlag_Discardable;
str8_list_pushf(scratch.arena, &list, "Discardable");
}
if (flags != 0) {
str8_list_pushf(scratch.arena, &list, "%#x", flags);
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
coff_string_from_import_header_type(COFF_ImportType type)
{
for (U64 i = 0; i < ArrayCount(g_coff_import_header_type_map); ++i) {
if (g_coff_import_header_type_map[i].type == type) {
return str8_cstring(g_coff_import_header_type_map[i].name);
}
}
return str8(0,0);
}
internal String8
coff_string_from_sym_dtype(COFF_SymDType x)
{
switch (x) {
case COFF_SymDType_Null: return str8_lit("Null");
case COFF_SymDType_Ptr : return str8_lit("Ptr");
case COFF_SymDType_Func: return str8_lit("Func");
case COFF_SymDType_Array: return str8_lit("Array");
}
return str8_zero();
}
internal String8
coff_string_from_sym_type(COFF_SymType x)
{
switch (x) {
case COFF_SymType_Null: return str8_lit("Null");
case COFF_SymType_Void: return str8_lit("Void");
case COFF_SymType_Char: return str8_lit("Char");
case COFF_SymType_Short: return str8_lit("Short");
case COFF_SymType_Int: return str8_lit("Int");
case COFF_SymType_Long: return str8_lit("Long");
case COFF_SymType_Float: return str8_lit("Float");
case COFF_SymType_Double: return str8_lit("Double");
case COFF_SymType_Struct: return str8_lit("Struct");
case COFF_SymType_Union: return str8_lit("Union");
case COFF_SymType_Enum: return str8_lit("Enum");
case COFF_SymType_MemberOfEnumeration: return str8_lit("MOE");
case COFF_SymType_Byte: return str8_lit("Byte");
case COFF_SymType_Word: return str8_lit("Word");
case COFF_SymType_UInt: return str8_lit("UInt");
case COFF_SymType_DWord: return str8_lit("DWord");
}
return str8_zero();
}
internal String8
coff_string_from_sym_storage_class(COFF_SymStorageClass x)
{
switch (x) {
case COFF_SymStorageClass_Null: break;
case COFF_SymStorageClass_EndOfFunction: return str8_lit("EndOfFunction");
case COFF_SymStorageClass_Automatic: return str8_lit("Automatic");
case COFF_SymStorageClass_External: return str8_lit("External");
case COFF_SymStorageClass_Static: return str8_lit("Static");
case COFF_SymStorageClass_Register: return str8_lit("Register");
case COFF_SymStorageClass_ExternalDef: return str8_lit("Def");
case COFF_SymStorageClass_Label: return str8_lit("Label");
case COFF_SymStorageClass_UndefinedLabel: return str8_lit("UndefinedLabel");
case COFF_SymStorageClass_MemberOfStruct: return str8_lit("Struct");
case COFF_SymStorageClass_Argument: return str8_lit("Argument");
case COFF_SymStorageClass_StructTag: return str8_lit("Tag");
case COFF_SymStorageClass_MemberOfUnion: return str8_lit("Union");
case COFF_SymStorageClass_UnionTag: return str8_lit("Tag");
case COFF_SymStorageClass_TypeDefinition: return str8_lit("Definition");
case COFF_SymStorageClass_UndefinedStatic: return str8_lit("Static");
case COFF_SymStorageClass_EnumTag: return str8_lit("Tag");
case COFF_SymStorageClass_MemberOfEnum: return str8_lit("Enum");
case COFF_SymStorageClass_RegisterParam: return str8_lit("Param");
case COFF_SymStorageClass_BitField: return str8_lit("Field");
case COFF_SymStorageClass_Block: return str8_lit("Block");
case COFF_SymStorageClass_Function: return str8_lit("Function");
case COFF_SymStorageClass_EndOfStruct: return str8_lit("Struct");
case COFF_SymStorageClass_File: return str8_lit("File");
case COFF_SymStorageClass_Section: return str8_lit("Section");
case COFF_SymStorageClass_WeakExternal: return str8_lit("External");
case COFF_SymStorageClass_CLRToken: return str8_lit("Token");
}
return str8_zero();
}
internal String8
coff_string_from_weak_ext_type(COFF_WeakExtType x)
{
switch (x) {
case COFF_WeakExt_NoLibrary: return str8_lit("NoLibrary");
case COFF_WeakExt_SearchLibrary: return str8_lit("SearchLibrary");
case COFF_WeakExt_SearchAlias: return str8_lit("SearchAlias");
}
return str8_zero();
}
internal String8
coff_string_from_reloc_x86(COFF_Reloc_X86 x)
{
switch (x) {
case COFF_Reloc_X86_Abs: return str8_lit("Abs");
case COFF_Reloc_X86_Dir16: return str8_lit("Dir16");
case COFF_Reloc_X86_Rel16: return str8_lit("Rel16");
case COFF_Reloc_X86_Unknown0: return str8_lit("Unknown0");
case COFF_Reloc_X86_Unknown2: return str8_lit("Unknown2");
case COFF_Reloc_X86_Unknown3: return str8_lit("Unknown3");
case COFF_Reloc_X86_Dir32: return str8_lit("Dir32");
case COFF_Reloc_X86_Dir32Nb: return str8_lit("Dir32Nb");
case COFF_Reloc_X86_Seg12: return str8_lit("Seg12");
case COFF_Reloc_X86_Section: return str8_lit("Section");
case COFF_Reloc_X86_SecRel: return str8_lit("SecRel");
case COFF_Reloc_X86_Token: return str8_lit("Token");
case COFF_Reloc_X86_SecRel7: return str8_lit("SecRel7");
case COFF_Reloc_X86_Unknown4: return str8_lit("Unknown4");
case COFF_Reloc_X86_Unknown5: return str8_lit("Unknown5");
case COFF_Reloc_X86_Unknown6: return str8_lit("Unknown6");
case COFF_Reloc_X86_Unknown7: return str8_lit("Unknown7");
case COFF_Reloc_X86_Unknown8: return str8_lit("Unknown8");
case COFF_Reloc_X86_Unknown9: return str8_lit("Unknown9");
case COFF_Reloc_X86_Rel32: return str8_lit("Rel32");
}
return str8_zero();
}
internal String8
coff_string_from_reloc_x64(COFF_Reloc_X64 x)
{
switch (x) {
case COFF_Reloc_X64_Abs: return str8_lit("Abs");
case COFF_Reloc_X64_Addr64: return str8_lit("Addr64");
case COFF_Reloc_X64_Addr32: return str8_lit("Addr32");
case COFF_Reloc_X64_Addr32Nb: return str8_lit("Addr32Nb");
case COFF_Reloc_X64_Rel32: return str8_lit("Rel32");
case COFF_Reloc_X64_Rel32_1: return str8_lit("Rel32_1");
case COFF_Reloc_X64_Rel32_2: return str8_lit("Rel32_2");
case COFF_Reloc_X64_Rel32_3: return str8_lit("Rel32_3");
case COFF_Reloc_X64_Rel32_4: return str8_lit("Rel32_4");
case COFF_Reloc_X64_Rel32_5: return str8_lit("Rel32_5");
case COFF_Reloc_X64_Section: return str8_lit("Section");
case COFF_Reloc_X64_SecRel: return str8_lit("SecRel");
case COFF_Reloc_X64_SecRel7: return str8_lit("SecRel7");
case COFF_Reloc_X64_Token: return str8_lit("Token");
case COFF_Reloc_X64_SRel32: return str8_lit("SRel32");
case COFF_Reloc_X64_Pair: return str8_lit("Pair");
case COFF_Reloc_X64_SSpan32: return str8_lit("SSpan32");
}
return str8_zero();
}
internal String8
coff_string_from_reloc_arm(COFF_Reloc_Arm x)
{
switch (x) {
case COFF_Reloc_Arm_Abs: return str8_lit("Abs");
case COFF_Reloc_Arm_Addr32: return str8_lit("Addr32");
case COFF_Reloc_Arm_Addr32Nb: return str8_lit("Addr32Nb");
case COFF_Reloc_Arm_Branch24: return str8_lit("Branch24");
case COFF_Reloc_Arm_Branch11: return str8_lit("Branch11");
case COFF_Reloc_Arm_Unknown1: return str8_lit("Unknown1");
case COFF_Reloc_Arm_Unknown2: return str8_lit("Unknown2");
case COFF_Reloc_Arm_Unknown3: return str8_lit("Unknown3");
case COFF_Reloc_Arm_Unknown4: return str8_lit("Unknown4");
case COFF_Reloc_Arm_Unknown5: return str8_lit("Unknown5");
case COFF_Reloc_Arm_Rel32: return str8_lit("Rel32");
case COFF_Reloc_Arm_Section: return str8_lit("Section");
case COFF_Reloc_Arm_SecRel: return str8_lit("SecRel");
case COFF_Reloc_Arm_Mov32: return str8_lit("Mov32");
case COFF_Reloc_Arm_ThumbMov32: return str8_lit("ThumbMov32");
case COFF_Reloc_Arm_ThumbBranch20: return str8_lit("ThumbBranch20");
case COFF_Reloc_Arm_Unused: return str8_lit("Unused");
case COFF_Reloc_Arm_ThumbBranch24: return str8_lit("ThumbBranch24");
case COFF_Reloc_Arm_ThumbBlx23: return str8_lit("ThumbBlx23");
case COFF_Reloc_Arm_Pair: return str8_lit("Pair");
}
return str8_zero();
}
internal String8
coff_string_from_reloc_arm64(COFF_Reloc_Arm64 x)
{
switch (x) {
case COFF_Reloc_Arm64_Abs: return str8_lit("Abs");
case COFF_Reloc_Arm64_Addr32: return str8_lit("Addr32");
case COFF_Reloc_Arm64_Addr32Nb: return str8_lit("Addr32Nb");
case COFF_Reloc_Arm64_Branch26: return str8_lit("Branch26");
case COFF_Reloc_Arm64_PageBaseRel21: return str8_lit("PageBaseRel21");
case COFF_Reloc_Arm64_Rel21: return str8_lit("Rel21");
case COFF_Reloc_Arm64_PageOffset12a: return str8_lit("PageOffset12a");
case COFF_Reloc_Arm64_SecRel: return str8_lit("SecRel");
case COFF_Reloc_Arm64_SecRelLow12a: return str8_lit("SecRelLow12a");
case COFF_Reloc_Arm64_SecRelHigh12a: return str8_lit("SecRelHigh12a");
case COFF_Reloc_Arm64_SecRelLow12l: return str8_lit("SecRelLow12l");
case COFF_Reloc_Arm64_Token: return str8_lit("Token");
case COFF_Reloc_Arm64_Section: return str8_lit("Section");
case COFF_Reloc_Arm64_Addr64: return str8_lit("Addr64");
case COFF_Reloc_Arm64_Branch19: return str8_lit("Branch19");
case COFF_Reloc_Arm64_Branch14: return str8_lit("Branch14");
case COFF_Reloc_Arm64_Rel32: return str8_lit("Rel32");
}
return str8_zero();
}
internal String8
coff_string_from_reloc(COFF_MachineType machine, COFF_RelocType x)
{
switch (machine) {
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();
}
internal COFF_MachineType
coff_machine_from_string(String8 string)
{
for (U64 i = 0; i < ArrayCount(g_coff_machine_map); ++i) {
if (str8_match(g_coff_machine_map[i].string, string, StringMatchFlag_CaseInsensitive)) {
return g_coff_machine_map[i].machine;
}
}
return COFF_MachineType_Unknown;
}
internal COFF_ImportType
coff_import_header_type_from_string(String8 name)
{
for (U64 i = 0; i < ArrayCount(g_coff_import_header_type_map); ++i) {
if (str8_match(str8_cstring(g_coff_import_header_type_map[i].name), name, StringMatchFlag_CaseInsensitive)) {
return g_coff_import_header_type_map[i].type;
}
}
return COFF_ImportType_Invalid;
}
+76 -26
View File
@@ -21,6 +21,7 @@ read_only global U8 g_coff_thin_archive_sig[8] = "!<thin>\n";
#pragma pack(push, 1)
#define COFF_TimeStamp_Max max_U32
typedef U32 COFF_TimeStamp;
typedef U16 COFF_FileHeaderFlags;
@@ -102,6 +103,7 @@ typedef struct COFF_BigObjHeader
typedef U32 COFF_SectionAlign;
enum
{
COFF_SectionAlign_None = 0x0,
COFF_SectionAlign_1Bytes = 0x1,
COFF_SectionAlign_2Bytes = 0x2,
COFF_SectionAlign_4Bytes = 0x3,
@@ -135,6 +137,20 @@ enum
COFF_SectionFlag_MemPreload = (1 << 19),
COFF_SectionFlag_AlignShift = 20,
COFF_SectionFlag_AlignMask = 0xf,
COFF_SectionFlag_Align1Bytes = (COFF_SectionAlign_1Bytes << COFF_SectionFlag_AlignShift),
COFF_SectionFlag_Align2Bytes = (COFF_SectionAlign_2Bytes << COFF_SectionFlag_AlignShift),
COFF_SectionFlag_Align4Bytes = (COFF_SectionAlign_4Bytes << COFF_SectionFlag_AlignShift),
COFF_SectionFlag_Align8Bytes = (COFF_SectionAlign_8Bytes << COFF_SectionFlag_AlignShift),
COFF_SectionFlag_Align16Bytes = (COFF_SectionAlign_16Bytes << COFF_SectionFlag_AlignShift),
COFF_SectionFlag_Align32Bytes = (COFF_SectionAlign_32Bytes << COFF_SectionFlag_AlignShift),
COFF_SectionFlag_Align64Bytes = (COFF_SectionAlign_64Bytes << COFF_SectionFlag_AlignShift),
COFF_SectionFlag_Align128Bytes = (COFF_SectionAlign_128Bytes << COFF_SectionFlag_AlignShift),
COFF_SectionFlag_Align256Bytes = (COFF_SectionAlign_256Bytes << COFF_SectionFlag_AlignShift),
COFF_SectionFlag_Align512Bytes = (COFF_SectionAlign_512Bytes << COFF_SectionFlag_AlignShift),
COFF_SectionFlag_Align1024Bytes = (COFF_SectionAlign_1024Bytes << COFF_SectionFlag_AlignShift),
COFF_SectionFlag_Align2048Bytes = (COFF_SectionAlign_2048Bytes << COFF_SectionFlag_AlignShift),
COFF_SectionFlag_Align4096Bytes = (COFF_SectionAlign_4096Bytes << COFF_SectionFlag_AlignShift),
COFF_SectionFlag_Align8192Bytes = (COFF_SectionAlign_8192Bytes << COFF_SectionFlag_AlignShift),
COFF_SectionFlag_LnkNRelocOvfl = (1 << 24),
COFF_SectionFlag_MemDiscardable = (1 << 25),
COFF_SectionFlag_MemNotCached = (1 << 26),
@@ -275,15 +291,13 @@ typedef struct COFF_Symbol32
U8 aux_symbol_count;
} COFF_Symbol32;
// Auxilary symbols are allocated with fixed size so that symbol table could be maintaned as array of regular size.
#define COFF_AuxSymbolSize 18
typedef U32 COFF_WeakExtType;
enum
{
COFF_WeakExt_NoLibrary = 1,
COFF_WeakExt_SearchLibrary = 2,
COFF_WeakExt_SearchAlias = 3
COFF_WeakExt_NoLibrary = 1,
COFF_WeakExt_SearchLibrary = 2,
COFF_WeakExt_SearchAlias = 3,
COFF_WeakExt_AntiDependency = 4, // default symbol must not reference a weak symbol
};
// storage class: External
@@ -352,23 +366,25 @@ typedef U16 COFF_RelocType;
typedef COFF_RelocType COFF_Reloc_X64;
enum
{
COFF_Reloc_X64_Abs = 0x0,
COFF_Reloc_X64_Addr64 = 0x1,
COFF_Reloc_X64_Addr32 = 0x2,
COFF_Reloc_X64_Addr32Nb = 0x3, // NB => No Base
COFF_Reloc_X64_Rel32 = 0x4,
COFF_Reloc_X64_Rel32_1 = 0x5,
COFF_Reloc_X64_Rel32_2 = 0x6,
COFF_Reloc_X64_Rel32_3 = 0x7,
COFF_Reloc_X64_Rel32_4 = 0x8,
COFF_Reloc_X64_Rel32_5 = 0x9,
COFF_Reloc_X64_Section = 0xA,
COFF_Reloc_X64_SecRel = 0xB,
COFF_Reloc_X64_SecRel7 = 0xC, // TODO(nick): MSDN doesn't specify size for CLR token
COFF_Reloc_X64_Token = 0xD,
COFF_Reloc_X64_SRel32 = 0xE, // TODO(nick): MSDN doesn't specify size for PAIR
COFF_Reloc_X64_Pair = 0xF,
COFF_Reloc_X64_SSpan32 = 0x10
COFF_Reloc_X64_Abs = 0x0,
COFF_Reloc_X64_Addr64 = 0x1,
COFF_Reloc_X64_Addr32 = 0x2,
COFF_Reloc_X64_Addr32Nb = 0x3, // NB => No Base
COFF_Reloc_X64_Rel32 = 0x4,
COFF_Reloc_X64_Rel32_1 = 0x5,
COFF_Reloc_X64_Rel32_2 = 0x6,
COFF_Reloc_X64_Rel32_3 = 0x7,
COFF_Reloc_X64_Rel32_4 = 0x8,
COFF_Reloc_X64_Rel32_5 = 0x9,
COFF_Reloc_X64_Section = 0xA,
COFF_Reloc_X64_SecRel = 0xB,
COFF_Reloc_X64_SecRel7 = 0xC, // TODO(nick): MSDN doesn't specify size for CLR token
COFF_Reloc_X64_Token = 0xD,
COFF_Reloc_X64_SRel32 = 0xE, // TODO(nick): MSDN doesn't specify size for PAIR
COFF_Reloc_X64_Pair = 0xF,
COFF_Reloc_X64_SSpan32 = 0x10,
COFF_Reloc_X64_Unknown_11 = 0x11,
COFF_Reloc_X64_Last = COFF_Reloc_X64_Unknown_11,
};
typedef COFF_RelocType COFF_Reloc_X86;
@@ -561,6 +577,12 @@ typedef struct COFF_ImportHeader
#pragma pack(pop)
typedef struct COFF_RelocValue
{
U64 size;
S64 value;
} COFF_RelocValue;
////////////////////////////////
// Section
@@ -581,19 +603,24 @@ internal String8 coff_read_symbol_name(String8 string_table, COFF_SymbolName *na
internal U64 coff_apply_size_from_reloc_x64(COFF_Reloc_X64 x);
internal U64 coff_apply_size_from_reloc_x86(COFF_Reloc_X86 x);
internal COFF_RelocValue coff_pick_reloc_value_x64(COFF_Reloc_X64 type, U64 image_base, U64 reloc_virtual_offset, U32 symbol_section_number, U32 symbol_section_offset, S64 symbol_virtual_offset);
////////////////////////////////
// Import
internal U32 coff_make_ordinal32(U16 hint);
internal U64 coff_make_ordinal64(U16 hint);
internal String8 coff_ordinal_data_from_hint(Arena *arena, COFF_MachineType machine, U16 hint);
internal String8 coff_make_import_lookup (Arena *arena, U16 hint, String8 name);
internal String8 coff_make_import_header_by_name (Arena *arena, String8 dll_name, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 name, U16 hint, COFF_ImportType type);
internal String8 coff_make_import_header_by_ordinal(Arena *arena, String8 dll_name, COFF_MachineType machine, COFF_TimeStamp time_stamp, U16 ordinal, COFF_ImportType type);
internal String8 coff_make_lib_member_header(Arena *arena, String8 name, COFF_TimeStamp time_stamp, U16 user_id, U16 group_id, U16 mode, U32 size);
internal String8 coff_make_import_lookup(Arena *arena, U16 hint, String8 name);
internal String8 coff_make_import_header(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, COFF_ImportByType import_by, String8 name, U16 hint_or_ordinal, COFF_ImportType type);
////////////////////////////////
// Misc
internal U16 coff_default_align_from_machine (COFF_MachineType machine);
internal U8 coff_code_align_byte_from_machine (COFF_MachineType machine);
internal U64 coff_word_size_from_machine (COFF_MachineType machine);
internal U64 coff_default_exe_base_from_machine(COFF_MachineType machine);
internal U64 coff_default_dll_base_from_machine(COFF_MachineType machine);
@@ -601,4 +628,27 @@ internal U64 coff_default_dll_base_from_machine(COFF_MachineType machine);
internal Arch arch_from_coff_machine(COFF_MachineType machine);
internal U64 coff_foff_from_voff(COFF_SectionHeader *sections, U64 section_count, U64 voff);
////////////////////////////////
//~ rjf: Enum <=> String
internal String8 coff_string_from_time_stamp(Arena *arena, COFF_TimeStamp time_stamp);
internal String8 coff_string_from_comdat_select_type(COFF_ComdatSelectType type);
internal String8 coff_string_from_machine_type(COFF_MachineType machine);
internal String8 coff_string_from_flags(Arena *arena, COFF_FileHeaderFlags flags);
internal String8 coff_string_from_section_flags(Arena *arena, COFF_SectionFlags flags);
internal String8 coff_string_from_resource_memory_flags(Arena *arena, COFF_ResourceMemoryFlags flags);
internal String8 coff_string_from_import_header_type(COFF_ImportType type);
internal String8 coff_string_from_sym_dtype(COFF_SymDType x);
internal String8 coff_string_from_sym_type(COFF_SymType x);
internal String8 coff_string_from_sym_storage_class(COFF_SymStorageClass x);
internal String8 coff_string_from_weak_ext_type(COFF_WeakExtType x);
internal String8 coff_string_from_reloc_x86(COFF_Reloc_X86 x);
internal String8 coff_string_from_reloc_x64(COFF_Reloc_X64 x);
internal String8 coff_string_from_reloc_arm(COFF_Reloc_Arm x);
internal String8 coff_string_from_reloc_arm64(COFF_Reloc_Arm64 x);
internal String8 coff_string_from_reloc(COFF_MachineType machine, COFF_RelocType x);
internal COFF_MachineType coff_machine_from_string(String8 string);
internal COFF_ImportType coff_import_header_type_from_string(String8 name);
#endif // COFF_H
+819
View File
@@ -0,0 +1,819 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#if 0
internal void
coff_print_archive_member_header(Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveMemberHeader header, String8 long_names)
{
Temp scratch = scratch_begin(&arena, 1);
String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header.time_stamp);
rd_printf("Name : %S" , header.name );
rd_printf("Time Stamp: (%#x) %S" , header.time_stamp, time_stamp );
rd_printf("User ID : %u" , header.user_id );
rd_printf("Group ID : %u" , header.group_id);
rd_printf("Mode : %S" , header.mode );
rd_printf("Data : [%#llx-%#llx)", header.data_range.min, header.data_range.max);
scratch_end(scratch);
}
internal void
coff_print_section_table(Arena *arena,
String8List *out,
String8 indent,
String8 string_table,
COFF_Symbol32Array symbol_table,
U64 section_count,
COFF_SectionHeader *section_table)
{
Temp scratch = scratch_begin(&arena, 1);
String8 *symlinks = push_array(scratch.arena, String8, section_count);
for (U64 i = 0; i < symbol_table.count; ++i) {
COFF_Symbol32 *symbol = symbol_table.v+i;
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol->section_number, symbol->value, symbol->storage_class);
if (interp == COFF_SymbolValueInterp_Regular &&
symbol->aux_symbol_count == 0 &&
(symbol->storage_class == COFF_SymStorageClass_External || symbol->storage_class == COFF_SymStorageClass_Static)) {
if (symbol->section_number > 0 && symbol->section_number <= symbol_table.count) {
COFF_SectionHeader *header = section_table+(symbol->section_number-1);
if (header->flags & COFF_SectionFlag_LnkCOMDAT) {
symlinks[symbol->section_number-1] = coff_read_symbol_name(string_table, &symbol->name);
}
}
}
i += symbol->aux_symbol_count;
}
if (section_count) {
rd_printf("# Section Table");
rd_indent();
rd_printf("%-4s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-8s %-5s %-10s %s",
"No.",
"Name",
"VirtSize",
"VirtOff",
"FileSize",
"FileOff",
"RelocOff",
"LinesOff",
"RelocCnt",
"LineCnt",
"Align",
"Flags",
"Symlink");
for (U64 i = 0; i < section_count; ++i) {
COFF_SectionHeader *header = section_table+i;
String8 name = str8_cstring_capped(header->name, header->name+sizeof(header->name));
String8 full_name = coff_name_from_section_header(string_table, header);
String8 align;
{
U64 align_size = coff_align_size_from_section_flags(header->flags);
align = push_str8f(scratch.arena, "%u", align_size);
}
String8 flags;
{
String8List mem_flags = {0};
if (header->flags & COFF_SectionFlag_MemRead) {
str8_list_pushf(scratch.arena, &mem_flags, "r");
}
if (header->flags & COFF_SectionFlag_MemWrite) {
str8_list_pushf(scratch.arena, &mem_flags, "w");
}
if (header->flags & COFF_SectionFlag_MemExecute) {
str8_list_pushf(scratch.arena, &mem_flags, "x");
}
String8List cnt_flags = {0};
if (header->flags & COFF_SectionFlag_CntCode) {
str8_list_pushf(scratch.arena, &cnt_flags, "c");
}
if (header->flags & COFF_SectionFlag_CntInitializedData) {
str8_list_pushf(scratch.arena, &cnt_flags, "d");
}
if (header->flags & COFF_SectionFlag_CntUninitializedData) {
str8_list_pushf(scratch.arena, &cnt_flags, "u");
}
String8List mem_extra_flags = {0};
if (header->flags & COFF_SectionFlag_MemShared) {
str8_list_pushf(scratch.arena, &mem_flags, "s");
}
if (header->flags & COFF_SectionFlag_Mem16Bit) {
str8_list_pushf(scratch.arena, &mem_extra_flags, "h");
}
if (header->flags & COFF_SectionFlag_MemLocked) {
str8_list_pushf(scratch.arena, &mem_extra_flags, "l");
}
if (header->flags & COFF_SectionFlag_MemDiscardable) {
str8_list_pushf(scratch.arena, &mem_extra_flags, "d");
}
if (header->flags & COFF_SectionFlag_MemNotCached) {
str8_list_pushf(scratch.arena, &mem_extra_flags, "c");
}
if (header->flags & COFF_SectionFlag_MemNotPaged) {
str8_list_pushf(scratch.arena, &mem_extra_flags, "p");
}
String8List lnk_flags = {0};
if (header->flags & COFF_SectionFlag_LnkRemove) {
str8_list_pushf(scratch.arena, &lnk_flags, "r");
}
if (header->flags & COFF_SectionFlag_LnkCOMDAT) {
str8_list_pushf(scratch.arena, &lnk_flags, "c");
}
if (header->flags & COFF_SectionFlag_LnkOther) {
str8_list_pushf(scratch.arena, &lnk_flags, "o");
}
if (header->flags & COFF_SectionFlag_LnkInfo) {
str8_list_pushf(scratch.arena, &lnk_flags, "i");
}
if (header->flags & COFF_SectionFlag_LnkNRelocOvfl) {
str8_list_pushf(scratch.arena, &lnk_flags, "f");
}
String8List other_flags = {0};
if (header->flags & COFF_SectionFlag_TypeNoPad) {
str8_list_pushf(scratch.arena, &other_flags, "n");
}
if (header->flags & COFF_SectionFlag_GpRel) {
str8_list_pushf(scratch.arena, &other_flags, "g");
}
String8 mem = str8_list_join(scratch.arena, &mem_flags, 0);
String8 cnt = str8_list_join(scratch.arena, &cnt_flags, 0);
String8 lnk = str8_list_join(scratch.arena, &lnk_flags, 0);
String8 ext = str8_list_join(scratch.arena, &mem_extra_flags, 0);
String8 oth = str8_list_join(scratch.arena, &other_flags, 0);
String8List f = {0};
str8_list_push(scratch.arena, &f, mem);
str8_list_push(scratch.arena, &f, cnt);
str8_list_push(scratch.arena, &f, ext);
str8_list_push(scratch.arena, &f, lnk);
str8_list_push(scratch.arena, &f, oth);
flags = str8_list_join(scratch.arena, &f, &(StringJoin){ .sep = str8_lit("-") });
if (!flags.size) {
flags = str8_lit("none");
}
}
String8List l = {0};
str8_list_pushf(scratch.arena, &l, "%-4x", i+1 );
str8_list_pushf(scratch.arena, &l, "%-8S", name );
str8_list_pushf(scratch.arena, &l, "%08x", header->vsize );
str8_list_pushf(scratch.arena, &l, "%08x", header->voff );
str8_list_pushf(scratch.arena, &l, "%08x", header->fsize );
str8_list_pushf(scratch.arena, &l, "%08x", header->foff );
str8_list_pushf(scratch.arena, &l, "%08x", header->relocs_foff);
str8_list_pushf(scratch.arena, &l, "%08x", header->lines_foff );
str8_list_pushf(scratch.arena, &l, "%08x", header->reloc_count);
str8_list_pushf(scratch.arena, &l, "%08x", header->line_count );
str8_list_pushf(scratch.arena, &l, "%-5S", align );
str8_list_pushf(scratch.arena, &l, "%-10S", flags );
if (symlinks[i].size > 0) {
str8_list_pushf(scratch.arena, &l, "%S", symlinks[i]);
} else {
str8_list_pushf(scratch.arena, &l, "[no symlink]");
}
String8 line = str8_list_join(scratch.arena, &l, &(StringJoin){ .sep = str8_lit(" "), });
rd_printf("%S", line);
if (full_name.size != name.size) {
rd_indent();
rd_printf("Full Name: %S", full_name);
rd_unindent();
}
}
rd_newline();
rd_printf("Flags:");
rd_indent();
rd_printf("r = MemRead w = MemWrite x = MemExecute");
rd_printf("c = CntCode d = InitializedData u = UninitializedData");
rd_printf("s = MemShared h = Mem16bit l = MemLocked d = MemDiscardable c = MemNotCached p = MemNotPaged");
rd_printf("r = LnkRemove c = LnkComdat o = LnkOther i = LnkInfo f = LnkNRelocOvfl");
rd_printf("g = GpRel n = TypeNoPad");
rd_unindent();
rd_unindent();
rd_newline();
}
scratch_end(scratch);
}
internal void
coff_disasm_sections(Arena *arena,
String8List *out,
String8 indent,
String8 raw_data,
COFF_MachineType machine,
U64 image_base,
B32 is_obj,
RD_MarkerArray *section_markers,
U64 section_count,
COFF_SectionHeader *sections)
{
if (section_count) {
for (U64 sect_idx = 0; sect_idx < section_count; ++sect_idx) {
COFF_SectionHeader *sect = sections+sect_idx;
if (sect->flags & COFF_SectionFlag_CntCode) {
U64 sect_off = is_obj ? sect->foff : sect->voff;
U64 sect_size = is_obj ? sect->fsize : sect->vsize;
String8 raw_code = str8_substr(raw_data, rng_1u64(sect->foff, sect->foff+sect_size));
U64 sect_number = sect_idx+1;
RD_MarkerArray markers = section_markers[sect_number];
rd_printf("# Disassembly [Section No. %#llx]", sect_number);
rd_indent();
rd_print_disasm(arena, out, indent, arch_from_coff_machine(machine), image_base, sect_off, markers.count, markers.v, raw_code);
rd_unindent();
}
}
}
}
internal void
coff_raw_data_sections(Arena *arena,
String8List *out,
String8 indent,
String8 raw_data,
B32 is_obj,
RD_MarkerArray *section_markers,
U64 section_count,
COFF_SectionHeader *section_table)
{
if (section_count) {
for (U64 sect_idx = 0; sect_idx < section_count; ++sect_idx) {
COFF_SectionHeader *sect = section_table+sect_idx;
if (sect->fsize > 0) {
U64 sect_size = is_obj ? sect->fsize : sect->vsize;
String8 raw_sect = str8_substr(raw_data, rng_1u64(sect->foff, sect->foff+sect_size));
RD_MarkerArray markers = section_markers[sect_idx];
rd_printf("# Raw Data [Section No. %#llx]", (sect_idx+1));
rd_indent();
rd_print_raw_data(arena, out, indent, 32, markers.count, markers.v, raw_sect);
rd_unindent();
rd_newline();
}
}
}
}
internal void
coff_print_relocs(Arena *arena,
String8List *out,
String8 indent,
String8 raw_data,
String8 string_table,
COFF_MachineType machine,
U64 sect_count,
COFF_SectionHeader *sect_headers,
COFF_Symbol32Array symbols)
{
Temp scratch = scratch_begin(&arena, 1);
B32 print_header = 1;
for (U64 sect_idx = 0; sect_idx < sect_count; ++sect_idx) {
COFF_SectionHeader *sect_header = sect_headers+sect_idx;
COFF_RelocInfo reloc_info = coff_reloc_info_from_section_header(raw_data, sect_header);
if (reloc_info.count) {
if (print_header) {
print_header = 0;
rd_printf("# Relocations");
rd_indent();
}
rd_printf("## Section %llx", sect_idx);
rd_indent();
rd_printf("%-4s %-8s %-16s %-16s %-8s %-7s", "No.", "Offset", "Type", "ApplyTo", "SymIdx", "SymName");
for (U64 reloc_idx = 0; reloc_idx < reloc_info.count; ++reloc_idx) {
COFF_Reloc *reloc = (COFF_Reloc*)(raw_data.str + reloc_info.array_off) + reloc_idx;
String8 type = coff_string_from_reloc(machine, reloc->type);
U64 apply_size = coff_apply_size_from_reloc(machine, reloc->type);
U64 apply_foff = sect_header->foff + reloc->apply_off;
if (apply_foff + apply_size > raw_data.size) {
rd_errorf("out of bounds apply file offset %#llx in relocation %#llx", apply_foff, reloc_idx);
break;
}
U64 raw_apply;
AssertAlways(apply_size <= sizeof(raw_apply));
MemoryCopy(&raw_apply, raw_data.str + apply_foff, apply_size);
S64 apply = extend_sign64(raw_apply, apply_size);
if (reloc->isymbol > symbols.count) {
rd_errorf("out of bounds symbol index %u in relocation %#llx", reloc->isymbol, reloc_idx);
break;
}
COFF_Symbol32 *symbol = symbols.v+reloc->isymbol;
String8 symbol_name = coff_read_symbol_name(string_table, &symbol->name);
String8List line = {0};
str8_list_pushf(scratch.arena, &line, "%-4x", reloc_idx );
str8_list_pushf(scratch.arena, &line, "%08x", reloc->apply_off);
str8_list_pushf(scratch.arena, &line, "%-16S", type );
str8_list_pushf(scratch.arena, &line, "%016x", apply );
str8_list_pushf(scratch.arena, &line, "%S", symbol_name );
String8 l = str8_list_join(scratch.arena, &line, &(StringJoin){.sep=str8_lit(" ")});
rd_printf("%S", l);
}
rd_unindent();
}
}
if (!print_header) {
rd_unindent();
}
rd_newline();
scratch_end(scratch);
}
internal void
coff_print_symbol_table(Arena *arena,
String8List *out,
String8 indent,
String8 raw_data,
B32 is_big_obj,
String8 string_table,
COFF_Symbol32Array symbols)
{
Temp scratch = scratch_begin(&arena, 1);
if (symbols.count) {
rd_printf("# Symbol Table");
rd_indent();
rd_printf("%-4s %-8s %-10s %-4s %-4s %-4s %-16s %-20s",
"No.", "Value", "SectNum", "Aux", "Msb", "Lsb", "Storage", "Name");
for (U64 i = 0; i < symbols.count; ++i) {
COFF_Symbol32 *symbol = &symbols.v[i];
String8 name = coff_read_symbol_name(string_table, &symbol->name);
String8 msb = coff_string_from_sym_dtype(symbol->type.u.msb);
String8 lsb = coff_string_from_sym_type(symbol->type.u.lsb);
String8 storage_class = coff_string_from_sym_storage_class(symbol->storage_class);
String8 section_number;
switch (symbol->section_number) {
case COFF_Symbol_UndefinedSection: section_number = str8_lit("Undef"); break;
case COFF_Symbol_AbsSection32: section_number = str8_lit("Abs"); break;
case COFF_Symbol_DebugSection32: section_number = str8_lit("Debug"); break;
default: section_number = push_str8f(scratch.arena, "%010x", symbol->section_number); break;
}
String8List line = {0};
str8_list_pushf(scratch.arena, &line, "%-4x", i );
str8_list_pushf(scratch.arena, &line, "%08x", symbol->value );
str8_list_pushf(scratch.arena, &line, "%-10S", section_number );
str8_list_pushf(scratch.arena, &line, "%-4u", symbol->aux_symbol_count);
str8_list_pushf(scratch.arena, &line, "%-4S", msb );
str8_list_pushf(scratch.arena, &line, "%-4S", lsb );
str8_list_pushf(scratch.arena, &line, "%-16S", storage_class );
str8_list_pushf(scratch.arena, &line, "%S", name );
String8 l = str8_list_join(scratch.arena, &line, &(StringJoin){.sep = str8_lit(" ")});
rd_printf("%S", l);
rd_indent();
for (U64 k=i+1, c = i+symbol->aux_symbol_count; k <= c; ++k) {
void *raw_aux = &symbols.v[k];
switch (symbol->storage_class) {
case COFF_SymStorageClass_External: {
COFF_SymbolFuncDef *func_def = (COFF_SymbolFuncDef*)&symbols.v[k];
rd_printf("Tag Index %#x, Total Size %#x, Line Numbers %#x, Next Function %#x",
func_def->tag_index, func_def->total_size, func_def->ptr_to_ln, func_def->ptr_to_next_func);
} break;
case COFF_SymStorageClass_Function: {
COFF_SymbolFunc *func = raw_aux;
rd_printf("Ordinal Line Number %#x, Next Function %#x", func->ln, func->ptr_to_next_func);
} break;
case COFF_SymStorageClass_WeakExternal: {
COFF_SymbolWeakExt *weak = raw_aux;
String8 type = coff_string_from_weak_ext_type(weak->characteristics);
rd_printf("Tag Index %#x, Characteristics %S", weak->tag_index, type);
} break;
case COFF_SymStorageClass_File: {
COFF_SymbolFile *file = raw_aux;
String8 name = str8_cstring_capped(file->name, file->name+sizeof(file->name));
rd_printf("Name %S", name);
} break;
case COFF_SymStorageClass_Static: {
COFF_SymbolSecDef *sd = raw_aux;
String8 selection = coff_string_from_comdat_select_type(sd->selection);
U32 number = sd->number_lo;
if (is_big_obj) {
number |= (U32)sd->number_hi << 16;
}
if (number) {
rd_printf("Length %x, Reloc Count %u, Line Count %u, Checksum %x, Section %x, Selection %S",
sd->length, sd->number_of_relocations, sd->number_of_ln, sd->check_sum, number, selection);
} else {
rd_printf("Length %x, Reloc Count %u, Line Count %u, Checksum %x",
sd->length, sd->number_of_relocations, sd->number_of_ln, sd->check_sum);
}
} break;
default: {
rd_printf("???");
} break;
}
}
i += symbol->aux_symbol_count;
rd_unindent();
}
rd_unindent();
rd_newline();
}
scratch_end(scratch);
}
internal void
coff_print_big_obj_header(Arena *arena, String8List *out, String8 indent, COFF_BigObjHeader *header)
{
Temp scratch = scratch_begin(&arena, 1);
String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header->time_stamp);
String8 machine = coff_string_from_machine_type(header->machine);
rd_printf("# Big Obj");
rd_indent();
rd_printf("Time Stamp : %#x (%S)", header->time_stamp, time_stamp);
rd_printf("Machine : %#x (%S)", header->machine, machine );
rd_printf("Section Count: %u", header->section_count );
rd_printf("Symbol Table : %#x", header->symbol_table_foff);
rd_printf("Symbol Count : %u", header->symbol_count );
rd_unindent();
scratch_end(scratch);
}
internal void
coff_print_file_header(Arena *arena, String8List *out, String8 indent, COFF_FileHeader *header)
{
Temp scratch = scratch_begin(&arena, 1);
String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header->time_stamp);
String8 machine = coff_string_from_machine_type(header->machine);
String8 flags = coff_string_from_flags(scratch.arena, header->flags);
rd_printf("# COFF File Header");
rd_indent();
rd_printf("Time Stamp : %#x (%S)", header->time_stamp, time_stamp );
rd_printf("Machine : %#x %S", header->machine, machine );
rd_printf("Section Count : %u", header->section_count );
rd_printf("Symbol Table : %#x", header->symbol_table_foff );
rd_printf("Symbol Count : %u", header->symbol_count );
rd_printf("Optional Header Size: %#x (%m)", header->optional_header_size, header->optional_header_size);
rd_printf("Flags : %#x (%S)", header->flags, flags );
rd_unindent();
scratch_end(scratch);
}
internal void
coff_print_import(Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveImportHeader *header)
{
Temp scratch = scratch_begin(&arena, 1);
String8 machine = coff_string_from_machine_type(header->machine);
String8 time_stamp = coff_string_from_time_stamp(scratch.arena, header->time_stamp);
rd_printf("# Import");
rd_indent();
rd_printf("Version : %u", header->version );
rd_printf("Machine : %S", machine );
rd_printf("Time Stamp: %#x (%S)", header->time_stamp, time_stamp );
rd_printf("Data Size : %#x (%m)", header->data_size, header->data_size);
rd_printf("Hint : %u", header->hint_or_ordinal);
rd_printf("Type : %u", header->type );
rd_printf("Import By : %u", header->import_by );
rd_printf("Function : %S", header->func_name );
rd_printf("DLL : %S", header->dll_name );
rd_unindent();
scratch_end(scratch);
}
internal void
coff_print_big_obj(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts)
{
Temp scratch = scratch_begin(&arena, 1);
COFF_FileHeaderInfo header_info = coff_file_header_info_from_data(raw_data);
String8 raw_header = str8_substr(raw_data, header_info.header_range);
String8 raw_section_table = str8_substr(raw_data, header_info.section_table_range);
String8 raw_string_table = str8_substr(raw_data, header_info.string_table_range);
COFF_BigObjHeader *big_obj = (COFF_BigObjHeader *)raw_header.str;
COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_section_table.str;
COFF_Symbol32Array symbol_table = coff_symbol_array_from_data_32(scratch.arena, raw_data, header_info.symbol_table_range.min, big_obj->symbol_count);
if (opts & RD_Option_Headers) {
coff_print_big_obj_header(arena, out, indent, big_obj);
rd_newline();
}
if (opts & RD_Option_Sections) {
Rng1U64 sect_headers_range = rng_1u64(sizeof(*big_obj), sizeof(*big_obj) + sizeof(COFF_SectionHeader)*big_obj->section_count);
Rng1U64 symbols_range = rng_1u64(big_obj->symbol_table_foff, big_obj->symbol_table_foff + sizeof(COFF_Symbol32)*big_obj->symbol_count);
if (sect_headers_range.max > raw_data.size) {
rd_errorf("not enough bytes to read big obj section headers");
goto exit;
}
if (big_obj->symbol_count) {
if (symbols_range.max > raw_data.size) {
rd_errorf("not enough bytes to read big obj symbol table");
goto exit;
}
if (contains_1u64(symbols_range, sect_headers_range.min) ||
contains_1u64(symbols_range, sect_headers_range.max)) {
rd_errorf("section headers and symbol table ranges overlap");
goto exit;
}
}
coff_print_section_table(arena, out, indent, raw_string_table, symbol_table, big_obj->section_count, section_table);
rd_newline();
}
if (opts & RD_Option_Relocs) {
coff_print_relocs(arena, out, indent, raw_data, raw_string_table, big_obj->machine, big_obj->section_count, section_table, symbol_table);
rd_newline();
}
if (opts & RD_Option_Symbols) {
coff_print_symbol_table(arena, out, indent, raw_data, 1, raw_string_table, symbol_table);
rd_newline();
}
exit:;
scratch_end(scratch);
}
internal void
coff_print_obj(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts)
{
Temp scratch = scratch_begin(&arena, 1);
COFF_FileHeaderInfo header_info = coff_file_header_info_from_data(raw_data);
String8 raw_header = str8_substr(raw_data, header_info.header_range);
String8 raw_section_table = str8_substr(raw_data, header_info.section_table_range);
String8 raw_string_table = str8_substr(raw_data, header_info.string_table_range);
COFF_FileHeader *header = (COFF_FileHeader *)raw_header.str;
COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_section_table.str;
COFF_Symbol32Array symbol_table = coff_symbol_array_from_data_16(scratch.arena, raw_data, header_info.symbol_table_range.min, header->symbol_count);
Arch arch = arch_from_coff_machine(header->machine);
if (opts & RD_Option_Headers) {
coff_print_file_header(arena, out, indent, header);
rd_newline();
}
if (opts & RD_Option_Sections) {
Rng1U64 sect_headers_range = rng_1u64(sizeof(*header), sizeof(*header) + sizeof(COFF_SectionHeader)*header->section_count);
Rng1U64 symbols_range = rng_1u64(header->symbol_table_foff, header->symbol_table_foff + sizeof(COFF_Symbol16)*header->symbol_count);
if (sect_headers_range.max > raw_data.size) {
rd_errorf("not enough bytes to read obj section headers");
goto exit;
}
if (header->symbol_count) {
if (symbols_range.max > raw_data.size) {
rd_errorf("not enough bytes to read obj symbol table");
goto exit;
}
if (contains_1u64(symbols_range, sect_headers_range.min) ||
contains_1u64(symbols_range, sect_headers_range.max)) {
rd_errorf("section headers and symbol table ranges overlap");
goto exit;
}
}
coff_print_section_table(arena, out, indent, raw_string_table, symbol_table, header->section_count, section_table);
rd_newline();
}
if (opts & RD_Option_Relocs) {
coff_print_relocs(arena, out, indent, raw_data, raw_string_table, header->machine, header->section_count, section_table, symbol_table);
rd_newline();
}
if (opts & RD_Option_Symbols) {
coff_print_symbol_table(arena, out, indent, raw_data, 0, raw_string_table, symbol_table);
rd_newline();
}
RD_MarkerArray *section_markers = 0;
if (opts & (RD_Option_Disasm|RD_Option_Rawdata)) {
section_markers = rd_section_markers_from_coff_symbol_table(scratch.arena, raw_string_table, header->section_count, symbol_table);
}
if (opts & RD_Option_Rawdata) {
coff_raw_data_sections(arena, out, indent, raw_data, 1, section_markers, header->section_count, section_table);
}
if (opts & RD_Option_Disasm) {
coff_disasm_sections(arena, out, indent, raw_data, header->machine, 0, 1, section_markers, header->section_count, section_table);
rd_newline();
}
if (opts & RD_Option_Codeview) {
cv_format_debug_sections(arena, out, indent, raw_data, raw_string_table, header->section_count, section_table);
}
if (opts & RD_Option_Dwarf) {
DW_Input dwarf_input = dw_input_from_coff_section_table(scratch.arena, raw_data, raw_string_table, header->section_count, section_table);
dw_format(arena, out, indent, opts, &dwarf_input, arch, ExecutableImageKind_CoffPe);
}
exit:;
scratch_end(scratch);
}
internal void
coff_print_archive(Arena *arena, String8List *out, String8 indent, String8 raw_archive, RD_Option opts)
{
Temp scratch = scratch_begin(&arena, 1);
COFF_ArchiveParse archive_parse = coff_archive_parse_from_data(raw_archive);
if (archive_parse.error.size) {
rd_errorf("%S", archive_parse.error);
return;
}
COFF_ArchiveFirstMember first_member = archive_parse.first_member;
{
rd_printf("# First Header");
rd_indent();
rd_printf("Symbol Count : %u", first_member.symbol_count);
rd_printf("String Table Size: %#llx (%M)", first_member.string_table.size, first_member.string_table.size);
rd_printf("Members:");
rd_indent();
String8List string_table = str8_split_by_string_chars(scratch.arena, first_member.string_table, str8_lit("\0"), 0);
if (string_table.node_count == first_member.member_offset_count) {
String8Node *string_n = string_table.first;
for (U64 i = 0; i < string_table.node_count; ++i, string_n = string_n->next) {
U32 offset = from_be_u32(first_member.member_offsets[i]);
rd_printf("[%4u] %#08x %S", i, offset, string_n->string);
}
} else {
rd_errorf("Member offset count (%llu) doesn't match string table count (%llu)", first_member.member_offset_count);
}
rd_unindent();
rd_unindent();
rd_newline();
}
if (archive_parse.has_second_header) {
COFF_ArchiveSecondMember second_member = archive_parse.second_member;
rd_printf("# Second Header");
rd_indent();
rd_printf("Member Count : %u", second_member.member_count);
rd_printf("Symbol Count : %u", second_member.symbol_count);
rd_printf("String Table Size: %#llx (%M)", second_member.string_table.size, second_member.string_table.size);
String8List string_table = str8_split_by_string_chars(scratch.arena, second_member.string_table, str8_lit("\0"), 0);
rd_printf("Members:");
rd_indent();
if (second_member.symbol_index_count == second_member.symbol_count) {
String8Node *string_n = string_table.first;
for (U64 i = 0; i < second_member.symbol_count; ++i, string_n = string_n->next) {
U16 symbol_number = second_member.symbol_indices[i];
if (symbol_number > 0 && symbol_number <= second_member.member_offset_count) {
U16 symbol_idx = symbol_number - 1;
U32 member_offset = second_member.member_offsets[i];
rd_printf("[%4u] %#08x %S", i, member_offset, string_n->string);
} else {
rd_errorf("[%4u] Out of bounds symbol number %u", i, symbol_number);
break;
}
}
} else {
rd_errorf("Symbol index count %u doesn't match symbol count %u",
second_member.symbol_index_count, second_member.symbol_count);
}
rd_unindent();
rd_unindent();
rd_newline();
}
if (archive_parse.has_long_names && opts & RD_Option_LongNames) {
rd_printf("# Long Names");
rd_indent();
String8List long_names = str8_split_by_string_chars(scratch.arena, archive_parse.long_names, str8_lit("\0"), 0);
U64 name_idx = 0;
for (String8Node *name_n = long_names.first; name_n != 0; name_n = name_n->next, ++name_idx) {
U64 offset = (U64)(name_n->string.str - archive_parse.long_names.str);
rd_printf("[%-4u] %#08x %S", name_idx, offset, name_n->string);
}
rd_unindent();
rd_newline();
}
U64 member_offset_count = 0;
U32 *member_offsets = 0;
if (archive_parse.has_second_header) {
member_offset_count = archive_parse.second_member.member_offset_count;
member_offsets = archive_parse.second_member.member_offsets;
} else {
HashTable *ht = hash_table_init(scratch.arena, 0x1000);
for (U64 i = 0; i < archive_parse.first_member.member_offset_count; ++i) {
U32 member_offset = from_be_u32(archive_parse.first_member.member_offsets[i]);
if (!hash_table_search_u32(ht, member_offset)) {
hash_table_push_u32_raw(scratch.arena, ht, member_offset, 0);
}
}
member_offset_count = ht->count;
member_offsets = keys_from_hash_table_u32(scratch.arena, ht);
radsort(member_offsets, member_offset_count, u32_is_before);
}
rd_printf("# Members");
rd_indent();
for (U64 i = 0; i < member_offset_count; ++i) {
U64 next_member_offset = i+1 < member_offset_count ? member_offsets[i+1] : raw_archive.size;
U64 member_offset = member_offsets[i];
String8 raw_member = str8_substr(raw_archive, rng_1u64(member_offset, next_member_offset));
COFF_ArchiveMember member = coff_archive_member_from_data(raw_member);
COFF_DataType member_type = coff_data_type_from_data(member.data);
rd_printf("Member @ %#llx", member_offset);
rd_indent();
if (opts & RD_Option_Headers) {
coff_print_archive_member_header(arena, out, indent, member.header, archive_parse.long_names);
rd_newline();
}
switch (member_type) {
case COFF_DataType_Obj: {
coff_print_obj(arena, out, indent, member.data, opts);
} break;
case COFF_DataType_BigObj: {
coff_print_big_obj(arena, out, indent, member.data, opts);
} break;
case COFF_DataType_Import: {
if (opts & RD_Option_Headers) {
COFF_ParsedArchiveImportHeader header = {0};
U64 parse_size = coff_parse_import(member.data, 0, &header);
if (parse_size) {
coff_print_import(arena, out, indent, &header);
} else {
rd_errorf("not enough bytes to parse import header");
}
}
} break;
case COFF_DataType_Null: {
rd_errorf("unknown member format", member_offset);
} break;
}
rd_unindent();
rd_newline();
}
rd_unindent();
scratch_end(scratch);
}
#endif
+22
View File
@@ -0,0 +1,22 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef COFF_DUMP_H
#define COFF_DUMP_H
#if 0
internal void coff_print_archive_member_header(Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveMemberHeader header, String8 long_names);
internal void coff_print_section_table (Arena *arena, String8List *out, String8 indent, String8 string_table, COFF_Symbol32Array symbols, U64 sect_count, COFF_SectionHeader *sect_headers);
internal void coff_disasm_sections (Arena *arena, String8List *out, String8 indent, String8 raw_data, COFF_MachineType machine, U64 image_base, B32 is_obj, RD_MarkerArray *section_markers, U64 section_count, COFF_SectionHeader *sections);
internal void coff_raw_data_sections (Arena *arena, String8List *out, String8 indent, String8 raw_data, B32 is_obj, RD_MarkerArray *section_markers, U64 section_count, COFF_SectionHeader *sections);
internal void coff_print_relocs (Arena *arena, String8List *out, String8 indent, String8 raw_data, String8 string_table, COFF_MachineType machine, U64 sect_count, COFF_SectionHeader *sect_headers, COFF_Symbol32Array symbols);
internal void coff_print_symbol_table (Arena *arena, String8List *out, String8 indent, String8 raw_data, B32 is_big_obj, String8 string_table, COFF_Symbol32Array symbols);
internal void coff_print_big_obj_header (Arena *arena, String8List *out, String8 indent, COFF_BigObjHeader *header);
internal void coff_print_file_header (Arena *arena, String8List *out, String8 indent, COFF_FileHeader *header);
internal void coff_print_import (Arena *arena, String8List *out, String8 indent, COFF_ParsedArchiveImportHeader *header);
internal void coff_print_big_obj (Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts);
internal void coff_print_obj (Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts);
internal void coff_print_archive (Arena *arena, String8List *out, String8 indent, String8 raw_archive, RD_Option opts);
#endif
#endif // COFF_DUMP_H
-479
View File
@@ -1,480 +1 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal String8
coff_string_from_time_stamp(Arena *arena, COFF_TimeStamp time_stamp)
{
String8 result;
if (time_stamp == 0) {
result = str8_lit("0");
} else if (time_stamp >= max_U32) {
result = str8_lit("-1");
} else {
DateTime dt = date_time_from_unix_time(time_stamp);
result = push_date_time_string(arena, &dt);
}
return result;
}
read_only struct
{
String8 string;
COFF_MachineType machine;
} g_coff_machine_map[] = {
{ 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 {
char * name;
COFF_ImportType type;
} g_coff_import_header_type_map[] = {
{ "Code", COFF_ImportHeader_Code },
{ "Data", COFF_ImportHeader_Data },
{ "Const", COFF_ImportHeader_Const },
};
internal String8
coff_string_from_comdat_select_type(COFF_ComdatSelectType type)
{
String8 result = str8_zero();
switch (type) {
case COFF_ComdatSelect_Null: result = str8_lit("Null"); break;
case COFF_ComdatSelect_NoDuplicates: result = str8_lit("NoDuplicates"); break;
case COFF_ComdatSelect_Any: result = str8_lit("Any"); break;
case COFF_ComdatSelect_SameSize: result = str8_lit("SameSize"); break;
case COFF_ComdatSelect_ExactMatch: result = str8_lit("ExactMatch"); break;
case COFF_ComdatSelect_Associative: result = str8_lit("Associative"); break;
case COFF_ComdatSelect_Largest: result = str8_lit("Largest"); break;
}
return result;
}
internal String8
coff_string_from_machine_type(COFF_MachineType machine)
{
for (U64 i = 0; i < ArrayCount(g_coff_machine_map); ++i) {
if (g_coff_machine_map[i].machine == machine) {
return g_coff_machine_map[i].string;
}
}
return str8_zero();
}
internal String8
coff_string_from_flags(Arena *arena, COFF_FileHeaderFlags flags)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (flags & COFF_FileHeaderFlag_RelocStripped) {
str8_list_pushf(scratch.arena, &list, "Relocs Stripped");
}
if (flags & COFF_FileHeaderFlag_ExecutableImage) {
str8_list_pushf(scratch.arena, &list, "Executable");
}
if (flags & COFF_FileHeaderFlag_LineNumbersStripped) {
str8_list_pushf(scratch.arena, &list, "Line Numbers Stripped");
}
if (flags & COFF_FileHeaderFlag_SymbolsStripped) {
str8_list_pushf(scratch.arena, &list, "Symbols Stripped");
}
if (flags & COFF_FileHeaderFlag_LargeAddressAware) {
str8_list_pushf(scratch.arena, &list, "Large Address Aware");
}
if (flags & COFF_FileHeaderFlag_32BitMachine) {
str8_list_pushf(scratch.arena, &list, "32-Bit Machine");
}
if (flags & COFF_FileHeaderFlag_DebugStripped) {
str8_list_pushf(scratch.arena, &list, "Debug Stripped");
}
if (flags & COFF_FileHeaderFlag_RemovableRunFromSwap) {
str8_list_pushf(scratch.arena, &list, "Removeable Run From Swap");
}
if (flags & COFF_FileHeaderFlag_NetRunFromSwap) {
str8_list_pushf(scratch.arena, &list, "Net Run From Swap");
}
if (flags & COFF_FileHeaderFlag_System) {
str8_list_pushf(scratch.arena, &list, "System");
}
if (flags & COFF_FileHeaderFlag_Dll) {
str8_list_pushf(scratch.arena, &list, "DLL");
}
if (flags & COFF_FileHeaderFlag_UpSystemOnly) {
str8_list_pushf(scratch.arena, &list, "Up System Only");
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
coff_string_from_section_flags(Arena *arena, COFF_SectionFlags flags)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (flags & COFF_SectionFlag_TypeNoPad) {
str8_list_pushf(scratch.arena, &list, "TypeNoPad");
}
if (flags & COFF_SectionFlag_CntCode) {
str8_list_pushf(scratch.arena, &list, "CntCode");
}
if (flags & COFF_SectionFlag_CntInitializedData) {
str8_list_pushf(scratch.arena, &list, "CntInitializedData");
}
if (flags & COFF_SectionFlag_CntUninitializedData) {
str8_list_pushf(scratch.arena, &list, "CntUninitializedData");
}
if (flags & COFF_SectionFlag_LnkOther) {
str8_list_pushf(scratch.arena, &list, "LnkOther");
}
if (flags & COFF_SectionFlag_LnkInfo) {
str8_list_pushf(scratch.arena, &list, "LnkInfo");
}
if (flags & COFF_SectionFlag_LnkCOMDAT) {
str8_list_pushf(scratch.arena, &list, "LnkCOMDAT");
}
if (flags & COFF_SectionFlag_GpRel) {
str8_list_pushf(scratch.arena, &list, "GpRel");
}
if (flags & COFF_SectionFlag_Mem16Bit) {
str8_list_pushf(scratch.arena, &list, "Mem16Bit");
}
if (flags & COFF_SectionFlag_MemLocked) {
str8_list_pushf(scratch.arena, &list, "MemLocked");
}
if (flags & COFF_SectionFlag_MemPreload) {
str8_list_pushf(scratch.arena, &list, "MemPreload");
}
if (flags & COFF_SectionFlag_LnkNRelocOvfl) {
str8_list_pushf(scratch.arena, &list, "LnkNRelocOvfl");
}
if (flags & COFF_SectionFlag_MemDiscardable) {
str8_list_pushf(scratch.arena, &list, "MemDiscardable");
}
if (flags & COFF_SectionFlag_MemNotCached) {
str8_list_pushf(scratch.arena, &list, "MemNotCached");
}
if (flags & COFF_SectionFlag_MemNotPaged) {
str8_list_pushf(scratch.arena, &list, "MemNotPaged");
}
if (flags & COFF_SectionFlag_MemShared) {
str8_list_pushf(scratch.arena, &list, "MemShared");
}
if (flags & COFF_SectionFlag_MemExecute) {
str8_list_pushf(scratch.arena, &list, "MemExecute");
}
if (flags & COFF_SectionFlag_MemRead) {
str8_list_pushf(scratch.arena, &list, "MemRead");
}
if (flags & COFF_SectionFlag_MemWrite) {
str8_list_pushf(scratch.arena, &list, "MemWrite");
}
U64 align = coff_align_size_from_section_flags(flags);
if (align) {
str8_list_pushf(scratch.arena, &list, "Align=%u", align);
}
if (!list.node_count) {
str8_list_pushf(scratch.arena, &list, "None");
}
StringJoin join = {0};
join.sep = str8_lit(", ");
String8 result = str8_list_join(arena, &list, &join);
scratch_end(scratch);
return result;
}
internal String8
coff_string_from_resource_memory_flags(Arena *arena, COFF_ResourceMemoryFlags flags)
{
Temp scratch = scratch_begin(&arena, 1);
String8List list = {0};
if (flags & COFF_ResourceMemoryFlag_Moveable) {
flags &= COFF_ResourceMemoryFlag_Moveable;
str8_list_pushf(scratch.arena, &list, "Moveable");
}
if (flags & COFF_ResourceMemoryFlag_Pure) {
flags &= COFF_ResourceMemoryFlag_Pure;
str8_list_pushf(scratch.arena, &list, "Pure");
}
if (flags & COFF_ResourceMemoryFlag_Discardable) {
flags &= COFF_ResourceMemoryFlag_Discardable;
str8_list_pushf(scratch.arena, &list, "Discardable");
}
if (flags != 0) {
str8_list_pushf(scratch.arena, &list, "%#x", flags);
}
String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")});
scratch_end(scratch);
return result;
}
internal String8
coff_string_from_import_header_type(COFF_ImportType type)
{
for (U64 i = 0; i < ArrayCount(g_coff_import_header_type_map); ++i) {
if (g_coff_import_header_type_map[i].type == type) {
return str8_cstring(g_coff_import_header_type_map[i].name);
}
}
return str8(0,0);
}
internal String8
coff_string_from_sym_dtype(COFF_SymDType x)
{
switch (x) {
case COFF_SymDType_Null: return str8_lit("Null");
case COFF_SymDType_Ptr : return str8_lit("Ptr");
case COFF_SymDType_Func: return str8_lit("Func");
case COFF_SymDType_Array: return str8_lit("Array");
}
return str8_zero();
}
internal String8
coff_string_from_sym_type(COFF_SymType x)
{
switch (x) {
case COFF_SymType_Null: return str8_lit("Null");
case COFF_SymType_Void: return str8_lit("Void");
case COFF_SymType_Char: return str8_lit("Char");
case COFF_SymType_Short: return str8_lit("Short");
case COFF_SymType_Int: return str8_lit("Int");
case COFF_SymType_Long: return str8_lit("Long");
case COFF_SymType_Float: return str8_lit("Float");
case COFF_SymType_Double: return str8_lit("Double");
case COFF_SymType_Struct: return str8_lit("Struct");
case COFF_SymType_Union: return str8_lit("Union");
case COFF_SymType_Enum: return str8_lit("Enum");
case COFF_SymType_MemberOfEnumeration: return str8_lit("MOE");
case COFF_SymType_Byte: return str8_lit("Byte");
case COFF_SymType_Word: return str8_lit("Word");
case COFF_SymType_UInt: return str8_lit("UInt");
case COFF_SymType_DWord: return str8_lit("DWord");
}
return str8_zero();
}
internal String8
coff_string_from_sym_storage_class(COFF_SymStorageClass x)
{
switch (x) {
case COFF_SymStorageClass_Null: break;
case COFF_SymStorageClass_EndOfFunction: return str8_lit("EndOfFunction");
case COFF_SymStorageClass_Automatic: return str8_lit("Automatic");
case COFF_SymStorageClass_External: return str8_lit("External");
case COFF_SymStorageClass_Static: return str8_lit("Static");
case COFF_SymStorageClass_Register: return str8_lit("Register");
case COFF_SymStorageClass_ExternalDef: return str8_lit("Def");
case COFF_SymStorageClass_Label: return str8_lit("Label");
case COFF_SymStorageClass_UndefinedLabel: return str8_lit("UndefinedLabel");
case COFF_SymStorageClass_MemberOfStruct: return str8_lit("Struct");
case COFF_SymStorageClass_Argument: return str8_lit("Argument");
case COFF_SymStorageClass_StructTag: return str8_lit("Tag");
case COFF_SymStorageClass_MemberOfUnion: return str8_lit("Union");
case COFF_SymStorageClass_UnionTag: return str8_lit("Tag");
case COFF_SymStorageClass_TypeDefinition: return str8_lit("Definition");
case COFF_SymStorageClass_UndefinedStatic: return str8_lit("Static");
case COFF_SymStorageClass_EnumTag: return str8_lit("Tag");
case COFF_SymStorageClass_MemberOfEnum: return str8_lit("Enum");
case COFF_SymStorageClass_RegisterParam: return str8_lit("Param");
case COFF_SymStorageClass_BitField: return str8_lit("Field");
case COFF_SymStorageClass_Block: return str8_lit("Block");
case COFF_SymStorageClass_Function: return str8_lit("Function");
case COFF_SymStorageClass_EndOfStruct: return str8_lit("Struct");
case COFF_SymStorageClass_File: return str8_lit("File");
case COFF_SymStorageClass_Section: return str8_lit("Section");
case COFF_SymStorageClass_WeakExternal: return str8_lit("External");
case COFF_SymStorageClass_CLRToken: return str8_lit("Token");
}
return str8_zero();
}
internal String8
coff_string_from_weak_ext_type(COFF_WeakExtType x)
{
switch (x) {
case COFF_WeakExt_NoLibrary: return str8_lit("NoLibrary");
case COFF_WeakExt_SearchLibrary: return str8_lit("SearchLibrary");
case COFF_WeakExt_SearchAlias: return str8_lit("SearchAlias");
}
return str8_zero();
}
internal String8
coff_string_from_reloc_x86(COFF_Reloc_X86 x)
{
switch (x) {
case COFF_Reloc_X86_Abs: return str8_lit("Abs");
case COFF_Reloc_X86_Dir16: return str8_lit("Dir16");
case COFF_Reloc_X86_Rel16: return str8_lit("Rel16");
case COFF_Reloc_X86_Unknown0: return str8_lit("Unknown0");
case COFF_Reloc_X86_Unknown2: return str8_lit("Unknown2");
case COFF_Reloc_X86_Unknown3: return str8_lit("Unknown3");
case COFF_Reloc_X86_Dir32: return str8_lit("Dir32");
case COFF_Reloc_X86_Dir32Nb: return str8_lit("Dir32Nb");
case COFF_Reloc_X86_Seg12: return str8_lit("Seg12");
case COFF_Reloc_X86_Section: return str8_lit("Section");
case COFF_Reloc_X86_SecRel: return str8_lit("SecRel");
case COFF_Reloc_X86_Token: return str8_lit("Token");
case COFF_Reloc_X86_SecRel7: return str8_lit("SecRel7");
case COFF_Reloc_X86_Unknown4: return str8_lit("Unknown4");
case COFF_Reloc_X86_Unknown5: return str8_lit("Unknown5");
case COFF_Reloc_X86_Unknown6: return str8_lit("Unknown6");
case COFF_Reloc_X86_Unknown7: return str8_lit("Unknown7");
case COFF_Reloc_X86_Unknown8: return str8_lit("Unknown8");
case COFF_Reloc_X86_Unknown9: return str8_lit("Unknown9");
case COFF_Reloc_X86_Rel32: return str8_lit("Rel32");
}
return str8_zero();
}
internal String8
coff_string_from_reloc_x64(COFF_Reloc_X64 x)
{
switch (x) {
case COFF_Reloc_X64_Abs: return str8_lit("Abs");
case COFF_Reloc_X64_Addr64: return str8_lit("Addr64");
case COFF_Reloc_X64_Addr32: return str8_lit("Addr32");
case COFF_Reloc_X64_Addr32Nb: return str8_lit("Addr32Nb");
case COFF_Reloc_X64_Rel32: return str8_lit("Rel32");
case COFF_Reloc_X64_Rel32_1: return str8_lit("Rel32_1");
case COFF_Reloc_X64_Rel32_2: return str8_lit("Rel32_2");
case COFF_Reloc_X64_Rel32_3: return str8_lit("Rel32_3");
case COFF_Reloc_X64_Rel32_4: return str8_lit("Rel32_4");
case COFF_Reloc_X64_Rel32_5: return str8_lit("Rel32_5");
case COFF_Reloc_X64_Section: return str8_lit("Section");
case COFF_Reloc_X64_SecRel: return str8_lit("SecRel");
case COFF_Reloc_X64_SecRel7: return str8_lit("SecRel7");
case COFF_Reloc_X64_Token: return str8_lit("Token");
case COFF_Reloc_X64_SRel32: return str8_lit("SRel32");
case COFF_Reloc_X64_Pair: return str8_lit("Pair");
case COFF_Reloc_X64_SSpan32: return str8_lit("SSpan32");
}
return str8_zero();
}
internal String8
coff_string_from_reloc_arm(COFF_Reloc_Arm x)
{
switch (x) {
case COFF_Reloc_Arm_Abs: return str8_lit("Abs");
case COFF_Reloc_Arm_Addr32: return str8_lit("Addr32");
case COFF_Reloc_Arm_Addr32Nb: return str8_lit("Addr32Nb");
case COFF_Reloc_Arm_Branch24: return str8_lit("Branch24");
case COFF_Reloc_Arm_Branch11: return str8_lit("Branch11");
case COFF_Reloc_Arm_Unknown1: return str8_lit("Unknown1");
case COFF_Reloc_Arm_Unknown2: return str8_lit("Unknown2");
case COFF_Reloc_Arm_Unknown3: return str8_lit("Unknown3");
case COFF_Reloc_Arm_Unknown4: return str8_lit("Unknown4");
case COFF_Reloc_Arm_Unknown5: return str8_lit("Unknown5");
case COFF_Reloc_Arm_Rel32: return str8_lit("Rel32");
case COFF_Reloc_Arm_Section: return str8_lit("Section");
case COFF_Reloc_Arm_SecRel: return str8_lit("SecRel");
case COFF_Reloc_Arm_Mov32: return str8_lit("Mov32");
case COFF_Reloc_Arm_ThumbMov32: return str8_lit("ThumbMov32");
case COFF_Reloc_Arm_ThumbBranch20: return str8_lit("ThumbBranch20");
case COFF_Reloc_Arm_Unused: return str8_lit("Unused");
case COFF_Reloc_Arm_ThumbBranch24: return str8_lit("ThumbBranch24");
case COFF_Reloc_Arm_ThumbBlx23: return str8_lit("ThumbBlx23");
case COFF_Reloc_Arm_Pair: return str8_lit("Pair");
}
return str8_zero();
}
internal String8
coff_string_from_reloc_arm64(COFF_Reloc_Arm64 x)
{
switch (x) {
case COFF_Reloc_Arm64_Abs: return str8_lit("Abs");
case COFF_Reloc_Arm64_Addr32: return str8_lit("Addr32");
case COFF_Reloc_Arm64_Addr32Nb: return str8_lit("Addr32Nb");
case COFF_Reloc_Arm64_Branch26: return str8_lit("Branch26");
case COFF_Reloc_Arm64_PageBaseRel21: return str8_lit("PageBaseRel21");
case COFF_Reloc_Arm64_Rel21: return str8_lit("Rel21");
case COFF_Reloc_Arm64_PageOffset12a: return str8_lit("PageOffset12a");
case COFF_Reloc_Arm64_SecRel: return str8_lit("SecRel");
case COFF_Reloc_Arm64_SecRelLow12a: return str8_lit("SecRelLow12a");
case COFF_Reloc_Arm64_SecRelHigh12a: return str8_lit("SecRelHigh12a");
case COFF_Reloc_Arm64_SecRelLow12l: return str8_lit("SecRelLow12l");
case COFF_Reloc_Arm64_Token: return str8_lit("Token");
case COFF_Reloc_Arm64_Section: return str8_lit("Section");
case COFF_Reloc_Arm64_Addr64: return str8_lit("Addr64");
case COFF_Reloc_Arm64_Branch19: return str8_lit("Branch19");
case COFF_Reloc_Arm64_Branch14: return str8_lit("Branch14");
case COFF_Reloc_Arm64_Rel32: return str8_lit("Rel32");
}
return str8_zero();
}
internal String8
coff_string_from_reloc(COFF_MachineType machine, COFF_RelocType x)
{
switch (machine) {
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();
}
internal COFF_MachineType
coff_machine_from_string(String8 string)
{
for (U64 i = 0; i < ArrayCount(g_coff_machine_map); ++i) {
if (str8_match(g_coff_machine_map[i].string, string, StringMatchFlag_CaseInsensitive)) {
return g_coff_machine_map[i].machine;
}
}
return COFF_MachineType_Unknown;
}
internal COFF_ImportType
coff_import_header_type_from_string(String8 name)
{
for (U64 i = 0; i < ArrayCount(g_coff_import_header_type_map); ++i) {
if (str8_match(str8_cstring(g_coff_import_header_type_map[i].name), name, StringMatchFlag_CaseInsensitive)) {
return g_coff_import_header_type_map[i].type;
}
}
return COFF_ImportType_Invalid;
}
-27
View File
@@ -1,27 +0,0 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef COFF_ENUM_H
#define COFF_ENUM_H
internal String8 coff_string_from_time_stamp(Arena *arena, COFF_TimeStamp time_stamp);
internal String8 coff_string_from_comdat_select_type(COFF_ComdatSelectType type);
internal String8 coff_string_from_machine_type(COFF_MachineType machine);
internal String8 coff_string_from_flags(Arena *arena, COFF_FileHeaderFlags flags);
internal String8 coff_string_from_section_flags(Arena *arena, COFF_SectionFlags flags);
internal String8 coff_string_from_resource_memory_flags(Arena *arena, COFF_ResourceMemoryFlags flags);
internal String8 coff_string_from_import_header_type(COFF_ImportType type);
internal String8 coff_string_from_sym_dtype(COFF_SymDType x);
internal String8 coff_string_from_sym_type(COFF_SymType x);
internal String8 coff_string_from_sym_storage_class(COFF_SymStorageClass x);
internal String8 coff_string_from_weak_ext_type(COFF_WeakExtType x);
internal String8 coff_string_from_reloc_x86(COFF_Reloc_X86 x);
internal String8 coff_string_from_reloc_x64(COFF_Reloc_X64 x);
internal String8 coff_string_from_reloc_arm(COFF_Reloc_Arm x);
internal String8 coff_string_from_reloc_arm64(COFF_Reloc_Arm64 x);
internal String8 coff_string_from_reloc(COFF_MachineType machine, COFF_RelocType x);
internal COFF_MachineType coff_machine_from_string(String8 string);
internal COFF_ImportType coff_import_header_type_from_string(String8 name);
#endif // COFF_ENUM_H
+6
View File
@@ -0,0 +1,6 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#include "coff/coff.c"
#include "coff/coff_parse.c"
#include "coff/coff_dump.c"
+11
View File
@@ -0,0 +1,11 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef COFF_INC_H
#define COFF_INC_H
#include "coff/coff.h"
#include "coff/coff_parse.h"
#include "coff/coff_dump.h"
#endif // COFF_INC_H
+365
View File
@@ -0,0 +1,365 @@
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal COFF_LibWriterSymbolNode *
coff_lib_writer_symbol_list_push(Arena *arena, COFF_LibWriterSymbolList *list, COFF_LibWriterSymbol symbol)
{
COFF_LibWriterSymbolNode *node = push_array_no_zero(arena, COFF_LibWriterSymbolNode, 1);
node->next = 0;
node->data = symbol;
SLLQueuePush(list->first, list->last, node);
list->count += 1;
return node;
}
internal COFF_LibWriterMemberNode *
coff_lib_writer_member_list_push(Arena *arena, COFF_LibWriterMemberList *list, COFF_LibWriterMember member)
{
COFF_LibWriterMemberNode *node = push_array_no_zero(arena, COFF_LibWriterMemberNode, 1);
node->next = 0;
node->data = member;
SLLQueuePush(list->first, list->last, node);
list->count += 1;
return node;
}
internal COFF_LibWriterSymbol *
coff_lib_writer_symbol_array_from_list(Arena *arena, COFF_LibWriterSymbolList list)
{
COFF_LibWriterSymbol *arr = push_array_no_zero(arena, COFF_LibWriterSymbol, list.count + 2);
COFF_LibWriterSymbol *ptr = arr + 1;
for (COFF_LibWriterSymbolNode *i = list.first; i != 0; i = i->next, ptr += 1) {
ptr->name = push_str8_copy(arena, i->data.name);
ptr->member_idx = i->data.member_idx;
}
MemoryZeroStruct(&arr[0]);
MemoryZeroStruct(&arr[list.count+1]);
return arr;
}
internal COFF_LibWriterMember *
coff_lib_writer_member_array_from_list(Arena *arena, COFF_LibWriterMemberList list)
{
COFF_LibWriterMember *arr = push_array_no_zero(arena, COFF_LibWriterMember, list.count);
COFF_LibWriterMember *ptr = arr;
for (COFF_LibWriterMemberNode *i = list.first; i != 0; i = i->next, ptr += 1) {
ptr->name = push_str8_copy(arena, i->data.name);
ptr->data = push_str8_copy(arena, i->data.data);
}
return arr;
}
internal int
coff_lib_writer_symbol_name_compar(const void *raw_a, const void *raw_b)
{
const COFF_LibWriterSymbol *sa = raw_a;
const COFF_LibWriterSymbol *sb = raw_b;
return str8_compar_case_sensitive(&sa->name, &sb->name);
}
internal int
coff_lib_writer_symbol_is_before(void *raw_a, void *raw_b)
{
int compar = coff_lib_writer_symbol_name_compar(raw_a, raw_b);
return compar < 0;
}
internal void
coff_lib_writer_symbol_array_sort(COFF_LibWriterSymbol *arr, U64 count)
{
Assert(count >= 2);
radsort(arr + 1, count - 2, coff_lib_writer_symbol_is_before);
}
internal COFF_LibWriter *
coff_lib_writer_alloc(void)
{
Arena *arena = arena_alloc();
COFF_LibWriter *writer = push_array(arena, COFF_LibWriter, 1);
writer->arena = arena;
return writer;
}
internal void
coff_lib_writer_release(COFF_LibWriter **writer_ptr)
{
arena_release((*writer_ptr)->arena);
*writer_ptr = 0;
}
internal U64
coff_lib_writer_push_obj(COFF_LibWriter *writer, String8 obj_path, String8 obj_data)
{
U64 member_idx = writer->member_list.count;
// push obj member
COFF_LibWriterMember member = {0};
member.name = obj_path;
member.data = obj_data;
coff_lib_writer_member_list_push(writer->arena, &writer->member_list, member);
// push external symbols
{
COFF_FileHeaderInfo obj_header = coff_file_header_info_from_data(obj_data);
String8 string_table = str8_substr(obj_data, obj_header.string_table_range);
String8 symbol_table = str8_substr(obj_data, obj_header.symbol_table_range);
COFF_ParsedSymbol symbol;
for (U64 symbol_idx = 0; symbol_idx < obj_header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
void *symbol_ptr;
if (obj_header.is_big_obj) {
symbol_ptr = &((COFF_Symbol32 *)symbol_table.str)[symbol_idx];
symbol = coff_parse_symbol32(string_table, symbol_ptr);
} else {
symbol_ptr = &((COFF_Symbol16 *)symbol_table.str)[symbol_idx];
symbol = coff_parse_symbol16(string_table, symbol_ptr);
}
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
if (interp == COFF_SymbolValueInterp_Regular) {
if (symbol.storage_class == COFF_SymStorageClass_External) {
COFF_LibWriterSymbol lib_symbol = {0};
lib_symbol.name = symbol.name;
lib_symbol.member_idx = member_idx;
coff_lib_writer_symbol_list_push(writer->arena, &writer->symbol_list, lib_symbol);
}
}
}
}
return member_idx;
}
internal void
coff_lib_writer_push_import(COFF_LibWriter *lib_writer, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, COFF_ImportByType import_by, String8 name, U16 hint_or_ordinal, COFF_ImportType import_type)
{
// push import member
U64 member_idx = lib_writer->member_list.count;
COFF_LibWriterMember member = {0};
member.name = dll_name;
member.data = coff_make_import_header(lib_writer->arena, machine, time_stamp, dll_name, import_by, name, hint_or_ordinal, import_type);
coff_lib_writer_member_list_push(lib_writer->arena, &lib_writer->member_list, member);
if (name.size) {
switch (import_type) {
case COFF_ImportHeader_Code: {
COFF_LibWriterSymbol thunk_symbol = {0};
thunk_symbol.name = push_str8_copy(lib_writer->arena, name);
thunk_symbol.member_idx = member_idx;
coff_lib_writer_symbol_list_push(lib_writer->arena, &lib_writer->symbol_list, thunk_symbol);
COFF_LibWriterSymbol imp_symbol = {0};
imp_symbol.name = push_str8f(lib_writer->arena, "__imp_%S", name);
imp_symbol.member_idx = member_idx;
coff_lib_writer_symbol_list_push(lib_writer->arena, &lib_writer->symbol_list, imp_symbol);
} break;
case COFF_ImportHeader_Data: {
COFF_LibWriterSymbol imp_symbol = {0};
imp_symbol.name = push_str8f(lib_writer->arena, "__imp_%S", name);
imp_symbol.member_idx = member_idx;
coff_lib_writer_symbol_list_push(lib_writer->arena, &lib_writer->symbol_list, imp_symbol);
} break;
case COFF_ImportHeader_Const: { NotImplemented; } break;
default: { InvalidPath; } break;
}
}
}
internal String8List
coff_lib_writer_serialize(Arena *arena, COFF_LibWriter *lib_writer, COFF_TimeStamp time_stamp, U16 mode, B32 emit_second_member)
{
Temp scratch = scratch_begin(&arena, 1);
// symbol & member lists -> arrays
U64 symbols_count;
COFF_LibWriterSymbol *symbols;
U64 member_count;
COFF_LibWriterMember *member_array;
{
U64 symbols_count_with_null = lib_writer->symbol_list.count + 2;
COFF_LibWriterSymbol *symbols_with_null = coff_lib_writer_symbol_array_from_list(scratch.arena, lib_writer->symbol_list);
coff_lib_writer_symbol_array_sort(symbols_with_null, symbols_count_with_null);
symbols_count = symbols_count_with_null - 2;
symbols = symbols_with_null + 1;
member_count = lib_writer->member_list.count;
member_array = coff_lib_writer_member_array_from_list(scratch.arena, lib_writer->member_list);
}
// serialize members
U64 *member_offsets = push_array_no_zero(scratch.arena, U64, member_count);
String8List long_names_list = {0};
String8List member_data_list = {0};
{
HashTable *name_ht = hash_table_init(scratch.arena, 1024);
for (U64 member_idx = 0; member_idx < member_count; member_idx += 1) {
COFF_LibWriterMember *member = &member_array[member_idx];
// make member name
String8 name;
U64 name_with_slash_size = member->name.size + 1;
if (name_with_slash_size > COFF_Archive_MaxShortNameSize) {
// have we seen this member name before?
KeyValuePair *is_present = hash_table_search_string(name_ht, member->name);
if (is_present) {
name = is_present->value_string;
} else {
name = push_str8f(scratch.arena, "/%u", long_names_list.total_size);
str8_list_pushf(scratch.arena, &long_names_list, "%S/\n", member->name);
hash_table_push_string_string(scratch.arena, name_ht, member->name, name);
}
} else {
name = push_str8f(scratch.arena, "%S/", member->name);
}
member_offsets[member_idx] = member_data_list.total_size;
String8 member_data = member->data;
String8 member_header = coff_make_lib_member_header(arena, name, time_stamp, 0, 0, mode, member_data.size);
str8_list_push(arena, &member_data_list, member_header);
str8_list_push(arena, &member_data_list, member_data);
{
U64 pad_size = AlignPadPow2(member_data_list.total_size, COFF_Archive_MemberAlign);
U8 *pad = push_array(arena, U8, pad_size);
str8_list_push(arena, &member_data_list, str8(pad, pad_size));
}
}
}
// long names member
if (long_names_list.total_size) {
String8 header = coff_make_lib_member_header(arena, str8_lit("//"), time_stamp, 0, 0, mode, long_names_list.total_size);
String8 data = str8_list_join(arena, &long_names_list, 0);
U64 member_offset = member_data_list.total_size + data.size + header.size;
{
U64 pad_size = AlignPadPow2(member_offset, COFF_Archive_MemberAlign);
U8 *pad = push_array(arena, U8, pad_size);
str8_list_push_front(arena, &member_data_list, str8(pad, pad_size));
}
str8_list_push_front(arena, &member_data_list, data);
str8_list_push_front(arena, &member_data_list, header);
}
// compute size for symbol string table
U32 name_buffer_size = 0;
for (COFF_LibWriterSymbol *ptr = &symbols[0], *opl = ptr + symbols_count; ptr < opl; ptr += 1) {
name_buffer_size += ptr->name.size;
name_buffer_size += 1; // null
}
// write symbol name buffer
U8 *name_buffer = push_array_no_zero(scratch.arena, U8, name_buffer_size);
{
U64 name_cursor = 0;
for (COFF_LibWriterSymbol *ptr = &symbols[0], *opl = ptr + symbols_count; ptr < opl; ptr += 1) {
MemoryCopy(name_buffer + name_cursor, ptr->name.str, ptr->name.size);
name_buffer[name_cursor + ptr->name.size] = '\0';
name_cursor += ptr->name.size + 1;
}
}
U64 members_base_offset;
{
U64 sizeof_first_header = sizeof(COFF_ArchiveMemberHeader) + sizeof(U32) + sizeof(U32) * symbols_count + name_buffer_size;
U64 sizeof_second_header = sizeof(COFF_ArchiveMemberHeader) + sizeof(U32) + sizeof(U32) * member_count + sizeof(U32) + sizeof(U16) * symbols_count + name_buffer_size;
U64 sizeof_long_names = sizeof(COFF_ArchiveMemberHeader) + long_names_list.total_size;
sizeof_first_header = AlignPow2(sizeof_first_header, COFF_Archive_MemberAlign);
sizeof_second_header = AlignPow2(sizeof_second_header, COFF_Archive_MemberAlign);
sizeof_long_names = AlignPow2(sizeof_long_names, COFF_Archive_MemberAlign);
members_base_offset = sizeof(g_coff_archive_sig);
members_base_offset += sizeof_first_header;
if (emit_second_member) {
members_base_offset += sizeof_second_header;
}
if (long_names_list.total_size) {
members_base_offset += sizeof_long_names;
}
}
// second linker member
if (emit_second_member) {
U32 member_count32 = safe_cast_u32(member_count);
U32 symbol_count32 = safe_cast_u32(symbols_count);
U32 *member_off32_arr = push_array_no_zero(scratch.arena, U32, member_count);
U16 *member_idx16_arr = push_array_no_zero(scratch.arena, U16, symbols_count);
// write member offset array
for (U64 member_idx = 0; member_idx < member_count; member_idx += 1) {
U64 member_offset = members_base_offset + member_offsets[member_idx];
U32 member_off32 = safe_cast_u32(member_offset);
member_off32_arr[member_idx] = member_off32;
}
// write member offset indices for each symbol
for (U64 symbol_idx = 0; symbol_idx < symbols_count; symbol_idx += 1) {
// member offset indices are 1-based
U64 member_idx = symbols[symbol_idx].member_idx + 1;
U16 member_idx16 = safe_cast_u16(member_idx);
member_idx16_arr[symbol_idx] = member_idx16;
}
// layout second member data
String8List second_member_data_list = {0};
str8_list_push(scratch.arena, &second_member_data_list, str8_struct(&member_count32));
str8_list_push(scratch.arena, &second_member_data_list, str8_array(member_off32_arr, member_count));
str8_list_push(scratch.arena, &second_member_data_list, str8_struct(&symbol_count32));
str8_list_push(scratch.arena, &second_member_data_list, str8_array(member_idx16_arr, symbols_count));
str8_list_push(scratch.arena, &second_member_data_list, str8(name_buffer, name_buffer_size));
String8 member_data = str8_list_join(arena, &second_member_data_list, 0);
String8 member_header = coff_make_lib_member_header(arena, str8_lit("/"), time_stamp, 0, 0, mode, member_data.size);
U64 member_offset = member_data_list.total_size + member_data.size + member_header.size;
{
U64 pad_size = AlignPadPow2(member_offset, COFF_Archive_MemberAlign);
U8 *pad = push_array(arena, U8, pad_size);
str8_list_push_front(arena, &member_data_list, str8(pad, pad_size));
}
str8_list_push_front(arena, &member_data_list, member_data);
str8_list_push_front(arena, &member_data_list, member_header);
}
// first linker member (obsolete, but kept for compatability reasons)
{
U32 symbol_count_be = from_be_u32(symbols_count);
U32 *member_off32_arr = push_array_no_zero(scratch.arena, U32, symbols_count);
for (U64 symbol_idx = 0; symbol_idx < symbols_count; symbol_idx += 1) {
COFF_LibWriterSymbol *symbol = &symbols[symbol_idx];
// write big endian member offset
U64 member_offset = members_base_offset + member_offsets[symbol->member_idx];
U32 member_off32 = from_be_u32(safe_cast_u32(member_offset));
member_off32_arr[symbol_idx] = member_off32;
}
// layout first member data
String8List first_member_data_list = {0};
str8_list_push(scratch.arena, &first_member_data_list, str8_struct(&symbol_count_be));
str8_list_push(scratch.arena, &first_member_data_list, str8_array(member_off32_arr, symbols_count));
str8_list_push(scratch.arena, &first_member_data_list, str8(name_buffer, name_buffer_size));
String8 member_data = str8_list_join(arena, &first_member_data_list, 0);
String8 member_header = coff_make_lib_member_header(arena, str8_lit("/"), time_stamp, 0, 0, mode, member_data.size);
U64 member_offset = sizeof(g_coff_archive_sig) + member_header.size + member_data.size;
{
U64 pad_size = AlignPadPow2(member_offset, COFF_Archive_MemberAlign);
U8 *pad = push_array(arena, U8, pad_size);
str8_list_push_front(arena, &member_data_list, str8(pad, pad_size));
}
str8_list_push_front(arena, &member_data_list, member_data);
str8_list_push_front(arena, &member_data_list, member_header);
}
// archive signature
str8_list_push_front(arena, &member_data_list, str8_struct(&g_coff_archive_sig));
scratch_end(scratch);
return member_data_list;
}
+69
View File
@@ -0,0 +1,69 @@
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef COFF_LIB_WRITER_H
#define COFF_LIB_WRITER_H
typedef struct COFF_LibWriterMember
{
String8 name;
String8 data;
} COFF_LibWriterMember;
typedef struct COFF_LibWriterMemberNode
{
COFF_LibWriterMember data;
struct COFF_LibWriterMemberNode *next;
} COFF_LibWriterMemberNode;
typedef struct COFF_LibWriterMemberList
{
U64 count;
COFF_LibWriterMemberNode *first;
COFF_LibWriterMemberNode *last;
} COFF_LibWriterMemberList;
typedef struct COFF_LibWriterSymbol
{
String8 name;
U64 member_idx;
} COFF_LibWriterSymbol;
typedef struct COFF_LibWriterSymbolNode
{
COFF_LibWriterSymbol data;
struct COFF_LibWriterSymbolNode *next;
} COFF_LibWriterSymbolNode;
typedef struct COFF_LibWriterSymbolList
{
U64 count;
COFF_LibWriterSymbolNode *first;
COFF_LibWriterSymbolNode *last;
} COFF_LibWriterSymbolList;
typedef struct COFF_LibWriter
{
Arena *arena;
COFF_LibWriterMemberList member_list;
COFF_LibWriterSymbolList symbol_list;
} COFF_LibWriter;
////////////////////////////////
internal COFF_LibWriterSymbolNode * coff_lib_writer_symbol_list_push(Arena *arena, COFF_LibWriterSymbolList *list, COFF_LibWriterSymbol symbol);
internal COFF_LibWriterMemberNode * coff_lib_writer_member_list_push(Arena *arena, COFF_LibWriterMemberList *list, COFF_LibWriterMember member);
internal COFF_LibWriterSymbol * coff_lib_writer_symbol_array_from_list(Arena *arena, COFF_LibWriterSymbolList list);
internal COFF_LibWriterMember * coff_lib_writer_member_array_from_list(Arena *arena, COFF_LibWriterMemberList list);
internal void coff_lib_writer_symbol_array_sort(COFF_LibWriterSymbol *arr, U64 count);
internal COFF_LibWriter * coff_lib_writer_alloc(void);
internal void coff_lib_writer_release(COFF_LibWriter **writer_ptr);
internal U64 coff_lib_writer_push_obj(COFF_LibWriter *writer, String8 obj_path, String8 obj_data);
internal void coff_lib_writer_push_import(COFF_LibWriter *lib_writer, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, COFF_ImportByType import_by, String8 name, U16 hint_or_ordinal, COFF_ImportType import_type);
internal String8List coff_lib_writer_serialize(Arena *arena, COFF_LibWriter *lib_writer, COFF_TimeStamp time_stamp, U16 mode, B32 emit_second_member);
#endif // COFF_LIB_WRITER_H
+470
View File
@@ -0,0 +1,470 @@
internal COFF_ObjWriter*
coff_obj_writer_alloc(COFF_TimeStamp time_stamp, COFF_MachineType machine)
{
Arena *arena = arena_alloc();
COFF_ObjWriter *obj_writer = push_array(arena, COFF_ObjWriter, 1);
obj_writer->arena = arena;
obj_writer->time_stamp = time_stamp;
obj_writer->machine = machine;
return obj_writer;
}
internal void
coff_obj_writer_release(COFF_ObjWriter **obj_writer)
{
arena_release((*obj_writer)->arena);
*obj_writer = 0;
}
internal String8
coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
{
Temp scratch = scratch_begin(&arena, 1);
String8List srl = {0};
String8List string_table = {0};
U32 *string_table_size = push_array(scratch.arena, U32, 1);
*string_table_size = sizeof(*string_table_size);
str8_list_push(scratch.arena, &string_table, str8_struct(string_table_size));
//
// assing section numbers
//
U64 obj_sections_count;
COFF_ObjSection **obj_sections;
{
obj_sections_count = obj_writer->sect_count;
obj_sections = push_array(scratch.arena, COFF_ObjSection *, obj_writer->sect_count);
U64 sect_idx = 0;
for (COFF_ObjSectionNode *sect_n = obj_writer->sect_first; sect_n != 0; sect_n = sect_n->next, sect_idx += 1) {
COFF_ObjSection *sect = &sect_n->v;
sect->section_number = sect_idx+1;
obj_sections[sect_idx] = sect;
}
}
AssertAlways(obj_sections_count <= max_U16);
//
// serialize symbol table
//
String8List symbol_table = {0};
{
U64 symbol_idx = 0;
for (COFF_ObjSymbolNode *symbol_n = obj_writer->symbol_first; symbol_n != 0; symbol_n = symbol_n->next) {
COFF_ObjSymbol *s = &symbol_n->v;
// assign symbol index
s->idx = symbol_idx++;
COFF_Symbol16 *d = push_array(scratch.arena, COFF_Symbol16, 1);
str8_list_push(scratch.arena, &symbol_table, str8_struct(d));
COFF_SymbolName name = {0};
// long name
if (s->name.size > sizeof(name.short_name)) {
U64 string_table_offset = string_table.total_size;
str8_list_push_cstr(scratch.arena, &string_table, s->name);
name.long_name.zeroes = 0;
name.long_name.string_table_offset = safe_cast_u32(string_table_offset);
}
// short name
else {
MemoryCopyStr8(name.short_name, s->name);
MemoryZeroTyped(name.short_name + s->name.size, sizeof(name.short_name) - s->name.size);
}
// symbol header
AssertAlways(s->aux_symbols.node_count <= max_U8);
d->name = name;
d->value = s->value;
switch (s->loc.type) {
case COFF_SymbolLocation_Null: break;
case COFF_SymbolLocation_Section: d->section_number = safe_cast_u16(s->loc.u.section->section_number); break;
case COFF_SymbolLocation_Abs: d->section_number = COFF_Symbol_AbsSection16; break;
case COFF_SymbolLocation_Undef: d->section_number = COFF_Symbol_UndefinedSection; break;
}
d->type = s->type;
d->storage_class = s->storage_class;
d->aux_symbol_count = 0;
U64 start_symbol_idx = symbol_idx;
if (s->storage_class == COFF_SymStorageClass_WeakExternal) {
if (s->aux_symbols.node_count > 0) {
COFF_ObjSymbolWeak *s_weak = (COFF_ObjSymbolWeak *)s->aux_symbols.first->string.str;
COFF_SymbolWeakExt *d_weak = push_array(scratch.arena, COFF_SymbolWeakExt, 1);
d_weak->tag_index = s_weak->tag->idx;
d_weak->characteristics = s_weak->characteristics;
str8_list_push(scratch.arena, &symbol_table, str8_struct(d_weak));
symbol_idx += 1;
}
} else if (s->storage_class == COFF_SymStorageClass_Static) {
if (s->aux_symbols.node_count > 0) {
Assert(s->loc.type == COFF_SymbolLocation_Section);
COFF_ObjSection *sect = s->loc.u.section;
COFF_ObjSymbolSecDef *s_sd = (COFF_ObjSymbolSecDef *)s->aux_symbols.first->string.str;
COFF_SymbolSecDef *d_sd = push_array(scratch.arena, COFF_SymbolSecDef, 1);
d_sd->length = safe_cast_u32(sect->data.total_size);
d_sd->number_of_relocations = (U16)sect->reloc_count;
d_sd->check_sum = 0;
d_sd->number_lo = s_sd->selection == COFF_ComdatSelect_Associative ? safe_cast_u16(s_sd->associate->section_number) : 0;
d_sd->selection = s_sd->selection;
str8_list_push(scratch.arena, &symbol_table, str8_struct(d_sd));
symbol_idx += 1;
}
}
U8 processed_aux_symbol_count = (U8)(symbol_idx - start_symbol_idx);
for (U64 aux_idx = processed_aux_symbol_count; aux_idx < s->aux_symbols.node_count; aux_idx += 1) {
COFF_Symbol16 *a = push_array(scratch.arena, COFF_Symbol16, 1);
str8_list_push(scratch.arena, &symbol_table, str8_struct(a));
}
d->aux_symbol_count = (U8)s->aux_symbols.node_count;
}
}
//
// file header
//
COFF_FileHeader *file_header = push_array(scratch.arena, COFF_FileHeader, 1);
file_header->machine = obj_writer->machine;
file_header->section_count = obj_sections_count;
file_header->time_stamp = obj_writer->time_stamp;
file_header->symbol_table_foff = 0;
file_header->symbol_count = safe_cast_u32(symbol_table.node_count);
file_header->optional_header_size = 0;
file_header->flags = 0;
str8_list_push(scratch.arena, &srl, str8_struct(file_header));
//
// section table
//
COFF_SectionHeader *sectab = push_array(scratch.arena, COFF_SectionHeader, obj_sections_count);
str8_list_push(scratch.arena, &srl, str8_array(sectab, obj_sections_count));
{
for (U64 sect_idx = 0; sect_idx < obj_sections_count; sect_idx += 1) {
COFF_ObjSection *s = obj_sections[sect_idx];
COFF_SectionHeader *d = &sectab[sect_idx];
// section name
String8 sect_name = s->name;
if (sect_name.size > sizeof(d->name)) {
U64 sect_name_off = string_table.total_size;
str8_list_push_cstr(scratch.arena, &string_table, sect_name);
sect_name = push_str8f(scratch.arena, "/%u", sect_name_off);
AssertAlways(sect_name.size <= sizeof(d->name));
}
// alloc zero nodes
for (String8Node *data_n = s->data.first; data_n != 0; data_n = data_n->next) {
if (data_n->string.str == 0 && data_n->string.size > 0) {
data_n->string = str8(push_array(scratch.arena, U8, data_n->string.size), data_n->string.size);
}
}
// section data
U64 data_foff = 0;
U64 data_size = 0;
if (s->data.total_size > 0) {
data_foff = srl.total_size;
data_size = s->data.total_size;
str8_list_concat_in_place(&srl, &s->data);
}
// section relocs
U64 relocs_foff = 0;
if (s->reloc_count) {
AssertAlways(s->reloc_count <= max_U16);
COFF_Reloc *relocs = push_array(scratch.arena, COFF_Reloc, s->reloc_count);
U64 reloc_idx = 0;
for (COFF_ObjRelocNode *reloc_n = s->reloc_first; reloc_n != 0; reloc_n = reloc_n->next, reloc_idx += 1) {
COFF_ObjReloc *rs = &reloc_n->v;
COFF_Reloc *rd = &relocs[reloc_idx];
rd->apply_off = rs->apply_off;
rd->isymbol = rs->symbol->idx;
rd->type = rs->type;
}
relocs_foff = srl.total_size;
str8_list_push(scratch.arena, &srl, str8_array(relocs, s->reloc_count));
}
// section header
MemoryCopyStr8(d->name, sect_name);
MemoryZeroTyped(d->name + sect_name.size, sizeof(d->name) - sect_name.size);
d->vsize = 0;
d->voff = 0;
d->fsize = data_size;
d->foff = data_foff;
d->relocs_foff = relocs_foff;
d->lines_foff = 0;
d->reloc_count = safe_cast_u32(s->reloc_count);
d->line_count = 0;
d->flags = s->flags;
}
}
//
// symbol table
//
if (symbol_table.total_size || string_table.total_size > sizeof(*string_table_size)) {
file_header->symbol_table_foff = srl.total_size;
str8_list_concat_in_place(&srl, &symbol_table);
}
//
// string table
//
if (string_table.total_size) {
*string_table_size = safe_cast_u32(string_table.total_size);
str8_list_concat_in_place(&srl, &string_table);
}
//
// join
//
String8 obj = str8_list_join(arena, &srl, 0);
scratch_end(scratch);
return obj;
}
internal COFF_ObjSection *
coff_obj_writer_push_section(COFF_ObjWriter *obj_writer, String8 name, COFF_SectionFlags flags, String8 data)
{
COFF_ObjSectionNode *sect_n = push_array(obj_writer->arena, COFF_ObjSectionNode, 1);
SLLQueuePush(obj_writer->sect_first, obj_writer->sect_last, sect_n);
obj_writer->sect_count += 1;
COFF_ObjSection *sect = &sect_n->v;
sect->name = name;
sect->flags = flags;
if (data.size) {
str8_list_push(obj_writer->arena, &sect->data, data);
}
return sect;
}
internal COFF_ObjSymbol *
coff_obj_writer_push_symbol(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_SymbolLocation loc, COFF_SymbolType type, COFF_SymStorageClass storage_class)
{
COFF_ObjSymbolNode *n = push_array(obj_writer->arena, COFF_ObjSymbolNode, 1);
SLLQueuePush(obj_writer->symbol_first, obj_writer->symbol_last, n);
obj_writer->symbol_count += 1;
COFF_ObjSymbol *s = &n->v;
s->name = name;
s->value = value;
s->loc = loc;
s->type = type;
s->storage_class = storage_class;
return s;
}
internal COFF_ObjSymbol *
coff_obj_writer_push_symbol_extern(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section)
{
COFF_SymbolLocation loc = {0};
loc.type = COFF_SymbolLocation_Section;
loc.u.section = section;
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, value, loc, (COFF_SymbolType){0}, COFF_SymStorageClass_External);
return s;
}
internal COFF_ObjSymbol *
coff_obj_writer_push_symbol_extern_func(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section)
{
COFF_SymbolType type = { .u.msb = COFF_SymDType_Func };
COFF_SymbolLocation loc = { .type = COFF_SymbolLocation_Section, .u.section = section };
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, value, loc, type, COFF_SymStorageClass_External);
return s;
}
internal COFF_ObjSymbol *
coff_obj_writer_push_symbol_static(COFF_ObjWriter *obj_writer, String8 name, U32 off, COFF_ObjSection *section)
{
COFF_SymbolLocation loc = {0};
loc.type = COFF_SymbolLocation_Section;
loc.u.section = section;
COFF_SymbolType symtype = {0};
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, off, loc, symtype, COFF_SymStorageClass_Static);
return s;
}
internal COFF_ObjSymbol *
coff_obj_writer_push_symbol_secdef(COFF_ObjWriter *obj_writer, COFF_ObjSection *section, COFF_ComdatSelectType selection)
{
COFF_ObjSymbol *s = coff_obj_writer_push_symbol_static(obj_writer, section->name, 0, section);
COFF_ObjSymbolSecDef *sd = push_array(obj_writer->arena, COFF_ObjSymbolSecDef, 1);
sd->selection = selection;
str8_list_push(obj_writer->arena, &s->aux_symbols, str8_struct(sd));
return s;
}
internal COFF_ObjSymbol *
coff_obj_writer_push_symbol_associative(COFF_ObjWriter *obj_writer, COFF_ObjSection *head, COFF_ObjSection *associate)
{
COFF_ObjSymbol *s = coff_obj_writer_push_symbol_static(obj_writer, head->name, 0, head);
COFF_ObjSymbolSecDef *sd = push_array(obj_writer->arena, COFF_ObjSymbolSecDef, 1);
sd->selection = COFF_ComdatSelect_Associative;
sd->associate = associate;
str8_list_push(obj_writer->arena, &s->aux_symbols, str8_struct(sd));
return s;
}
internal COFF_ObjSymbol *
coff_obj_writer_push_symbol_weak(COFF_ObjWriter *obj_writer, String8 name, COFF_WeakExtType characteristics, COFF_ObjSymbol *tag)
{
COFF_SymbolLocation loc = {0};
COFF_SymbolType symtype = {0};
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, COFF_Symbol_UndefinedSection, loc, symtype, COFF_SymStorageClass_WeakExternal);
COFF_ObjSymbolWeak *weak_ext = push_array(obj_writer->arena, COFF_ObjSymbolWeak, 1);
weak_ext->tag = tag;
weak_ext->characteristics = characteristics;
str8_list_push(obj_writer->arena, &s->aux_symbols, str8_struct(weak_ext));
return s;
}
internal COFF_ObjSymbol *
coff_obj_writer_push_symbol_abs(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_SymStorageClass storage_class)
{
COFF_SymbolLocation loc = {0};
loc.type = COFF_SymbolLocation_Abs;
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, value, loc, (COFF_SymbolType){0}, storage_class);
return s;
}
internal COFF_ObjSymbol *
coff_obj_writer_push_symbol_undef(COFF_ObjWriter *obj_writer, String8 name)
{
COFF_SymbolType type = {0};
COFF_SymbolLocation loc = {0};
loc.type = COFF_SymbolLocation_Undef;
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, 0, loc, type, COFF_SymStorageClass_External);
return s;
}
internal COFF_ObjSymbol *
coff_obj_writer_push_symbol_undef_func(COFF_ObjWriter *obj_writer, String8 name)
{
COFF_SymbolType type = {0};
type.u.msb = COFF_SymDType_Func;
COFF_SymbolLocation loc = {0};
loc.type = COFF_SymbolLocation_Undef;
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, 0, loc, type, COFF_SymStorageClass_External);
return s;
}
internal COFF_ObjSymbol *
coff_obj_writer_push_symbol_undef_sect(COFF_ObjWriter *obj_writer, String8 name, U32 value)
{
COFF_SymbolType type = {0};
COFF_SymbolLocation loc = {0};
loc.type = COFF_SymbolLocation_Undef;
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, value, loc, type, COFF_SymStorageClass_Section);
return s;
}
internal COFF_ObjSymbol *
coff_obj_writer_push_symbol_sect(COFF_ObjWriter *obj_writer, String8 name, COFF_ObjSection *sect)
{
COFF_SymbolType type = {0};
COFF_SymbolLocation loc = {0};
loc.type = COFF_SymbolLocation_Section;
loc.u.section = sect;
// strip align flags
COFF_SectionFlags expected_flags = sect->flags & ~(COFF_SectionFlag_AlignMask << COFF_SectionFlag_AlignShift);
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, expected_flags, loc, type, COFF_SymStorageClass_Section);
return s;
}
internal COFF_ObjSymbol *
coff_obj_writer_push_symbol_common(COFF_ObjWriter *obj_writer, String8 name, U32 size)
{
COFF_SymbolType type = {0};
COFF_SymbolLocation loc = {0};
loc.type = COFF_SymbolLocation_Common;
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, size, loc, type, COFF_SymStorageClass_External);
return s;
}
internal COFF_ObjReloc*
coff_obj_writer_section_push_reloc(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol, COFF_RelocType type)
{
COFF_ObjRelocNode *reloc_n = push_array(obj_writer->arena, COFF_ObjRelocNode, 1);
SLLQueuePush(sect->reloc_first, sect->reloc_last, reloc_n);
sect->reloc_count += 1;
COFF_ObjReloc *reloc = &reloc_n->v;
reloc->apply_off = apply_off;
reloc->symbol = symbol;
reloc->type = type;
return reloc;
}
internal COFF_ObjReloc *
coff_obj_writer_section_push_reloc_addr(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol)
{
COFF_RelocType reloc_type = 0;
switch (obj_writer->machine) {
case COFF_MachineType_Unknown: break;
case COFF_MachineType_X64: reloc_type = COFF_Reloc_X64_Addr64; break;
default: { NotImplemented; } break;
}
return coff_obj_writer_section_push_reloc(obj_writer, sect, apply_off, symbol, reloc_type);
}
internal COFF_ObjReloc *
coff_obj_writer_section_push_reloc_voff(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol)
{
COFF_RelocType reloc_type = 0;
switch (obj_writer->machine) {
case COFF_MachineType_Unknown: break;
case COFF_MachineType_X64: reloc_type = COFF_Reloc_X64_Addr32Nb; break;
default: { NotImplemented; } break;
}
return coff_obj_writer_section_push_reloc(obj_writer, sect, apply_off, symbol, reloc_type);
}
internal void
coff_obj_writer_push_directive(COFF_ObjWriter *obj_writer, String8 directive)
{
if (obj_writer->drectve_sect == 0) {
local_persist const U8 bom_sig[] = { ' ', ' ', ' ' };
obj_writer->drectve_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".drectve"), COFF_SectionFlag_LnkInfo|COFF_SectionFlag_LnkRemove|COFF_SectionFlag_Align1Bytes, str8_array_fixed(bom_sig));
}
String8List *data = &obj_writer->drectve_sect->data;
str8_list_push(obj_writer->arena, data, directive);
str8_list_pushf(obj_writer->arena, data, " ");
}
internal int
coff_obj_section_is_before(void *raw_a, void *raw_b)
{
COFF_ObjSection **a = raw_a;
COFF_ObjSection **b = raw_b;
return (*a)->section_number < (*b)->section_number;
}
+125
View File
@@ -0,0 +1,125 @@
#ifndef COFF_OBJ_WRITER_H
#define COFF_OBJ_WRITER_H
typedef enum
{
COFF_SymbolLocation_Null,
COFF_SymbolLocation_Section,
COFF_SymbolLocation_Abs,
COFF_SymbolLocation_Undef,
COFF_SymbolLocation_Common,
} COFF_SymbolLocationType;
typedef struct COFF_SymbolLocation
{
COFF_SymbolLocationType type;
union {
struct COFF_ObjSection *section;
} u;
} COFF_SymbolLocation;
typedef struct COFF_ObjSymbolWeak
{
struct COFF_ObjSymbol *tag;
COFF_WeakExtType characteristics;
} COFF_ObjSymbolWeak;
typedef struct COFF_ObjSymbolSecDef
{
COFF_ComdatSelectType selection;
struct COFF_ObjSection *associate;
} COFF_ObjSymbolSecDef;
typedef struct COFF_ObjSymbol
{
String8 name;
U32 value;
COFF_SymbolLocation loc;
COFF_SymbolType type;
COFF_SymStorageClass storage_class;
String8List aux_symbols;
U32 idx;
} COFF_ObjSymbol;
typedef struct COFF_ObjSymbolNode
{
struct COFF_ObjSymbolNode *next;
COFF_ObjSymbol v;
} COFF_ObjSymbolNode;
typedef struct COFF_ObjReloc
{
U32 apply_off;
COFF_ObjSymbol *symbol;
COFF_RelocType type;
} COFF_ObjReloc;
typedef struct COFF_ObjRelocNode
{
struct COFF_ObjRelocNode *next;
COFF_ObjReloc v;
} COFF_ObjRelocNode;
typedef struct COFF_ObjSection
{
String8 name;
String8List data;
COFF_SectionFlags flags;
U64 reloc_count;
COFF_ObjRelocNode *reloc_first;
COFF_ObjRelocNode *reloc_last;
U32 section_number;
} COFF_ObjSection;
typedef struct COFF_ObjSectionNode
{
struct COFF_ObjSectionNode *next;
COFF_ObjSection v;
} COFF_ObjSectionNode;
typedef struct COFF_ObjWriter
{
Arena *arena;
COFF_TimeStamp time_stamp;
COFF_MachineType machine;
U64 symbol_count;
COFF_ObjSymbolNode *symbol_first;
COFF_ObjSymbolNode *symbol_last;
U64 sect_count;
COFF_ObjSectionNode *sect_first;
COFF_ObjSectionNode *sect_last;
COFF_ObjSection *drectve_sect;
} COFF_ObjWriter;
////////////////////////////////
internal COFF_ObjWriter * coff_obj_writer_alloc(COFF_TimeStamp time_stamp, COFF_MachineType machine);
internal void coff_obj_writer_release(COFF_ObjWriter **obj_writer);
internal String8 coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer);
internal COFF_ObjSection * coff_obj_writer_push_section(COFF_ObjWriter *obj_writer, String8 name, COFF_SectionFlags flags, String8 data);
internal COFF_ObjSymbol* coff_obj_writer_push_symbol(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_SymbolLocation loc, COFF_SymbolType type, COFF_SymStorageClass storage_class);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_extern_func(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_extern(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_static(COFF_ObjWriter *obj_writer, String8 name, U32 off, COFF_ObjSection *section);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_secdef(COFF_ObjWriter *obj_writer, COFF_ObjSection *section, COFF_ComdatSelectType selection);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_associative(COFF_ObjWriter *obj_writer, COFF_ObjSection *head, COFF_ObjSection *associate);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_weak(COFF_ObjWriter *obj_writer, String8 name, COFF_WeakExtType characteristics, COFF_ObjSymbol *tag);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_abs(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_SymStorageClass storage_class);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_undef(COFF_ObjWriter *obj_writer, String8 name);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_undef_func(COFF_ObjWriter *obj_writer, String8 name);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_undef_sect(COFF_ObjWriter *obj_writer, String8 name, U32 value);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_sect(COFF_ObjWriter *obj_writer, String8 name, COFF_ObjSection *sect);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_common(COFF_ObjWriter *obj_writer, String8 name, U32 size);
internal COFF_ObjReloc * coff_obj_writer_section_push_reloc(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol, COFF_RelocType reloc_type);
internal COFF_ObjReloc * coff_obj_writer_section_push_reloc_addr(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol);
internal COFF_ObjReloc * coff_obj_writer_section_push_reloc_voff(COFF_ObjWriter *obj_writer, COFF_ObjSection *sect, U32 apply_off, COFF_ObjSymbol *symbol);
internal void coff_obj_writer_push_directive(COFF_ObjWriter *obj_writer, String8 directive);
#endif // COFF_OBJ_WRITER_H
+69
View File
@@ -121,6 +121,18 @@ coff_file_header_info_from_data(String8 raw_coff)
return info;
}
internal COFF_SectionHeader **
coff_section_table_from_data(Arena *arena, String8 data, Rng1U64 section_table_range)
{
U64 section_count = dim_1u64(section_table_range) / sizeof(COFF_SectionHeader);
COFF_SectionHeader **section_table = push_array_no_zero(arena, COFF_SectionHeader *, section_count+1);
section_table[0] = push_array(arena, COFF_SectionHeader, 1);
for (U64 i = 0; i < section_count; ++i) {
section_table[i+1] = str8_deserial_get_raw_ptr(data, section_table_range.min + i*sizeof(COFF_SectionHeader), sizeof(COFF_SectionHeader));
}
return section_table;
}
internal COFF_ParsedSymbol
coff_parse_symbol32(String8 string_table, COFF_Symbol32 *sym32)
{
@@ -131,6 +143,7 @@ coff_parse_symbol32(String8 string_table, COFF_Symbol32 *sym32)
result.type = sym32->type;
result.storage_class = sym32->storage_class;
result.aux_symbol_count = sym32->aux_symbol_count;
result.raw_symbol = sym32;
return result;
}
@@ -150,9 +163,22 @@ coff_parse_symbol16(String8 string_table, COFF_Symbol16 *sym16)
result.type = sym16->type;
result.storage_class = sym16->storage_class;
result.aux_symbol_count = sym16->aux_symbol_count;
result.raw_symbol = sym16;
return result;
}
internal COFF_ParsedSymbol
coff_parse_symbol(COFF_FileHeaderInfo header, String8 string_table, String8 symbol_table, U32 symbol_idx)
{
COFF_ParsedSymbol symbol;
if (header.is_big_obj) {
symbol = coff_parse_symbol32(string_table, (COFF_Symbol32 *)symbol_table.str + symbol_idx);
} else {
symbol = coff_parse_symbol16(string_table, (COFF_Symbol16 *)symbol_table.str + symbol_idx);
}
return symbol;
}
internal COFF_Symbol32Array
coff_symbol_array_from_data_16(Arena *arena, String8 raw_coff, U64 symbol_array_off, U64 symbol_count)
{
@@ -253,6 +279,49 @@ coff_interp_symbol(U32 section_number, U32 value, COFF_SymStorageClass storage_c
return COFF_SymbolValueInterp_Regular;
}
internal COFF_SymbolValueInterpType
coff_interp_from_parsed_symbol(COFF_ParsedSymbol symbol)
{
return coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
}
internal void
coff_parse_secdef(COFF_ParsedSymbol symbol, B32 is_big_obj, COFF_ComdatSelectType *selection_out, U32 *number_out, U32 *length_out, U32 *check_sum_out)
{
Assert(coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class) == COFF_SymbolValueInterp_Regular);
Assert(symbol.aux_symbol_count > 0);
if (is_big_obj) {
COFF_SymbolSecDef *sd = (COFF_SymbolSecDef *)((COFF_Symbol32 *)symbol.raw_symbol + 1);
if (selection_out) *selection_out = sd->selection;
if (length_out) *length_out = sd->length;
if (check_sum_out) *check_sum_out = sd->check_sum;
if (number_out) *number_out = Compose32Bit(sd->number_hi, sd->number_lo);
} else {
COFF_SymbolSecDef *sd = (COFF_SymbolSecDef *)((COFF_Symbol16 *)symbol.raw_symbol + 1);
if (selection_out) *selection_out = sd->selection;
if (length_out) *length_out = sd->length;
if (check_sum_out) *check_sum_out = sd->check_sum;
if (number_out) *number_out = sd->number_lo;
}
}
internal COFF_SymbolWeakExt *
coff_parse_weak_tag(COFF_ParsedSymbol symbol, B32 is_big_obj)
{
Assert(coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class) == COFF_SymbolValueInterp_Weak);
Assert(symbol.aux_symbol_count > 0);
void *tag;
if (is_big_obj) {
tag = (COFF_SymbolWeakExt *)((COFF_Symbol32 *)symbol.raw_symbol + 1);
} else {
tag = (COFF_SymbolWeakExt *)((COFF_Symbol16 *)symbol.raw_symbol + 1);
}
return tag;
}
internal COFF_RelocNode *
coff_reloc_list_push(Arena *arena, COFF_RelocList *list, COFF_Reloc reloc)
{
+19 -8
View File
@@ -49,12 +49,13 @@ typedef struct COFF_Symbol32Array
typedef struct COFF_ParsedSymbol
{
String8 name;
U32 value;
U32 section_number;
COFF_SymbolType type;
COFF_SymStorageClass storage_class;
U8 aux_symbol_count;
String8 name;
U64 value;
U32 section_number;
COFF_SymbolType type;
COFF_SymStorageClass storage_class;
U8 aux_symbol_count;
void *raw_symbol;
} COFF_ParsedSymbol;
typedef U32 COFF_SymbolValueInterpType;
@@ -194,8 +195,8 @@ typedef struct COFF_ParsedArchiveImportHeader
typedef struct COFF_ArchiveMember
{
COFF_ParsedArchiveMemberHeader header;
U64 offset;
String8 data;
U64 offset;
String8 data;
} COFF_ArchiveMember;
typedef struct COFF_ArchiveFirstMember
@@ -247,11 +248,17 @@ internal B32 coff_is_big_obj(String8 raw_coff);
internal B32 coff_is_obj (String8 raw_coff);
internal COFF_FileHeaderInfo coff_file_header_info_from_data(String8 raw_coff);
////////////////////////////////
// Section
internal COFF_SectionHeader ** coff_section_table_from_data(Arena *arena, String8 data, Rng1U64 section_table_range);
////////////////////////////////
// Symbol
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_ParsedSymbol coff_parse_symbol(COFF_FileHeaderInfo header, String8 string_table, String8 symbol_table, U32 symbol_idx);
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);
@@ -260,6 +267,10 @@ internal COFF_Symbol32Array coff_symbol_array_from_data (Arena *arena, String8
internal COFF_Symbol16Node *coff_symbol16_list_push(Arena *arena, COFF_Symbol16List *list, COFF_Symbol16 symbol);
internal COFF_SymbolValueInterpType coff_interp_symbol(U32 section_number, U32 value, COFF_SymStorageClass storage_class);
internal COFF_SymbolValueInterpType coff_interp_from_parsed_symbol(COFF_ParsedSymbol symbol);
internal void coff_parse_secdef(COFF_ParsedSymbol symbol, B32 is_big_obj, COFF_ComdatSelectType *selection_out, U32 *number_out, U32 *length_out, U32 *check_sum_out);
internal COFF_SymbolWeakExt * coff_parse_weak_tag(COFF_ParsedSymbol symbol, B32 is_big_obj);
////////////////////////////////
// Reloc
+376 -148
View File
@@ -9,14 +9,16 @@
////////////////////////////////
//~ rjf: Basic Type Functions
#if !defined(XXH_IMPLEMENTATION)
# define XXH_IMPLEMENTATION
# define XXH_STATIC_LINKING_ONLY
# include "third_party/xxHash/xxhash.h"
#endif
internal U64
ctrl_hash_from_string(String8 string)
{
U64 result = 5381;
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, 5381);
return result;
}
@@ -1366,14 +1368,16 @@ ctrl_entity_store_apply_events(CTRL_EntityCtxRWStore *store, CTRL_EventList *lis
}break;
case CTRL_EventKind_ModuleDebugInfoPathChange:
{
Temp scratch = scratch_begin(0, 0);
CTRL_Entity *module = ctrl_entity_from_handle(&store->ctx, event->entity);
CTRL_Entity *debug_info_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath);
if(debug_info_path == &ctrl_entity_nil)
{
debug_info_path = ctrl_entity_alloc(store, module, CTRL_EntityKind_DebugInfoPath, Arch_Null, ctrl_handle_zero(), 0);
}
ctrl_entity_equip_string(store, debug_info_path, event->string);
ctrl_entity_equip_string(store, debug_info_path, path_normalized_from_string(scratch.arena, event->string));
debug_info_path->timestamp = event->timestamp;
scratch_end(scratch);
}break;
//- rjf: dynamic, program-created breakpoints
@@ -1552,6 +1556,7 @@ ctrl_init(void)
ctrl_state->ctrl_thread_entity_ctx_rw_mutex = os_rw_mutex_alloc();
ctrl_state->ctrl_thread_entity_store = ctrl_entity_ctx_rw_store_alloc();
ctrl_state->ctrl_thread_eval_cache = e_cache_alloc();
ctrl_state->ctrl_thread_msg_process_arena = arena_alloc();
ctrl_state->dmn_event_arena = arena_alloc();
ctrl_state->user_entry_point_arena = arena_alloc();
ctrl_state->dbg_dir_arena = arena_alloc();
@@ -1681,14 +1686,14 @@ ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32
{
id_exists = 1;
id_stale = (n->mem_gen < mem_gen);
id_working = (ins_atomic_u64_eval(&n->working_count) != 0);
id_working = (n->working_count != 0);
goto end_fast_lookup;
}
}
}
}
end_fast_lookup:;
if(os_now_microseconds() >= endt_us || !id_working)
if(!id_stale || !id_working || os_now_microseconds() >= endt_us)
{
break;
}
@@ -1715,7 +1720,6 @@ ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32
if(!id_exists || (id_exists && id_stale && !id_working))
{
B32 node_needs_stream = 0;
U64 *node_working_count = 0;
OS_MutexScopeW(process_stripe->rw_mutex)
{
for(CTRL_ProcessMemoryCacheNode *process_n = process_slot->first; process_n != 0; process_n = process_n->next)
@@ -1744,13 +1748,12 @@ ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32
}
else
{
node_needs_stream = (range_n->mem_gen < mem_gen);
node_needs_stream = (range_n->mem_gen < mem_gen && range_n->working_count == 0);
}
if(node_needs_stream)
{
ins_atomic_u64_inc_eval(&range_n->working_count);
range_n->working_count += 1;
}
node_working_count = &range_n->working_count;
break;
}
}
@@ -1759,10 +1762,14 @@ ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32
{
if(ctrl_u2ms_enqueue_req(key, process, vaddr_range, zero_terminated, endt_us))
{
async_push_work(ctrl_mem_stream_work, .working_counter = node_working_count);
// NOTE(rjf): debugging
#if 0
raddbg_log("[0x%I64x, 0x%I64x) push: (gen: %I64u)\n", vaddr_range.min, vaddr_range.max, mem_gen);
#endif
async_push_work(ctrl_mem_stream_work);
requested = 1;
}
else OS_MutexScopeR(process_stripe->rw_mutex)
else OS_MutexScopeW(process_stripe->rw_mutex)
{
for(CTRL_ProcessMemoryCacheNode *process_n = process_slot->first; process_n != 0; process_n = process_n->next)
{
@@ -1770,23 +1777,29 @@ ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32
{
U64 range_slot_idx = range_hash%process_n->range_hash_slots_count;
CTRL_ProcessMemoryRangeHashSlot *range_slot = &process_n->range_hash_slots[range_slot_idx];
CTRL_ProcessMemoryRangeHashNode *range_n = 0;
for(CTRL_ProcessMemoryRangeHashNode *n = range_slot->first; n != 0; n = n->next)
{
if(hs_id_match(n->id, id))
{
ins_atomic_u64_dec_eval(&n->working_count);
goto end_fail_work;
n->working_count -= 1;
break;
}
}
}
}
end_fail_work:;
}
}
}
//- rjf: step 4: if we didn't request, and if we aren't working, then exit
if(!requested && !id_working)
if(!requested)
{
break;
}
//- rjf: step 5: exit if out of time
if(os_now_microseconds() >= endt_us)
{
break;
}
@@ -1971,6 +1984,12 @@ ctrl_process_write(CTRL_Handle process, Rng1U64 range, void *src)
ProfBeginFunction();
B32 result = dmn_process_write(process.dmn_handle, range, src);
//- rjf: success -> bump generation
if(result)
{
ins_atomic_u64_inc_eval(&ctrl_state->mem_gen);
}
//- rjf: success -> wait for cache updates, for small regions - prefer relatively seamless
// writes within calling frame's "view" of the memory, at the expense of a small amount of
// time.
@@ -2077,7 +2096,7 @@ ctrl_reg_block_from_thread(Arena *arena, CTRL_EntityCtx *ctx, CTRL_Handle handle
// rjf: copy from node
if(node)
{
U64 current_reg_gen = dmn_reg_gen();
U64 current_reg_gen = ctrl_reg_gen();
B32 need_stale = 1;
if(node->reg_gen != current_reg_gen && dmn_thread_read_reg_block(handle.dmn_handle, result))
{
@@ -2135,6 +2154,10 @@ ctrl_thread_write_reg_block(CTRL_Handle thread, void *block)
{
// TODO(rjf): @callstacks immediately reflect this in the call stack cache
B32 good = dmn_thread_write_reg_block(thread.dmn_handle, block);
if(good)
{
ins_atomic_u64_inc_eval(&ctrl_state->reg_gen);
}
return good;
}
@@ -3287,7 +3310,7 @@ ctrl_call_stack_from_unwind(Arena *arena, CTRL_Entity *process, CTRL_Unwind *bas
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr);
U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr);
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module);
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 0);
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 1, 0);
RDI_Scope *scope = rdi_scope_from_voff(rdi, rip_voff);
// rjf: build inline frames (minus parent & inline depth)
@@ -3405,96 +3428,89 @@ ctrl_call_stack_from_thread(CTRL_Scope *scope, CTRL_EntityCtx *entity_ctx, CTRL_
//- rjf: loop: try to grab cached call stack; request; wait
//
B32 can_request = !ins_atomic_u64_eval(&ctrl_state->ctrl_thread_run_state);
B32 did_request = 0;
OS_MutexScopeR(stripe->rw_mutex)
for(U64 retry_idx = 0;; retry_idx += 1)
{
CTRL_CallStackCacheNode *taken_node = 0;
for(;;)
//- rjf: [read-only] try to look for current call stack; wait if working
B32 node_exists = 0;
B32 node_stale = 1;
B32 node_working = 0;
OS_MutexScopeR(stripe->rw_mutex) for(;;)
{
////////////////////////////
//- rjf: try to grab cached
//
B32 is_good = 0;
B32 is_stale = 1;
B32 is_working = 0;
CTRL_CallStackCacheNode *node = 0;
for(CTRL_CallStackCacheNode *n = slot->first; n != 0; n = n->next)
{
for(CTRL_CallStackCacheNode *n = slot->first; n != 0; n = n->next)
if(ctrl_handle_match(n->thread, handle))
{
if(ctrl_handle_match(n->thread, handle))
{
node = n;
is_good = 1;
is_stale = (reg_gen > n->reg_gen || mem_gen > n->mem_gen);
is_working = (n->working_count > 0);
call_stack = n->call_stack;
taken_node = node;
break;
}
node = n;
node_exists = 1;
node_stale = (reg_gen > n->reg_gen || mem_gen > n->mem_gen);
node_working = (n->working_count > 0);
break;
}
}
////////////////////////////
//- rjf: create node if needed
//
if(!is_good) OS_MutexScopeRWPromote(stripe->rw_mutex)
{
node = 0;
for(CTRL_CallStackCacheNode *n = slot->first; n != 0; n = n->next)
{
if(ctrl_handle_match(n->thread, handle))
{
node = n;
break;
}
}
if(node == 0)
{
node = push_array(stripe->arena, CTRL_CallStackCacheNode, 1);
DLLPushBack(slot->first, slot->last, node);
node->thread = thread->handle;
}
}
////////////////////////////
//- rjf: request if needed
//
if(can_request && node != 0 && !is_working && is_stale)
{
if(ctrl_u2csb_enqueue_req(thread->handle, endt_us))
{
did_request = 1;
is_working = 1;
ins_atomic_u64_inc_eval(&node->working_count);
async_push_work(ctrl_call_stack_build_work, .priority = high_priority ? ASYNC_Priority_High : ASYNC_Priority_Low);
}
}
////////////////////////////
//- rjf: good, or timeout? -> exit
//
if(!can_request || !is_stale || os_now_microseconds() >= endt_us)
if(node_exists && (!can_request || !node_stale || os_now_microseconds() >= endt_us))
{
call_stack = node->call_stack;
ctrl_scope_touch_call_stack_node__stripe_r_guarded(scope, stripe, node);
break;
}
////////////////////////////
//- rjf: time to wait for new result? -> wait
//
if(did_request && !is_working)
{
break;
}
else if(did_request)
else if(node_working)
{
os_condition_variable_wait_rw_r(stripe->cv, stripe->rw_mutex, endt_us);
}
else
{
break;
}
}
if(taken_node != 0)
//- rjf: out of time => exit
if(retry_idx > 0 && os_now_microseconds() >= endt_us)
{
ctrl_scope_touch_call_stack_node__stripe_r_guarded(scope, stripe, taken_node);
break;
}
//- rjf: [write] node does not exist => create; request if new or stale
B32 need_request = (!node_exists || node_stale);
CTRL_CallStackCacheNode *node_to_request = 0;
if(can_request && need_request) OS_MutexScopeW(stripe->rw_mutex)
{
CTRL_CallStackCacheNode *node = 0;
for(CTRL_CallStackCacheNode *n = slot->first; n != 0; n = n->next)
{
if(ctrl_handle_match(n->thread, handle))
{
node = n;
break;
}
}
if(node == 0)
{
node = push_array(stripe->arena, CTRL_CallStackCacheNode, 1);
DLLPushBack(slot->first, slot->last, node);
node->thread = thread->handle;
}
if(node->working_count == 0)
{
node->working_count += 1;
node_to_request = node;
}
}
//- rjf: request if needed
if(node_to_request != 0)
{
if(ctrl_u2csb_enqueue_req(thread->handle, endt_us))
{
async_push_work(ctrl_call_stack_build_work, .priority = high_priority ? ASYNC_Priority_High : ASYNC_Priority_Low);
}
else OS_MutexScopeW(stripe->rw_mutex)
{
node_to_request->working_count -= 1;
}
}
}
return call_stack;
}
@@ -3510,26 +3526,26 @@ ctrl_halt(void)
////////////////////////////////
//~ rjf: Shared Accessor Functions
//- rjf: run generation counter
//- rjf: generation counters
internal U64
ctrl_run_gen(void)
{
U64 result = dmn_run_gen();
U64 result = ins_atomic_u64_eval(&ctrl_state->run_gen);
return result;
}
internal U64
ctrl_mem_gen(void)
{
U64 result = dmn_mem_gen();
U64 result = ins_atomic_u64_eval(&ctrl_state->mem_gen);
return result;
}
internal U64
ctrl_reg_gen(void)
{
U64 result = dmn_reg_gen();
U64 result = ins_atomic_u64_eval(&ctrl_state->reg_gen);
return result;
}
@@ -3709,9 +3725,75 @@ ctrl_thread__entry_point(void *p)
log_infof("user2ctrl_msg:{kind:\"%S\"}\n", ctrl_string_from_msg_kind(msg->kind));
}
//- rjf: unpack per-message parameterizations & store
//- rjf: reset per-message state
arena_clear(ctrl_state->ctrl_thread_msg_process_arena);
ctrl_state->module_req_cache_slots_count = 1024;
ctrl_state->module_req_cache_slots = push_array(ctrl_state->ctrl_thread_msg_process_arena, CTRL_ModuleReqCacheNode *, ctrl_state->module_req_cache_slots_count);
MemoryZeroStruct(&ctrl_state->msg_user_bp_touched_files);
MemoryZeroStruct(&ctrl_state->msg_user_bp_touched_symbols);
MemoryCopyArray(ctrl_state->exception_code_filters, msg->exception_code_filters);
//- rjf: gather all touched symbols by user breakpoints
{
MemoryCopyArray(ctrl_state->exception_code_filters, msg->exception_code_filters);
Temp scratch = scratch_begin(0, 0);
for(CTRL_UserBreakpointNode *n = msg->user_bps.first; n != 0; n = n->next)
{
if(n->v.kind != CTRL_UserBreakpointKind_Expression)
{
continue;
}
E_Parse addr_parse = e_push_parse_from_string(scratch.arena, n->v.string);
E_Parse cnd_parse = e_push_parse_from_string(scratch.arena, n->v.condition);
E_Expr *exprs[] = {addr_parse.expr, cnd_parse.expr};
for EachElement(idx, exprs)
{
typedef struct ExprWalkTask ExprWalkTask;
struct ExprWalkTask
{
ExprWalkTask *next;
E_Expr *expr;
};
ExprWalkTask start_task = {0, exprs[idx]};
ExprWalkTask *first_task = &start_task;
for(ExprWalkTask *t = first_task; t != 0; t = t->next)
{
E_Expr *expr = t->expr;
if(expr->ref != &e_expr_nil)
{
expr = expr->ref;
}
if(expr->kind == E_ExprKind_LeafIdentifier)
{
str8_list_push(ctrl_state->ctrl_thread_msg_process_arena, &ctrl_state->msg_user_bp_touched_symbols, expr->string);
}
if(expr->next != &e_expr_nil)
{
ExprWalkTask *task = push_array(scratch.arena, ExprWalkTask, 1);
task->expr = expr->next;
task->next = t->next;
t->next = task;
}
if(expr->first != &e_expr_nil)
{
ExprWalkTask *task = push_array(scratch.arena, ExprWalkTask, 1);
task->expr = expr->first;
task->next = t->next;
t->next = task;
}
}
}
}
scratch_end(scratch);
}
//- rjf: gather all touched files by user breakpoints
for(CTRL_UserBreakpointNode *n = msg->user_bps.first; n != 0; n = n->next)
{
if(n->v.kind != CTRL_UserBreakpointKind_FileNameAndLineColNumber)
{
continue;
}
str8_list_push(ctrl_state->ctrl_thread_msg_process_arena, &ctrl_state->msg_user_bp_touched_files, n->v.string);
}
//- rjf: process message
@@ -3747,7 +3829,10 @@ ctrl_thread__entry_point(void *p)
CTRL_Entity *debug_info_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath);
DI_Key old_dbgi_key = {debug_info_path->string, debug_info_path->timestamp};
di_close(&old_dbgi_key);
OS_MutexScopeW(ctrl_state->ctrl_thread_entity_ctx_rw_mutex) ctrl_entity_equip_string(ctrl_state->ctrl_thread_entity_store, debug_info_path, path);
OS_MutexScopeW(ctrl_state->ctrl_thread_entity_ctx_rw_mutex)
{
ctrl_entity_equip_string(ctrl_state->ctrl_thread_entity_store, debug_info_path, path_normalized_from_string(scratch.arena, path));
}
U64 new_dbgi_timestamp = os_properties_from_file_path(path).modified;
debug_info_path->timestamp = new_dbgi_timestamp;
DI_Key new_dbgi_key = {debug_info_path->string, new_dbgi_timestamp};
@@ -3780,18 +3865,28 @@ ctrl_thread__entry_point(void *p)
}
ins_atomic_u64_eval_assign(&ctrl_state->ctrl_thread_run_state, 0);
}
ins_atomic_u64_inc_eval(&ctrl_state->run_gen);
ins_atomic_u64_inc_eval(&ctrl_state->mem_gen);
ins_atomic_u64_inc_eval(&ctrl_state->reg_gen);
//- rjf: update thread register cache
ProfScope("update thread register cache")
{
CTRL_EntityCtx *entity_ctx = &ctrl_state->ctrl_thread_entity_store->ctx;
CTRL_EntityArray threads = ctrl_entity_array_from_kind(entity_ctx, CTRL_EntityKind_Thread);
REGS_RegBlockX64 *blocks = push_array(scratch.arena, REGS_RegBlockX64, threads.count);
{
for EachIndex(idx, threads.count)
{
Temp scratch = scratch_begin(0, 0);
ctrl_reg_block_from_thread(scratch.arena, entity_ctx, threads.v[idx]->handle);
scratch_end(scratch);
}
}
}
//- rjf: gather & output logs
LogScopeResult log = log_scope_end(scratch.arena);
ctrl_thread__flush_info_log(log.strings[LogMsgKind_Info]);
if(log.strings[LogMsgKind_UserError].size != 0)
{
CTRL_EventList evts = {0};
CTRL_Event *evt = ctrl_event_list_push(scratch.arena, &evts);
evt->kind = CTRL_EventKind_Error;
evt->string = log.strings[LogMsgKind_UserError];
ctrl_c2u_push_events(&evts);
}
ctrl_thread__end_and_flush_log();
}
scratch_end(scratch);
@@ -3804,13 +3899,14 @@ 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)
{
if(user_bps->first == 0) { return; }
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
DI_Scope *di_scope = eval_scope->di_scope;
CTRL_EntityCtx *entity_ctx = &ctrl_state->ctrl_thread_entity_store->ctx;
CTRL_Entity *module_entity = ctrl_entity_from_handle(entity_ctx, module);
CTRL_Entity *debug_info_path_entity = ctrl_entity_child_from_kind(module_entity, CTRL_EntityKind_DebugInfoPath);
DI_Key dbgi_key = {debug_info_path_entity->string, debug_info_path_entity->timestamp};
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, max_U64);
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 1, 0);
U64 base_vaddr = module_entity->vaddr_range.min;
for(CTRL_UserBreakpointNode *n = user_bps->first; n != 0; n = n->next)
{
@@ -3854,6 +3950,7 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_EvalScope *
}
// rjf: src_id * pt -> push
if(src_id != 0)
{
RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id);
RDI_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx);
@@ -3875,7 +3972,7 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_EvalScope *
{
String8 expr = bp->string;
E_Value value = e_value_from_string(expr);
if(value.u64 != 0)
if(value.u64 != 0 || bp->flags != 0)
{
DMN_Trap trap = {process.dmn_handle, value.u64, (U64)bp};
trap.flags = ctrl_dmn_trap_flags_from_user_breakpoint_flags(bp->flags);
@@ -3886,6 +3983,7 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_EvalScope *
}
}
scratch_end(scratch);
ProfEnd();
}
internal void
@@ -3898,7 +3996,7 @@ ctrl_thread__append_resolved_process_user_bp_traps(Arena *arena, CTRL_EvalScope
{
String8 expr = bp->string;
E_Value value = e_value_from_string(expr);
if(value.u64 != 0)
if(value.u64 != 0 || bp->flags != 0)
{
DMN_Trap trap = {process.dmn_handle, value.u64, (U64)bp};
trap.flags = ctrl_dmn_trap_flags_from_user_breakpoint_flags(bp->flags);
@@ -3946,6 +4044,7 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
String8 rdi_dbg_path = str8_zero();
String8 raddbg_data = str8_zero();
Rng1U64 raddbg_section_voff_range = r1u64(0, 0);
Rng1U64 raddbg_is_attached_section_voff_range = r1u64(0, 0);
ProfScope("unpack relevant PE info")
{
B32 is_valid = 1;
@@ -4144,6 +4243,11 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
raddbg_section_voff_range.min = sec[idx].voff;
raddbg_section_voff_range.max = sec[idx].voff + sec[idx].vsize;
}
else if(str8_match(section_name, str8_lit(".rdbgia"), 0))
{
raddbg_is_attached_section_voff_range.min = sec[idx].voff;
raddbg_is_attached_section_voff_range.max = sec[idx].voff + sec[idx].vsize;
}
}
raddbg_data.size = dim_1u64(raddbg_section_voff_range);
raddbg_data.str = push_array(arena, U8, raddbg_data.size);
@@ -4152,11 +4256,11 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
scratch_end(scratch);
}
// rjf: if we have a raddbg section, mark the first byte as 1, to signify attachment
if(raddbg_section_voff_range.max != raddbg_section_voff_range.min)
// rjf: if we have a "raddbg is attached" section, mark the first byte as 1, to signify attachment
if(raddbg_is_attached_section_voff_range.max != raddbg_is_attached_section_voff_range.min)
{
U8 new_value = 1;
dmn_process_write_struct(process.dmn_handle, vaddr_range.min + raddbg_section_voff_range.min, &new_value);
dmn_process_write_struct(process.dmn_handle, vaddr_range.min + raddbg_is_attached_section_voff_range.min, &new_value);
}
}
}
@@ -4384,7 +4488,7 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg,
B32 asan_shadow_variable_exists_but_is_zero = 0;
CTRL_Entity *dbg_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath);
DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp};
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, max_U64);
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 1, max_U64);
RDI_NameMap *unparsed_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_GlobalVariables);
{
RDI_ParsedNameMap map = {0};
@@ -4494,6 +4598,9 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg,
}
}
DMN_EventList events = dmn_ctrl_run(scratch.arena, ctrl_ctx, run_ctrls);
ins_atomic_u64_inc_eval(&ctrl_state->mem_gen);
ins_atomic_u64_inc_eval(&ctrl_state->reg_gen);
ins_atomic_u64_inc_eval(&ctrl_state->run_gen);
for(DMN_EventNode *src_n = events.first; src_n != 0; src_n = src_n->next)
{
DMN_EventNode *dst_n = ctrl_state->free_dmn_event_node;
@@ -4613,6 +4720,7 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg,
out_evt->entity_id = event->code;
}break;
case DMN_EventKind_UnloadModule:
ProfScope("unload module %.*s", str8_varg(event->string))
{
CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts);
CTRL_Handle module_handle = ctrl_handle_make(CTRL_MachineID_Local, event->module);
@@ -4672,7 +4780,7 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg,
out_evt->msg_id = msg->msg_id;
out_evt->vaddr_rng = r1u64(event->address, event->address + event->size);
out_evt->string = event->string;
}
}break;
case DMN_EventKind_SetBreakpoint:
{
CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts);
@@ -4718,12 +4826,11 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg,
// modules (a very bad heuristic that may or may not inform us that we are
// dealing with insane-town projects)
//
if(event->kind == DMN_EventKind_LoadModule &&
if(0 &&
event->kind == DMN_EventKind_LoadModule &&
(entity_ctx->entity_kind_counts[CTRL_EntityKind_Module] > 256 ||
entity_ctx->entity_kind_counts[CTRL_EntityKind_Module] == 1))
{
U64 endt_us = os_now_microseconds() + 1000000;
//- rjf: unpack event
CTRL_Handle process_handle = ctrl_handle_make(CTRL_MachineID_Local, event->process);
CTRL_Handle loaded_module_handle = ctrl_handle_make(CTRL_MachineID_Local, event->module);
@@ -4867,6 +4974,14 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg,
DI_Key key = {push_str8f(scratch.arena, "%S/%S", t->path, info.name), info.props.modified};
di_open(&key);
di_key_list_push(scratch.arena, &preemptively_loaded_keys, &key);
if(preemptively_loaded_keys.count >= Max(1, async_thread_count()/2))
{
for(DI_KeyNode *n = preemptively_loaded_keys.first; n != 0; n = n->next)
{
di_close(&n->v);
}
MemoryZeroStruct(&preemptively_loaded_keys);
}
}
}
os_file_iter_end(it);
@@ -4874,16 +4989,6 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg,
}
}
}
//- rjf: for each pre-emptively loaded key, wait for the initial
// load task to be done
for(DI_KeyNode *n = preemptively_loaded_keys.first; n != 0; n = n->next)
{
DI_Scope *di_scope = di_scope_open();
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &n->v, endt_us);
di_scope_close(di_scope);
di_close(&n->v);
}
}
}
@@ -4970,7 +5075,7 @@ ctrl_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range)
//- rjf: control thread eval scopes
internal CTRL_EvalScope *
ctrl_thread__eval_scope_begin(Arena *arena, CTRL_Entity *thread)
ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, CTRL_Entity *thread)
{
CTRL_EntityCtx *entity_ctx = &ctrl_state->ctrl_thread_entity_store->ctx;
CTRL_EvalScope *scope = push_array(arena, CTRL_EvalScope, 1);
@@ -5012,8 +5117,96 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_Entity *thread)
if(mod->kind != CTRL_EntityKind_Module) { continue; }
CTRL_Entity *dbg_path = ctrl_entity_child_from_kind(mod, CTRL_EntityKind_DebugInfoPath);
DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp};
//- rjf: try to obtain this module's RDI
RDI_Parsed *rdi = di_rdi_from_key(scope->di_scope, &dbgi_key, 1, 0);
//- rjf: if this RDI is not yet ready => determine if we need to wait for it
//
// (we *always* wait for the initial module)
//
B32 rdi_is_necessary = 1;
if(rdi == &rdi_parsed_nil) ProfScope("determine if RDI is necessary")
{
// rjf: find cached result
U64 hash = ctrl_hash_from_handle(mod->handle);
U64 slot_idx = hash%ctrl_state->module_req_cache_slots_count;
CTRL_ModuleReqCacheNode *slot = ctrl_state->module_req_cache_slots[slot_idx];
CTRL_ModuleReqCacheNode *node = 0;
for(CTRL_ModuleReqCacheNode *n = slot; slot != 0; slot = slot->next)
{
if(ctrl_handle_match(n->module, mod->handle))
{
node = n;
break;
}
}
// rjf: cached? -> take cached result
if(node != 0)
{
rdi_is_necessary = node->required;
}
// rjf: not cached -> compute & store
else ProfScope("cache miss")
{
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, dbgi_key.path);
{
//- rjf: determine if file is PDB
B32 file_is_pdb = 0;
if(!file_is_pdb)
{
U8 msf70_magic_maybe[sizeof(msf_msf70_magic)] = {0};
os_file_read(file, r1u64(0, sizeof(msf70_magic_maybe)), msf70_magic_maybe);
if(MemoryMatch(msf70_magic_maybe, msf_msf70_magic, sizeof(msf70_magic_maybe)))
{
file_is_pdb = 1;
}
}
if(!file_is_pdb)
{
U8 msf20_magic_maybe[sizeof(msf_msf20_magic)] = {0};
os_file_read(file, r1u64(0, sizeof(msf20_magic_maybe)), msf20_magic_maybe);
if(MemoryMatch(msf20_magic_maybe, msf_msf20_magic, sizeof(msf20_magic_maybe)))
{
file_is_pdb = 1;
}
}
//- rjf: file is PDB -> do thin parse & lookup of all breakpoint files/symbols.
// if any are found in the PDB, then this RDI is necessary.
if(file_is_pdb)
{
FileProperties props = os_properties_from_file(file);
OS_Handle map = os_file_map_open(OS_AccessFlag_Read, file);
void *file_base = os_file_map_view_open(map, OS_AccessFlag_Read, r1u64(0, props.size));
String8 file_data = str8(file_base, props.size);
{
rdi_is_necessary = pdb_has_symbol_or_file_ref(file_data, ctrl_state->msg_user_bp_touched_symbols, ctrl_state->msg_user_bp_touched_files);
}
os_file_map_view_close(map, file_base, r1u64(0, props.size));
os_file_map_close(map);
}
}
os_file_close(file);
node = push_array(ctrl_state->ctrl_thread_msg_process_arena, CTRL_ModuleReqCacheNode, 1);
node->next = slot;
ctrl_state->module_req_cache_slots[slot_idx] = node;
node->module = mod->handle;
node->required = rdi_is_necessary;
}
}
//- rjf: if this RDI is necessary, but we do not have it => wait for it forever
if(rdi == &rdi_parsed_nil && rdi_is_necessary)
{
rdi = di_rdi_from_key(scope->di_scope, &dbgi_key, 1, max_U64);
}
//- rjf: fill evaluation module info
eval_modules[eval_module_idx].arch = arch;
eval_modules[eval_module_idx].rdi = di_rdi_from_key(scope->di_scope, &dbgi_key, max_U64);
eval_modules[eval_module_idx].rdi = rdi;
eval_modules[eval_module_idx].vaddr_range = mod->vaddr_range;
eval_modules[eval_module_idx].space = e_space_make(CTRL_EvalSpaceKind_Entity);
eval_modules[eval_module_idx].space.u64_0 = (U64)process;
@@ -5101,17 +5294,19 @@ ctrl_thread__eval_scope_end(CTRL_EvalScope *scope)
//- rjf: log flusher
internal void
ctrl_thread__flush_info_log(String8 string)
{
os_append_data_to_file_path(ctrl_state->ctrl_thread_log_path, string);
}
internal void
ctrl_thread__end_and_flush_info_log(void)
ctrl_thread__end_and_flush_log(void)
{
Temp scratch = scratch_begin(0, 0);
LogScopeResult log = log_scope_end(scratch.arena);
ctrl_thread__flush_info_log(log.strings[LogMsgKind_Info]);
os_append_data_to_file_path(ctrl_state->ctrl_thread_log_path, log.strings[LogMsgKind_Info]);
if(log.strings[LogMsgKind_UserError].size != 0)
{
CTRL_EventList evts = {0};
CTRL_Event *evt = ctrl_event_list_push(scratch.arena, &evts);
evt->kind = CTRL_EventKind_Error;
evt->string = log.strings[LogMsgKind_UserError];
ctrl_c2u_push_events(&evts);
}
scratch_end(scratch);
}
@@ -5447,7 +5642,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
DMN_TrapChunkList user_traps = {0};
{
CTRL_Entity *thread = ctrl_entity_from_handle(entity_ctx, target_thread);
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, thread);
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, &msg->user_bps, thread);
for(CTRL_Entity *machine = entity_ctx->root->first;
machine != &ctrl_entity_nil;
machine = machine->next)
@@ -5692,6 +5887,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
//- rjf: setup run controls
//
DMN_RunCtrls run_ctrls = {0};
run_ctrls.priority_thread = target_thread.dmn_handle;
run_ctrls.ignore_previous_exception = 1;
run_ctrls.run_entity_count = frozen_threads.count;
run_ctrls.run_entities = push_array(scratch.arena, DMN_Handle, run_ctrls.run_entity_count);
@@ -5739,7 +5935,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
}break;
case DMN_EventKind_CreateProcess:
{
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, &ctrl_entity_nil);
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, &msg->user_bps, &ctrl_entity_nil);
{
DMN_TrapChunkList new_traps = {0};
ctrl_thread__append_resolved_process_user_bp_traps(scratch.arena, eval_scope, ctrl_handle_make(CTRL_MachineID_Local, event->process), &msg->user_bps, &new_traps);
@@ -5762,7 +5958,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
case DMN_EventKind_LoadModule:
{
CTRL_Entity *thread = ctrl_entity_from_handle(entity_ctx, ctrl_handle_make(CTRL_MachineID_Local, event->thread));
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, thread);
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, &msg->user_bps, thread);
{
DMN_TrapChunkList new_traps = {0};
ctrl_thread__append_resolved_module_user_bp_traps(scratch.arena, eval_scope, ctrl_handle_make(CTRL_MachineID_Local, event->process), ctrl_handle_make(CTRL_MachineID_Local, event->module), &msg->user_bps, &new_traps);
@@ -5823,7 +6019,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
U64 module_base_vaddr = module->vaddr_range.min;
CTRL_Entity *dbg_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath);
DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp};
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, max_U64);
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 1, max_U64);
RDI_NameMap *unparsed_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures);
RDI_ParsedNameMap map = {0};
rdi_parsed_from_name_map(rdi, unparsed_map, &map);
@@ -6156,10 +6352,18 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
}
}
// rjf: programmatic user breakpoints (we do not have state for it,
// but the target program(s) did something breakpoint-like, and we
// want to treat it as if we did)
if(event->address != 0)
{
hit_user_bp = 1;
}
// rjf: evaluate hit stop conditions
if(conditions.node_count != 0) ProfScope("evaluate hit stop conditions")
{
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(temp.arena, thread);
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(temp.arena, &msg->user_bps, thread);
for(String8Node *condition_n = conditions.first; condition_n != 0; condition_n = condition_n->next)
{
// rjf: evaluate
@@ -6638,6 +6842,7 @@ ctrl_u2ms_dequeue_req(HS_Key *out_key, CTRL_Handle *out_process, Rng1U64 *out_va
ASYNC_WORK_DEF(ctrl_mem_stream_work)
{
#define CTRL_MEM_STREAM_WORK_DEBUG 0
ProfBeginFunction();
CTRL_ProcessMemoryCache *cache = &ctrl_state->process_memory_cache;
@@ -6673,7 +6878,12 @@ ASYNC_WORK_DEF(ctrl_mem_stream_work)
void *range_base = 0;
U64 zero_terminated_size = 0;
U64 pre_read_mem_gen = ctrl_mem_gen();
U64 post_read_mem_gen = 0;
B32 pre_run_state = ins_atomic_u64_eval(&ctrl_state->ctrl_thread_run_state);
#if CTRL_MEM_STREAM_WORK_DEBUG
Log *log = log_alloc();
log_select(log);
log_scope_begin();
#endif
{
range_size = dim_1u64(vaddr_range_clamped);
U64 page_size = os_get_system_info()->page_size;
@@ -6733,8 +6943,25 @@ ASYNC_WORK_DEF(ctrl_mem_stream_work)
}
}
}
post_read_mem_gen = dmn_mem_gen();
}
U64 post_read_mem_gen = ctrl_mem_gen();
B32 post_run_state = ins_atomic_u64_eval(&ctrl_state->ctrl_thread_run_state);
// NOTE(rjf): debugging
#if CTRL_MEM_STREAM_WORK_DEBUG
{
Temp scratch = scratch_begin(0, 0);
String8 sample_data_str = str8_lit("no data");
if(range_base != 0)
{
String8 sample_data = str8((U8*)range_base + 0x100, 16);
String8List sample_data_strs = numeric_str8_list_from_data(scratch.arena, 16, sample_data, 1);
sample_data_str = str8_list_join(scratch.arena, &sample_data_strs, &(StringJoin){.sep = str8_lit(", ")});
}
LogScopeResult log = log_scope_end(scratch.arena);
raddbg_log("[0x%I64x, 0x%I64x) { pre_gen: %I64u, post_gen: %I64u, pre_run: %i, post_run: %i, bytes: [%S], info:```%S``` }\n", vaddr_range.min, vaddr_range.max, pre_read_mem_gen, post_read_mem_gen, pre_run_state, post_run_state, sample_data_str, log.strings[LogMsgKind_Info]);
scratch_end(scratch);
}
#endif
//- rjf: read successful -> submit to hash store
U128 hash = {0};
@@ -6764,6 +6991,7 @@ ASYNC_WORK_DEF(ctrl_mem_stream_work)
{
range_n->mem_gen = post_read_mem_gen;
}
range_n->working_count -= 1;
goto commit__break_all;
}
}
+24 -4
View File
@@ -756,6 +756,17 @@ struct CTRL_TCTX
CTRL_ScopeCallStackTouch *free_call_stack_touch;
};
////////////////////////////////
//~ rjf: Module Requirement Cache Types
typedef struct CTRL_ModuleReqCacheNode CTRL_ModuleReqCacheNode;
struct CTRL_ModuleReqCacheNode
{
CTRL_ModuleReqCacheNode *next;
CTRL_Handle module;
B32 required;
};
////////////////////////////////
//~ rjf: Wakeup Hook Function Types
@@ -781,6 +792,11 @@ struct CTRL_State
CTRL_CallStackCache call_stack_cache;
CTRL_ModuleImageInfoCache module_image_info_cache;
// rjf: generations
U64 run_gen;
U64 mem_gen;
U64 reg_gen;
// rjf: user -> ctrl msg ring buffer
U64 u2c_ring_size;
U8 *u2c_ring_base;
@@ -806,6 +822,7 @@ struct CTRL_State
OS_Handle ctrl_thread_entity_ctx_rw_mutex;
CTRL_EntityCtxRWStore *ctrl_thread_entity_store;
E_Cache *ctrl_thread_eval_cache;
Arena *ctrl_thread_msg_process_arena;
Arena *dmn_event_arena;
DMN_EventNode *first_dmn_event_node;
DMN_EventNode *last_dmn_event_node;
@@ -816,6 +833,10 @@ struct CTRL_State
U64 process_counter;
Arena *dbg_dir_arena;
CTRL_DbgDirNode *dbg_dir_root;
U64 module_req_cache_slots_count;
CTRL_ModuleReqCacheNode **module_req_cache_slots;
String8List msg_user_bp_touched_files;
String8List msg_user_bp_touched_symbols;
// rjf: user -> memstream ring buffer
U64 u2ms_ring_size;
@@ -852,7 +873,7 @@ thread_static CTRL_EntityCtxLookupAccel *ctrl_entity_ctx_lookup_accel = 0;
////////////////////////////////
//~ rjf: Logging Markup
#define CTRL_CtrlThreadLogScope DeferLoop(log_scope_begin(), ctrl_thread__end_and_flush_info_log())
#define CTRL_CtrlThreadLogScope DeferLoop(log_scope_begin(), ctrl_thread__end_and_flush_log())
////////////////////////////////
//~ rjf: Basic Type Functions
@@ -1099,12 +1120,11 @@ internal DMN_Event *ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_
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 CTRL_EvalScope *ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, 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);
internal void ctrl_thread__end_and_flush_log(void);
//- rjf: msg kind implementations
internal void ctrl_thread__launch(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg);
+1 -1
View File
@@ -533,7 +533,7 @@ ASYNC_WORK_DEF(dasm_parse_work)
RDI_Parsed *rdi = &rdi_parsed_nil;
if(params.dbgi_key.path.size != 0)
{
rdi = di_rdi_from_key(di_scope, &params.dbgi_key, max_U64);
rdi = di_rdi_from_key(di_scope, &params.dbgi_key, 1, max_U64);
}
//- rjf: hash -> data
+1
View File
@@ -65,6 +65,7 @@ D_CmdTable: // | | | |
@table(name)
D_DevToggleTable:
{
{always_refresh}
{simulate_lag}
{draw_ui_text_pos}
{draw_ui_focus_debug}
+10 -10
View File
@@ -475,7 +475,7 @@ d_trap_net_from_thread__step_over_line(Arena *arena, CTRL_Entity *thread)
}
// rjf: push trap for natural linear flow
if(good_line_info)
if(good_line_info && good_machine_code)
{
CTRL_Trap trap = {CTRL_TrapFlag_EndStepping, line_vaddr_rng.max};
ctrl_trap_list_push(arena, &result, &trap);
@@ -631,7 +631,7 @@ d_trap_net_from_thread__step_into_line(Arena *arena, CTRL_Entity *thread)
}
// rjf: push trap for natural linear flow
if(good_line_info)
if(good_line_info && good_machine_code)
{
CTRL_Trap trap = {CTRL_TrapFlag_EndStepping, line_vaddr_rng.max};
ctrl_trap_list_push(arena, &result, &trap);
@@ -654,7 +654,7 @@ d_voff_from_dbgi_key_symbol_name(DI_Key *dbgi_key, String8 symbol_name)
DI_Scope *scope = di_scope_open();
U64 result = 0;
{
RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 0);
RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 1, 0);
RDI_NameMapKind name_map_kinds[] =
{
RDI_NameMapKind_GlobalVariables,
@@ -734,7 +734,7 @@ d_lines_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff)
{
Temp scratch = scratch_begin(&arena, 1);
DI_Scope *scope = di_scope_open();
RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 0);
RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 1, 0);
D_LineList result = {0};
{
//- rjf: gather line tables
@@ -843,7 +843,7 @@ d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key,
String8 file_path_normalized = lower_from_str8(scratch.arena, path_normalized_from_string(scratch.arena, file_path));
// rjf: binary -> rdi
RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0);
RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 1, 0);
// rjf: file_path_normalized * rdi -> src_id
B32 good_src_id = 0;
@@ -941,7 +941,7 @@ d_lines_array_from_file_path_line_range(Arena *arena, String8 file_path, Rng1S64
{
// rjf: binary -> rdi
DI_Key key = dbgi_key_n->v;
RDI_Parsed *rdi = di_rdi_from_key(scope, &key, 0);
RDI_Parsed *rdi = di_rdi_from_key(scope, &key, 1, 0);
// rjf: file_path_normalized * rdi -> src_id
B32 good_src_id = 0;
@@ -1302,7 +1302,7 @@ d_query_cached_locals_map_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff)
if(node == 0)
{
DI_Scope *scope = di_scope_open();
RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 0);
RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 1, 0);
E_String2NumMap *map = e_push_locals_map_from_rdi_voff(cache->arena, rdi, voff);
if(map->slots_count != 0)
{
@@ -1356,7 +1356,7 @@ d_query_cached_member_map_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff)
if(node == 0)
{
DI_Scope *scope = di_scope_open();
RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 0);
RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 1, 0);
E_String2NumMap *map = e_push_member_map_from_rdi_voff(cache->arena, rdi, voff);
if(map->slots_count != 0)
{
@@ -1843,7 +1843,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_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, params->thread);
}
else
{
@@ -1970,7 +1970,7 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
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);
d_cmd(D_CmdKind_Continue, .machine = params->machine, .process = params->process, .thread = params->thread);
}
else if(!d_ctrl_targets_running())
{
@@ -44,6 +44,7 @@ D_CmdKind_Attach,
D_CmdKind_COUNT,
} D_CmdKind;
global B32 DEV_always_refresh = 0;
global B32 DEV_simulate_lag = 0;
global B32 DEV_draw_ui_text_pos = 0;
global B32 DEV_draw_ui_focus_debug = 0;
@@ -54,6 +55,7 @@ global B32 DEV_cmd_context_tooltips = 0;
global B32 DEV_updating_indicator = 0;
struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] =
{
{&DEV_always_refresh, str8_lit_comp("always_refresh")},
{&DEV_simulate_lag, str8_lit_comp("simulate_lag")},
{&DEV_draw_ui_text_pos, str8_lit_comp("draw_ui_text_pos")},
{&DEV_draw_ui_focus_debug, str8_lit_comp("draw_ui_focus_debug")},
+112 -38
View File
@@ -462,25 +462,24 @@ di_open(DI_Key *key)
Temp scratch = scratch_begin(0, 0);
if(key->path.size != 0)
{
DI_Key key_normalized = di_normalized_key_from_key(scratch.arena, key);
U64 hash = di_hash_from_key(&key_normalized);
U64 hash = di_hash_from_key(key);
U64 slot_idx = hash%di_shared->slots_count;
U64 stripe_idx = slot_idx%di_shared->stripes_count;
DI_Slot *slot = &di_shared->slots[slot_idx];
DI_Stripe *stripe = &di_shared->stripes[stripe_idx];
log_infof("open_debug_info: {\"%S\", 0x%I64x}\n", key_normalized.path, key_normalized.min_timestamp);
log_infof("open_debug_info: {\"%S\", 0x%I64x}\n", key->path, key->min_timestamp);
OS_MutexScopeW(stripe->rw_mutex)
{
//- rjf: find existing node
DI_Node *node = di_node_from_key_slot__stripe_mutex_r_guarded(slot, &key_normalized);
DI_Node *node = di_node_from_key_slot__stripe_mutex_r_guarded(slot, key);
//- rjf: allocate node if none exists; insert into slot
if(node == 0)
{
U64 current_timestamp = os_properties_from_file_path(key_normalized.path).modified;
U64 current_timestamp = os_properties_from_file_path(key->path).modified;
if(current_timestamp == 0)
{
current_timestamp = key_normalized.min_timestamp;
current_timestamp = key->min_timestamp;
}
node = stripe->free_node;
if(node != 0)
@@ -493,7 +492,7 @@ di_open(DI_Key *key)
}
MemoryZeroStruct(node);
DLLPushBack(slot->first, slot->last, node);
String8 path_stored = di_string_alloc__stripe_mutex_w_guarded(stripe, key_normalized.path);
String8 path_stored = di_string_alloc__stripe_mutex_w_guarded(stripe, key->path);
node->key.path = path_stored;
node->key.min_timestamp = current_timestamp;
}
@@ -504,7 +503,7 @@ di_open(DI_Key *key)
node->ref_count += 1;
if(node->ref_count == 1)
{
di_u2p_enqueue_key(&key_normalized, max_U64);
di_u2p_enqueue_key(key, max_U64);
ins_atomic_u64_eval_assign(&node->is_working, 1);
DeferLoop(os_rw_mutex_drop_w(stripe->rw_mutex), os_rw_mutex_take_w(stripe->rw_mutex))
{
@@ -524,18 +523,16 @@ di_close(DI_Key *key)
Temp scratch = scratch_begin(0, 0);
if(key->path.size != 0)
{
DI_Key key_normalized = di_normalized_key_from_key(scratch.arena, key);
U64 hash = di_hash_from_key(&key_normalized);
U64 hash = di_hash_from_key(key);
U64 slot_idx = hash%di_shared->slots_count;
U64 stripe_idx = slot_idx%di_shared->stripes_count;
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;
log_infof("close_debug_info: {\"%S\", 0x%I64x}\n", key->path, key->min_timestamp);
OS_MutexScopeW(stripe->rw_mutex)
{
//- rjf: find existing node
DI_Node *node = di_node_from_key_slot__stripe_mutex_r_guarded(slot, &key_normalized);
DI_Node *node = di_node_from_key_slot__stripe_mutex_r_guarded(slot, key);
//- rjf: node exists -> decrement reference count; release
if(node != 0)
@@ -568,7 +565,7 @@ di_close(DI_Key *key)
break;
}
//- rjf: wait for touch count to go to 0
//- rjf: wait for touch count / working marker to go to 0
os_condition_variable_wait_rw_w(stripe->cv, stripe->rw_mutex, max_U64);
}
}
@@ -582,15 +579,14 @@ di_close(DI_Key *key)
//~ rjf: Debug Info Cache Lookups
internal RDI_Parsed *
di_rdi_from_key(DI_Scope *scope, DI_Key *key, U64 endt_us)
di_rdi_from_key(DI_Scope *scope, DI_Key *key, B32 high_priority, U64 endt_us)
{
ProfBeginFunction();
RDI_Parsed *result = &rdi_parsed_nil;
if(key->path.size != 0)
{
Temp scratch = scratch_begin(0, 0);
DI_Key key_normalized = di_normalized_key_from_key(scratch.arena, key);
U64 hash = di_hash_from_key(&key_normalized);
U64 hash = di_hash_from_key(key);
U64 slot_idx = hash%di_shared->slots_count;
U64 stripe_idx = slot_idx%di_shared->stripes_count;
DI_Slot *slot = &di_shared->slots[slot_idx];
@@ -598,7 +594,7 @@ di_rdi_from_key(DI_Scope *scope, DI_Key *key, U64 endt_us)
ProfScope("grab node") OS_MutexScopeR(stripe->rw_mutex) for(;;)
{
//- rjf: find existing node
DI_Node *node = di_node_from_key_slot__stripe_mutex_r_guarded(slot, &key_normalized);
DI_Node *node = di_node_from_key_slot__stripe_mutex_r_guarded(slot, key);
//- rjf: no node? this path is not opened
if(node == 0)
@@ -624,14 +620,14 @@ di_rdi_from_key(DI_Scope *scope, DI_Key *key, U64 endt_us)
if(node != 0 &&
!node->parse_done &&
!ins_atomic_u64_eval(&node->is_working) &&
di_u2p_enqueue_key(&key_normalized, endt_us))
di_u2p_enqueue_key(key, endt_us))
{
ProfScope("ask for parse")
{
ins_atomic_u64_eval_assign(&node->is_working, 1);
DeferLoop(os_rw_mutex_drop_r(stripe->rw_mutex), os_rw_mutex_take_r(stripe->rw_mutex))
{
async_push_work(di_parse_work);
async_push_work(di_parse_work, .priority = high_priority ? ASYNC_Priority_High : ASYNC_Priority_Low);
}
}
}
@@ -1129,6 +1125,16 @@ ASYNC_WORK_DEF(di_parse_work)
node->rdi = rdi_parsed;
node->parse_done = 1;
}
else
{
if(rdi_parsed_arena != 0)
{
arena_release(rdi_parsed_arena);
}
os_file_map_view_close(file_map, file_base, r1u64(0, file_props.size));
os_file_map_close(file_map);
os_file_close(file);
}
}
os_condition_variable_broadcast(stripe->cv);
@@ -1253,6 +1259,10 @@ ASYNC_WORK_DEF(di_search_work)
{
// NOTE(rjf): name must be determined from self_type_idx
}break;
case RDI_SectionKind_SourceFiles:
{
// NOTE(rjf): name must be determined from file path node chain
}break;
}
//- rjf: loop through table, gather matches
@@ -1281,17 +1291,42 @@ ASYNC_WORK_DEF(di_search_work)
//- rjf: get element, map to string; if empty, continue to next element
void *element = (U8 *)table_base + element_size*idx;
U32 *name_idx_ptr = (U32 *)((U8 *)element + element_name_idx_off);
if(in->section_kind == RDI_SectionKind_UDTs)
String8 name = {0};
switch(in->section_kind)
{
RDI_UDT *udt = (RDI_UDT *)element;
RDI_TypeNode *type_node = rdi_element_from_name_idx(in->rdi, TypeNodes, udt->self_type_idx);
name_idx_ptr = &type_node->user_defined.name_string_idx;
case RDI_SectionKind_UDTs:
{
RDI_UDT *udt = (RDI_UDT *)element;
RDI_TypeNode *type_node = rdi_element_from_name_idx(in->rdi, TypeNodes, udt->self_type_idx);
name.str = rdi_string_from_idx(in->rdi, type_node->user_defined.name_string_idx, &name.size);
name = str8_copy(arena, name);
}break;
case RDI_SectionKind_SourceFiles:
{
Temp scratch = scratch_begin(&arena, 1);
RDI_SourceFile *file = (RDI_SourceFile *)element;
String8List path_parts = {0};
for(RDI_FilePathNode *fpn = rdi_element_from_name_idx(in->rdi, FilePathNodes, file->file_path_node_idx);
fpn != rdi_element_from_name_idx(in->rdi, FilePathNodes, 0);
fpn = rdi_element_from_name_idx(in->rdi, FilePathNodes, fpn->parent_path_node))
{
String8 path_part = {0};
path_part.str = rdi_string_from_idx(in->rdi, fpn->name_string_idx, &path_part.size);
str8_list_push_front(scratch.arena, &path_parts, path_part);
}
StringJoin join = {0};
join.sep = str8_lit("/");
name = str8_list_join(arena, &path_parts, &join);
scratch_end(scratch);
}break;
default:
{
U32 name_idx = *(U32 *)((U8 *)element + element_name_idx_off);
U64 name_size = 0;
U8 *name_base = rdi_string_from_idx(in->rdi, name_idx, &name_size);
name = str8(name_base, name_size);
}break;
}
U32 name_idx = *name_idx_ptr;
U64 name_size = 0;
U8 *name_base = rdi_string_from_idx(in->rdi, name_idx, &name_size);
String8 name = str8(name_base, name_size);
if(name.size == 0) { continue; }
//- rjf: fuzzy match against query
@@ -1313,7 +1348,7 @@ ASYNC_WORK_DEF(di_search_work)
chunk->v[chunk->count].idx = idx;
chunk->v[chunk->count].dbgi_idx = in->dbgi_idx;
chunk->v[chunk->count].match_ranges = matches;
chunk->v[chunk->count].missed_size = (name_size > matches.total_dim) ? (name_size-matches.total_dim) : 0;
chunk->v[chunk->count].missed_size = (name.size > matches.total_dim) ? (name.size-matches.total_dim) : 0;
chunk->count += 1;
out->items.total_count += 1;
}
@@ -1392,7 +1427,7 @@ di_search_thread__entry_point(void *p)
RDI_Parsed **rdis = push_array(scratch.arena, RDI_Parsed *, rdis_count);
for EachIndex(idx, rdis_count)
{
rdis[idx] = di_rdi_from_key(di_scope, &params.dbgi_keys.v[idx], max_U64);
rdis[idx] = di_rdi_from_key(di_scope, &params.dbgi_keys.v[idx], 1, max_U64);
}
//- rjf: kick off search tasks
@@ -1584,6 +1619,10 @@ di_match_store_alloc(void)
store->u2m_ring_mutex = os_mutex_alloc();
store->u2m_ring_size = KB(2);
store->u2m_ring_base = push_array_no_zero(arena, U8, store->u2m_ring_size);
store->m2u_ring_cv = os_condition_variable_alloc();
store->m2u_ring_mutex = os_mutex_alloc();
store->m2u_ring_size = KB(2);
store->m2u_ring_base = push_array_no_zero(arena, U8, store->m2u_ring_size);
return store;
}
@@ -1632,13 +1671,22 @@ di_match_store_begin(DI_MatchStore *store, DI_KeyArray keys)
}
}
// rjf: pop new matches
#if 0
for(;;)
{
U64 unconsumed_size = store->m2u_ring_write_pos - store->m2u_ring_read_pos;
}
#endif
ProfEnd();
}
internal RDI_SectionKind
di_match_store_section_kind_from_name(DI_MatchStore *store, String8 name, U64 endt_us)
internal DI_Match
di_match_from_name(DI_MatchStore *store, String8 name, U64 endt_us)
{
RDI_SectionKind result = 0;
DI_Match result = {0};
if(name.size != 0)
{
// rjf: unpack name
U64 hash = di_hash_from_string(name, 0);
@@ -1737,7 +1785,12 @@ di_match_store_section_kind_from_name(DI_MatchStore *store, String8 name, U64 en
}
// rjf: return node present info
result = node->section_kind;
result = node->primary_match;
if(node->cmp_params_hash != store->params_hash)
{
result.dbgi_idx = 0;
result.idx = 0;
}
}
return result;
}
@@ -1777,11 +1830,18 @@ ASYNC_WORK_DEF(di_match_work)
params_hash = store->params_hash;
}
//- rjf: do match
//- rjf: zero match info
ins_atomic_u64_eval_assign(&node->primary_match.dbgi_idx, 0);
ins_atomic_u32_eval_assign(&node->primary_match.idx, 0);
//- rjf: gather matches
DI_MatchNode *first_match = 0;
DI_MatchNode *last_match = 0;
RDI_NameMapKind name_map_kinds[] =
{
RDI_NameMapKind_GlobalVariables,
RDI_NameMapKind_ThreadVariables,
RDI_NameMapKind_Constants,
RDI_NameMapKind_Procedures,
RDI_NameMapKind_Types,
};
@@ -1789,6 +1849,7 @@ ASYNC_WORK_DEF(di_match_work)
{
RDI_SectionKind_GlobalVariables,
RDI_SectionKind_ThreadVariables,
RDI_SectionKind_Constants,
RDI_SectionKind_Procedures,
RDI_SectionKind_TypeNodes,
};
@@ -1798,7 +1859,7 @@ ASYNC_WORK_DEF(di_match_work)
{
DI_Scope *di_scope = di_scope_open();
DI_Key key = params_keys.v[dbgi_idx];
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &key, os_now_microseconds()+1000);
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &key, 1, os_now_microseconds()+1000);
for EachElement(name_map_kind_idx, name_map_kinds)
{
RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, name_map_kinds[name_map_kind_idx]);
@@ -1809,7 +1870,20 @@ ASYNC_WORK_DEF(di_match_work)
U32 *run = rdi_matches_from_map_node(rdi, map_node, &num);
if(num != 0)
{
ins_atomic_u32_eval_assign(&node->section_kind, name_map_section_kinds[name_map_kind_idx]);
// rjf: atomically update the node's primary match
ins_atomic_u64_eval_assign(&node->primary_match.dbgi_idx, dbgi_idx);
ins_atomic_u32_eval_assign(&node->primary_match.section, name_map_section_kinds[name_map_kind_idx]);
ins_atomic_u32_eval_assign(&node->primary_match.idx, run[0]);
// rjf: gather all alternate matches
for(U32 match_idx = 1; match_idx < num; match_idx += 1)
{
DI_MatchNode *m = push_array(scratch.arena, DI_MatchNode, 1);
SLLQueuePush(first_match, last_match, m);
m->v.dbgi_idx = dbgi_idx;
m->v.section = name_map_section_kinds[name_map_kind_idx];
m->v.idx = run[match_idx];
}
}
}
di_scope_close(di_scope);
+20 -7
View File
@@ -263,13 +263,18 @@ struct DI_SearchThread
typedef struct DI_Match DI_Match;
struct DI_Match
{
DI_Match *next;
DI_Match *prev;
U64 dbgi_idx;
RDI_SectionKind section;
U32 idx;
};
typedef struct DI_MatchNode DI_MatchNode;
struct DI_MatchNode
{
DI_MatchNode *next;
DI_Match v;
};
typedef struct DI_MatchNameNode DI_MatchNameNode;
struct DI_MatchNameNode
{
@@ -289,9 +294,9 @@ struct DI_MatchNameNode
// rjf: atomically written by match work
U64 cmp_count;
U64 cmp_params_hash;
RDI_SectionKind section_kind;
// DI_Match *first_match;
// DI_Match *last_match;
DI_Match primary_match;
// DI_MatchNode *first_alt_match;
// DI_MatchNode *last_alt_match;
};
typedef struct DI_MatchNameSlot DI_MatchNameSlot;
@@ -332,6 +337,14 @@ struct DI_MatchStore
U8 *u2m_ring_base;
U64 u2m_ring_write_pos;
U64 u2m_ring_read_pos;
// rjf: match -> user work ring buffer
OS_Handle m2u_ring_cv;
OS_Handle m2u_ring_mutex;
U64 m2u_ring_size;
U8 *m2u_ring_base;
U64 m2u_ring_write_pos;
U64 m2u_ring_read_pos;
};
////////////////////////////////
@@ -435,7 +448,7 @@ internal void di_close(DI_Key *key);
////////////////////////////////
//~ rjf: Debug Info Cache Lookups
internal RDI_Parsed *di_rdi_from_key(DI_Scope *scope, DI_Key *key, U64 endt_us);
internal RDI_Parsed *di_rdi_from_key(DI_Scope *scope, DI_Key *key, B32 high_priority, U64 endt_us);
////////////////////////////////
//~ rjf: Search Cache Lookups
@@ -470,7 +483,7 @@ internal void di_search_evictor_thread__entry_point(void *p);
internal DI_MatchStore *di_match_store_alloc(void);
internal void di_match_store_begin(DI_MatchStore *store, DI_KeyArray keys);
internal RDI_SectionKind di_match_store_section_kind_from_name(DI_MatchStore *store, String8 name, U64 endt_us);
internal DI_Match di_match_from_name(DI_MatchStore *store, String8 name, U64 endt_us);
ASYNC_WORK_DEF(di_match_work);
#endif // DBGI_H
+1 -5
View File
@@ -139,6 +139,7 @@ struct DMN_TrapChunkList
typedef struct DMN_RunCtrls DMN_RunCtrls;
struct DMN_RunCtrls
{
DMN_Handle priority_thread;
DMN_Handle single_step_thread;
B8 ignore_previous_exception;
B8 run_entities_are_unfrozen;
@@ -221,11 +222,6 @@ internal void dmn_halt(U64 code, U64 user_data);
////////////////////////////////
//~ rjf: @dmn_os_hooks Introspection Functions (Implemented Per-OS)
//- rjf: run/memory/register counters
internal U64 dmn_run_gen(void);
internal U64 dmn_mem_gen(void);
internal U64 dmn_reg_gen(void);
//- rjf: non-blocking-control-thread access barriers
internal B32 dmn_access_open(void);
internal void dmn_access_close(void);
File diff suppressed because it is too large Load Diff
+330
View File
@@ -4,4 +4,334 @@
#ifndef DEMON_CORE_LINUX_H
#define DEMON_CORE_LINUX_H
////////////////////////////////
//~ rjf: Includes
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/uio.h>
#include <unistd.h>
#include <elf.h>
#include <dirent.h>
#include <errno.h>
////////////////////////////////
//~ rjf: ptrace options
#define DMN_LNX_PTRACE_OPTIONS (PTRACE_O_TRACEEXIT|\
PTRACE_O_EXITKILL|\
PTRACE_O_TRACEFORK|\
PTRACE_O_TRACEVFORK|\
PTRACE_O_TRACECLONE)
////////////////////////////////
//~ rjf: Register Layouts
//
// These are defined in <sys/user.h>, but only for one architecture at a time
#pragma pack(push, 1)
typedef struct DMN_LNX_UserRegsX64 DMN_LNX_UserRegsX64;
struct DMN_LNX_UserRegsX64
{
U64 r15;
U64 r14;
U64 r13;
U64 r12;
U64 rbp;
U64 rbx;
U64 r11;
U64 r10;
U64 r9;
U64 r8;
U64 rax;
U64 rcx;
U64 rdx;
U64 rsi;
U64 rdi;
U64 orig_rax;
U64 rip;
U64 cs;
U64 rflags;
U64 rsp;
U64 ss;
U64 fsbase;
U64 gsbase;
U64 ds;
U64 es;
U64 fs;
U64 gs;
};
typedef struct DMN_LNX_XSaveLegacy DMN_LNX_XSaveLegacy;
struct DMN_LNX_XSaveLegacy
{
U16 fcw;
U16 fsw;
U16 ftw;
U16 fop;
union
{
struct
{
U64 fip;
U64 fdp;
} b64;
struct
{
U32 fip;
U16 fcs, _pad0;
U32 fdp;
U16 fds, _pad1;
} b32;
};
U32 mxcsr;
U32 mxcsr_mask;
U128 st_space;
U256 xmm_space;
U8 padding[96];
};
typedef struct DMN_LNX_XSaveHeader DMN_LNX_XSaveHeader;
struct DMN_LNX_XSaveHeader
{
U64 xstate_bv;
U64 xcomp_bv;
U8 reserved[48];
};
// TODO(rjf):
//
// this one is hacked; ymmh is not gauranteed to be at a fixed location
// and there can be more after that. Requires CPUID to be totally compliant to the standard.
// See intel's manual on the xsave format for more info.
//
typedef struct DMN_LNX_XSave DMN_LNX_XSave;
struct DMN_LNX_XSave
{
DMN_LNX_XSaveLegacy legacy;
DMN_LNX_XSaveHeader header;
U8 ymmh[256];
};
typedef struct DMN_LNX_UserX64 DMN_LNX_UserX64;
struct DMN_LNX_UserX64
{
DMN_LNX_UserRegsX64 regs;
S32 u_fpvalid, _pad0;
DMN_LNX_XSaveLegacy i387;
U64 u_tsize, u_dsize, u_ssize, start_code, start_stack;
U64 signal;
S32 reserved, _pad1;
U64 u_ar0, u_fpstate;
U64 magic;
U8 u_comm[32];
U64 u_debugreg[8];
};
typedef struct DMN_LNX_UserRegsX86 DMN_LNX_UserRegsX86;
struct DMN_LNX_UserRegsX86
{
U32 ebx;
U32 ecx;
U32 edx;
U32 esi;
U32 edi;
U32 ebp;
U32 eax;
U32 ds;
U32 es;
U32 fs;
U32 gs;
U32 orig_eax;
U32 eip;
U32 cs;
U32 eflags;
U32 sp;
U32 ss;
};
// NOTE(rjf): (32-Bit Protected Mode Format)
typedef struct DMN_LNX_FSave DMN_LNX_FSave;
struct DMN_LNX_FSave
{
// control registers
U16 fcw;
U16 _pad0;
U16 fsw;
U16 _pad1;
U16 ftw;
U16 _pad2;
U32 fip;
U16 fips;
U16 fop;
U32 fdp;
U16 fds;
U16 _pad3;
// data registers
U8 st[80];
};
typedef struct DMN_LNX_UserX86 DMN_LNX_UserX86;
struct DMN_LNX_UserX86
{
DMN_LNX_UserRegsX86 regs;
S32 u_fpvalid;
DMN_LNX_FSave i387;
U32 u_tsize, u_dsize, u_ssize, start_code, start_stack;
S32 signal, reserved;
U32 u_ar0, u_fpstate;
U32 magic;
U8 u_comm[32];
U32 u_debugreg[8];
};
#pragma pack(pop)
////////////////////////////////
//~ rjf: Process Info Extraction Types
typedef struct DMN_LNX_ProcessAux DMN_LNX_ProcessAux;
struct DMN_LNX_ProcessAux
{
B32 filled;
U64 phnum;
U64 phent;
U64 phdr;
U64 execfn;
U64 pagesz;
};
typedef struct DMN_LNX_PhdrInfo DMN_LNX_PhdrInfo;
struct DMN_LNX_PhdrInfo
{
Rng1U64 range;
U64 dynamic;
};
typedef struct DMN_LNX_ModuleInfo DMN_LNX_ModuleInfo;
struct DMN_LNX_ModuleInfo
{
Rng1U64 vaddr_range;
U64 name;
};
typedef struct DMN_LNX_ModuleInfoNode DMN_LNX_ModuleInfoNode;
struct DMN_LNX_ModuleInfoNode
{
DMN_LNX_ModuleInfoNode *next;
DMN_LNX_ModuleInfo v;
};
typedef struct DMN_LNX_ModuleInfoList DMN_LNX_ModuleInfoList;
struct DMN_LNX_ModuleInfoList
{
DMN_LNX_ModuleInfoNode *first;
DMN_LNX_ModuleInfoNode *last;
U64 count;
};
////////////////////////////////
//~ rjf: Entity Types
typedef enum DMN_LNX_EntityKind
{
DMN_LNX_EntityKind_Null,
DMN_LNX_EntityKind_Root,
DMN_LNX_EntityKind_Process,
DMN_LNX_EntityKind_Thread,
DMN_LNX_EntityKind_Module,
DMN_LNX_EntityKind_COUNT
}
DMN_LNX_EntityKind;
typedef struct DMN_LNX_Entity DMN_LNX_Entity;
struct DMN_LNX_Entity
{
DMN_LNX_Entity *first;
DMN_LNX_Entity *last;
DMN_LNX_Entity *next;
DMN_LNX_Entity *prev;
DMN_LNX_Entity *parent;
DMN_LNX_EntityKind kind;
U32 gen;
Arch arch;
U64 id;
int fd;
B32 expecting_dummy_sigstop;
};
typedef struct DMN_LNX_EntityNode DMN_LNX_EntityNode;
struct DMN_LNX_EntityNode
{
DMN_LNX_EntityNode *next;
DMN_LNX_Entity *v;
};
////////////////////////////////
//~ rjf: Main State Bundle
typedef struct DMN_LNX_State DMN_LNX_State;
struct DMN_LNX_State
{
Arena *arena;
// rjf: access locking mechanism
OS_Handle access_mutex;
B32 access_run_state;
// rjf: deferred events
Arena *deferred_events_arena;
DMN_EventList deferred_events;
// rjf: entity storage
Arena *entities_arena;
DMN_LNX_Entity *entities_base;
U64 entities_count;
DMN_LNX_Entity *free_entity;
// rjf: halting mechanism
B32 has_halt_injection;
U64 halt_code;
U64 halt_user_data;
};
read_only global DMN_LNX_Entity dmn_lnx_nil_entity = {&dmn_lnx_nil_entity, &dmn_lnx_nil_entity, &dmn_lnx_nil_entity, &dmn_lnx_nil_entity, &dmn_lnx_nil_entity};
global DMN_LNX_State *dmn_lnx_state = 0;
thread_static B32 dmn_lnx_ctrl_thread = 0;
////////////////////////////////
//~ rjf: Helpers
//- rjf: file descriptor memory reading/writing helpers
internal U64 dmn_lnx_read(int memory_fd, Rng1U64 range, void *dst);
internal B32 dmn_lnx_write(int memory_fd, Rng1U64 range, void *src);
#define dmn_lnx_read_struct(fd, vaddr, ptr) dmn_lnx_read((fd), r1u64((vaddr), (vaddr)+sizeof(*(ptr))), (ptr))
#define dmn_lnx_write_struct(fd, vaddr, ptr) dmn_lnx_write((fd), r1u64((vaddr), (vaddr)+sizeof(*(ptr))), (ptr))
internal String8 dmn_lnx_read_string(Arena *arena, int memory_fd, U64 base_vaddr);
//- rjf: pid => info extraction
internal String8 dmn_lnx_exe_path_from_pid(Arena *arena, pid_t pid);
internal Arch dmn_lnx_arch_from_pid(pid_t pid);
internal DMN_LNX_ProcessAux dmn_lnx_aux_from_pid(pid_t pid, Arch arch);
//- rjf: phdr info extraction
internal DMN_LNX_PhdrInfo dmn_lnx_phdr_info_from_memory(int memory_fd, B32 is_32bit, U64 phvaddr, U64 phsize, U64 phcount);
//- rjf: process entity => info extraction
internal DMN_LNX_ModuleInfoList dmn_lnx_module_info_list_from_process(Arena *arena, DMN_LNX_Entity *process);
////////////////////////////////
//~ rjf: Entity Functions
internal DMN_LNX_Entity *dmn_lnx_entity_alloc(DMN_LNX_Entity *parent, DMN_LNX_EntityKind kind);
internal void dmn_lnx_entity_release(DMN_LNX_Entity *entity);
internal DMN_Handle dmn_lnx_handle_from_entity(DMN_LNX_Entity *entity);
internal DMN_LNX_Entity *dmn_lnx_entity_from_handle(DMN_Handle handle);
internal DMN_LNX_Entity *dmn_lnx_thread_from_pid(pid_t pid);
internal B32 dmn_lnx_thread_read_reg_block(DMN_LNX_Entity *thread, void *reg_block);
internal B32 dmn_lnx_thread_write_reg_block(DMN_LNX_Entity *thread, void *reg_block);
#endif // DEMON_CORE_LINUX_H
+78 -74
View File
@@ -320,7 +320,10 @@ dmn_w32_process_read(HANDLE process, Rng1U64 range, void *dst)
SIZE_T actual_read = 0;
if(!ReadProcessMemory(process, (LPCVOID)cursor, ptr, to_read, &actual_read))
{
DWORD error = GetLastError();
log_infof("'Win32 ReadProcessMemory failure': { [0x%I64x, 0x%I64x), code: %i }\n", range.min, range.max, error);
bytes_read += actual_read;
(void)error;
break;
}
ptr += actual_read;
@@ -349,7 +352,6 @@ dmn_w32_process_write(HANDLE process, Rng1U64 range, void *src)
ptr += actual_write;
cursor += actual_write;
}
ins_atomic_u64_inc_eval(&dmn_w32_shared->mem_gen);
return result;
}
@@ -766,8 +768,8 @@ dmn_w32_thread_read_reg_block(Arch arch, HANDLE thread, void *reg_block)
dst->fop.u16 = xsave->ErrorOpcode;
dst->fcs.u16 = xsave->ErrorSelector;
dst->fds.u16 = xsave->DataSelector;
dst->fip.u32 = xsave->ErrorOffset;
dst->fdp.u32 = xsave->DataOffset;
dst->fip.u64 = xsave->ErrorOffset;
dst->fdp.u64 = xsave->DataOffset;
dst->mxcsr.u32 = xsave->MxCsr;
dst->mxcsr_mask.u32 = xsave->MxCsr_Mask;
{
@@ -1035,8 +1037,8 @@ dmn_w32_thread_write_reg_block(Arch arch, HANDLE thread, void *reg_block)
fxsave->ErrorOpcode = src->fop.u16;
fxsave->ErrorSelector = src->fcs.u16;
fxsave->DataSelector = src->fds.u16;
fxsave->ErrorOffset = src->fip.u32;
fxsave->DataOffset = src->fdp.u32;
fxsave->ErrorOffset = src->fip.u64;
fxsave->DataOffset = src->fdp.u64;
{
M128A *float_d = fxsave->FloatRegisters;
REGS_Reg80 *float_s = &src->fpr0;
@@ -1112,7 +1114,6 @@ dmn_w32_thread_write_reg_block(Arch arch, HANDLE thread, void *reg_block)
scratch_end(scratch);
}break;
}
ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen);
ProfEnd();
return result;
}
@@ -1541,7 +1542,6 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
U64 new_rflags = rflags | 0x100;
single_step_thread_ctx->EFlags = new_rflags;
SetThreadContext(thread->handle, single_step_thread_ctx);
ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen);
}
}break;
}
@@ -1684,6 +1684,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
}break;
case DMN_TrapFlag_BreakOnRead|DMN_TrapFlag_BreakOnWrite|DMN_TrapFlag_BreakOnExecute:
case DMN_TrapFlag_BreakOnRead|DMN_TrapFlag_BreakOnWrite:
case DMN_TrapFlag_BreakOnRead:
{
regs.dr7.u64 |= (((U64)bit17) << (trap_idx*4));
regs.dr7.u64 |= (((U64)bit18) << (trap_idx*4));
@@ -1801,40 +1802,14 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
}
}
//////////////////////////
//- rjf: resume threads which will run
//
ProfScope("resume threads which will run")
{
for(DMN_W32_EntityNode *n = first_run_thread; n != 0; n = n->next)
{
DMN_W32_Entity *thread = n->v;
DWORD resume_result = ResumeThread(thread->handle);
switch(resume_result)
{
case 0xffffffffu:
{
// TODO(rjf): error - unknown cause. need to do GetLastError, FormatMessage
}break;
default:
{
DWORD desired_counter = 0;
DWORD current_counter = resume_result - 1;
if(current_counter != desired_counter)
{
// NOTE(rjf): Warning. The user has manually suspended this thread,
// so even though from Demon's perspective it thinks this thread
// should run, it will not, because the user has manually called
// SuspendThread or used CREATE_SUSPENDED or whatever.
}
}break;
}
}
}
//////////////////////////
//- rjf: loop, consume win32 debug events until we produce the relevant demon events
//
B32 priority_mode = !dmn_handle_match(dmn_handle_zero(), ctrls->priority_thread);
B32 did_priority_mode = priority_mode;
B32 do_threads_resume = 1;
DMN_W32_EntityNode *first_ran_thread = 0;
DMN_W32_EntityNode *last_ran_thread = 0;
U64 begin_time = os_now_microseconds();
String8List debug_strings = {0};
DMN_Event *debug_strings_event = 0;
@@ -1842,6 +1817,54 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
{
keep_going = 0;
////////////////////////
//- rjf: resume threads that we want to run
//
// if priority mode? => first, just resume priority thread
// if not? => resume all non-priority threads
//
if(do_threads_resume) ProfScope("resume threads that we want to run")
{
do_threads_resume = 0;
for(DMN_W32_EntityNode *n = first_run_thread; n != 0; n = n->next)
{
DMN_W32_Entity *thread = n->v;
B32 thread_is_priority = dmn_handle_match(dmn_w32_handle_from_entity(thread), ctrls->priority_thread);
if((priority_mode && !thread_is_priority) ||
(!priority_mode && did_priority_mode && thread_is_priority))
{
continue;
}
DWORD resume_result = ResumeThread(thread->handle);
DMN_W32_EntityNode *n = push_array(scratch.arena, DMN_W32_EntityNode, 1);
SLLQueuePush(first_ran_thread, last_ran_thread, n);
n->v = thread;
switch(resume_result)
{
case 0xffffffffu:
{
// TODO(rjf): error - unknown cause. need to do GetLastError, FormatMessage
}break;
default:
{
DWORD desired_counter = 0;
DWORD current_counter = resume_result - 1;
if(current_counter != desired_counter)
{
// NOTE(rjf): Warning. The user has manually suspended this thread,
// so even though from Demon's perspective it thinks this thread
// should run, it will not, because the user has manually called
// SuspendThread or used CREATE_SUSPENDED or whatever.
}
}break;
}
if(priority_mode && thread_is_priority)
{
break;
}
}
}
////////////////////////
//- rjf: choose win32 resume code
//
@@ -1878,7 +1901,12 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
}
if(resume_good)
{
evt_good = !!WaitForDebugEvent(&evt, 100);
DWORD wait_ms = 100;
if(priority_mode)
{
wait_ms = 30;
}
evt_good = !!WaitForDebugEvent(&evt, wait_ms);
if(evt_good)
{
dmn_w32_shared->resume_needed = 1;
@@ -1891,9 +1919,11 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
(void)err;
keep_going = 1;
}
ins_atomic_u64_inc_eval(&dmn_w32_shared->run_gen);
ins_atomic_u64_inc_eval(&dmn_w32_shared->mem_gen);
ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen);
if(priority_mode)
{
priority_mode = 0;
do_threads_resume = 1;
}
}
}
@@ -2327,7 +2357,6 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
U64 new_rip = instruction_pointer;
ctx->Rip = new_rip;
SetThreadContext(thread->handle, ctx);
ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen);
}
}break;
}
@@ -2387,7 +2416,6 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
// 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;
@@ -2402,10 +2430,10 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
{
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; }
else if(regs.dr7.u64 & (1ull<<0) && regs.dr6.u64 & (1ull<<0)) { flagged_trap_idx = 0; e->address = regs.dr0.u64; }
else if(regs.dr7.u64 & (1ull<<2) && regs.dr6.u64 & (1ull<<1)) { flagged_trap_idx = 1; e->address = regs.dr1.u64; }
else if(regs.dr7.u64 & (1ull<<4) && regs.dr6.u64 & (1ull<<2)) { flagged_trap_idx = 2; e->address = regs.dr2.u64; }
else if(regs.dr7.u64 & (1ull<<8) && regs.dr6.u64 & (1ull<<3)) { flagged_trap_idx = 3; e->address = regs.dr3.u64; }
}
}break;
}
@@ -2649,7 +2677,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
////////////////////////
//- rjf: exit loop after a little while, so we keep pumping e.g. debug strings
//
if(os_now_microseconds() >= begin_time+100000)
if(os_now_microseconds() >= begin_time+100000 && debug_strings.total_size != 0)
{
keep_going = 0;
}
@@ -2669,7 +2697,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
//
ProfScope("suspend threads which ran")
{
for(DMN_W32_EntityNode *n = first_run_thread; n != 0; n = n->next)
for(DMN_W32_EntityNode *n = first_ran_thread; n != 0; n = n->next)
{
DMN_W32_Entity *thread = n->v;
if(thread->kind != DMN_W32_EntityKind_Thread)
@@ -2841,7 +2869,6 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
U64 new_rflags = rflags & ~0x100;
single_step_thread_ctx->EFlags = new_rflags;
SetThreadContext(thread->handle, single_step_thread_ctx);
ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen);
}
}break;
}
@@ -2938,29 +2965,6 @@ dmn_halt(U64 code, U64 user_data)
////////////////////////////////
//~ rjf: @dmn_os_hooks Introspection Functions (Implemented Per-OS)
//- rjf: run/memory/register counters
internal U64
dmn_run_gen(void)
{
U64 result = ins_atomic_u64_eval(&dmn_w32_shared->run_gen);
return result;
}
internal U64
dmn_mem_gen(void)
{
U64 result = ins_atomic_u64_eval(&dmn_w32_shared->mem_gen);
return result;
}
internal U64
dmn_reg_gen(void)
{
U64 result = ins_atomic_u64_eval(&dmn_w32_shared->reg_gen);
return result;
}
//- rjf: non-blocking-control-thread access barriers
internal B32
-5
View File
@@ -200,11 +200,6 @@ struct DMN_W32_Shared
OS_Handle access_mutex;
B32 access_run_state;
// rjf: run/mem/reg gens
U64 run_gen;
U64 mem_gen;
U64 reg_gen;
// rjf: detaching info
Arena *detach_arena;
DMN_HandleList detach_processes;
+11 -4
View File
@@ -507,12 +507,19 @@ dr_sub_bucket(DR_Bucket *bucket)
MemoryCopyStruct(&dst_group_n->params, &src_group_n->params);
dst_group_n->batches = src_group_n->batches;
dst_group_n->params.xform = dr_top_xform2d();
B32 clip_is_set = !(dst_group_n->params.clip.x0 == 0 &&
dst_group_n->params.clip.y0 == 0 &&
dst_group_n->params.clip.x1 == 0 &&
dst_group_n->params.clip.y1 == 0);
if(clip_is_set)
{
Rng2F32 og_clip = dst_group_n->params.clip;
Mat3x3F32 xform = dst_group_n->params.xform;
dst_group_n->params.clip = r2f32(xform_3f32(v3f32(og_clip.x0, og_clip.y0, 1), xform).xy,
xform_3f32(v3f32(og_clip.x1, og_clip.y1, 1), xform).xy);
}
if(dst_clip_is_set)
{
B32 clip_is_set = !(dst_group_n->params.clip.x0 == 0 &&
dst_group_n->params.clip.y0 == 0 &&
dst_group_n->params.clip.x1 == 0 &&
dst_group_n->params.clip.y1 == 0);
dst_group_n->params.clip = clip_is_set ? intersect_2f32(dst_clip, dst_group_n->params.clip) : dst_clip;
}
}
+300 -27
View File
@@ -70,10 +70,10 @@ dw_reg_pos_from_code(Arch arch, DW_Reg reg_code)
}
internal DW_AttribClass
dw_attrib_class_from_attrib_kind_v2(DW_AttribKind k)
dw_attrib_class_from_attrib_v2(DW_AttribKind k)
{
switch (k) {
#define X(_N,_C) case DW_Attrib_##_N: return _C;
#define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_V2_XList(X)
#undef X
}
@@ -81,10 +81,10 @@ dw_attrib_class_from_attrib_kind_v2(DW_AttribKind k)
}
internal DW_AttribClass
dw_attrib_class_from_attrib_kind_v3(DW_AttribKind k)
dw_attrib_class_from_attrib_v3(DW_AttribKind k)
{
switch (k) {
#define X(_N,_C) case DW_Attrib_##_N: return _C;
#define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_V3_XList(X)
#undef X
}
@@ -92,10 +92,10 @@ dw_attrib_class_from_attrib_kind_v3(DW_AttribKind k)
}
internal DW_AttribClass
dw_attrib_class_from_attrib_kind_v4(DW_AttribKind k)
dw_attrib_class_from_attrib_v4(DW_AttribKind k)
{
switch (k) {
#define X(_N,_C) case DW_Attrib_##_N: return _C;
#define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_V4_XList(X)
#undef X
}
@@ -103,10 +103,10 @@ dw_attrib_class_from_attrib_kind_v4(DW_AttribKind k)
}
internal DW_AttribClass
dw_attrib_class_from_attrib_kind_v5(DW_AttribKind k)
dw_attrib_class_from_attrib_v5(DW_AttribKind k)
{
switch (k) {
#define X(_N,_C) case DW_Attrib_##_N: return _C;
#define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_V5_XList(X)
#undef X
}
@@ -114,10 +114,10 @@ dw_attrib_class_from_attrib_kind_v5(DW_AttribKind k)
}
internal DW_AttribClass
dw_attrib_class_from_attrib_kind_gnu(DW_AttribKind k)
dw_attrib_class_from_attrib_gnu(DW_AttribKind k)
{
switch (k) {
#define X(_N,_C) case DW_Attrib_##_N: return _C;
#define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_GNU_XList(X)
#undef X
}
@@ -125,10 +125,10 @@ dw_attrib_class_from_attrib_kind_gnu(DW_AttribKind k)
}
internal DW_AttribClass
dw_attrib_class_from_attrib_kind_llvm(DW_AttribKind k)
dw_attrib_class_from_attrib_llvm(DW_AttribKind k)
{
switch (k) {
#define X(_N,_C) case DW_Attrib_##_N: return _C;
#define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_LLVM_XList(X)
#undef X
}
@@ -136,10 +136,10 @@ dw_attrib_class_from_attrib_kind_llvm(DW_AttribKind k)
}
internal DW_AttribClass
dw_attrib_class_from_attrib_kind_apple(DW_AttribKind k)
dw_attrib_class_from_attrib_apple(DW_AttribKind k)
{
switch (k) {
#define X(_N,_C) case DW_Attrib_##_N: return _C;
#define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_APPLE_XList(X)
#undef X
}
@@ -147,10 +147,10 @@ dw_attrib_class_from_attrib_kind_apple(DW_AttribKind k)
}
internal DW_AttribClass
dw_attrib_class_from_attrib_kind_mips(DW_AttribKind k)
dw_attrib_class_from_attrib_mips(DW_AttribKind k)
{
switch (k) {
#define X(_N,_C) case DW_Attrib_##_N: return _C;
#define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_MIPS_XList(X)
#undef X
}
@@ -158,7 +158,7 @@ dw_attrib_class_from_attrib_kind_mips(DW_AttribKind k)
}
internal DW_AttribClass
dw_attrib_class_from_attrib_kind(DW_Version ver, DW_Ext ext, DW_AttribKind k)
dw_attrib_class_from_attrib(DW_Version ver, DW_Ext ext, DW_AttribKind k)
{
DW_AttribClass result = DW_AttribClass_Null;
@@ -172,10 +172,10 @@ dw_attrib_class_from_attrib_kind(DW_Version ver, DW_Ext ext, DW_AttribKind k)
switch (flag) {
case DW_Ext_Null: break;
case DW_Ext_GNU: result = dw_attrib_class_from_attrib_kind_gnu(k); break;
case DW_Ext_LLVM: result = dw_attrib_class_from_attrib_kind_llvm(k); break;
case DW_Ext_APPLE: result = dw_attrib_class_from_attrib_kind_apple(k); break;
case DW_Ext_MIPS: result = dw_attrib_class_from_attrib_kind_mips(k); break;
case DW_Ext_GNU: result = dw_attrib_class_from_attrib_gnu(k); break;
case DW_Ext_LLVM: result = dw_attrib_class_from_attrib_llvm(k); break;
case DW_Ext_APPLE: result = dw_attrib_class_from_attrib_apple(k); break;
case DW_Ext_MIPS: result = dw_attrib_class_from_attrib_mips(k); break;
default: InvalidPath; break;
}
@@ -188,10 +188,10 @@ dw_attrib_class_from_attrib_kind(DW_Version ver, DW_Ext ext, DW_AttribKind k)
switch (ver) {
case DW_Version_Null: break;
case DW_Version_1: AssertAlways(!"DWARF V1 is not supported"); break;
case DW_Version_2: result = dw_attrib_class_from_attrib_kind_v2(k); break;
case DW_Version_3: result = dw_attrib_class_from_attrib_kind_v3(k); break;
case DW_Version_4: result = dw_attrib_class_from_attrib_kind_v4(k); break;
case DW_Version_5: result = dw_attrib_class_from_attrib_kind_v5(k); break;
case DW_Version_2: result = dw_attrib_class_from_attrib_v2(k); break;
case DW_Version_3: result = dw_attrib_class_from_attrib_v3(k); break;
case DW_Version_4: result = dw_attrib_class_from_attrib_v4(k); break;
case DW_Version_5: result = dw_attrib_class_from_attrib_v5(k); break;
default: InvalidPath; break;
}
}
@@ -302,14 +302,14 @@ dw_pick_attrib_value_class(DW_Version ver, DW_Ext ext, B32 relaxed, DW_AttribKin
// This function's purpose is to find the overlapping class between an
// DW_AttribKind and DW_FormKind.
DW_AttribClass attrib_class = dw_attrib_class_from_attrib_kind(ver, ext, attrib_kind);
DW_AttribClass attrib_class = dw_attrib_class_from_attrib(ver, ext, attrib_kind);
DW_AttribClass form_class = dw_attrib_class_from_form_kind(ver, form_kind);
if(relaxed)
{
if(attrib_class == DW_AttribClass_Null || form_class == DW_AttribClass_Null)
{
attrib_class = dw_attrib_class_from_attrib_kind(DW_Version_Last, ext, attrib_kind);
attrib_class = dw_attrib_class_from_attrib(DW_Version_Last, ext, attrib_kind);
form_class = dw_attrib_class_from_form_kind(DW_Version_Last, form_kind);
}
}
@@ -386,3 +386,276 @@ dw_pick_default_lower_bound(DW_Language lang)
return lower_bound;
}
////////////////////////////////
//~ rjf: String <=> Enum
internal String8
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;
if (ext & DW_Ext_GNU) {
switch (op) {
DW_Expr_GNU_XList(X);
}
}
switch (ver) {
case DW_Version_5: {
switch (op) {
DW_Expr_V5_XList(X)
}
} // fall-through
case DW_Version_4: {
switch (op) {
DW_Expr_V4_XList(X)
}
} // fall-through
case DW_Version_3: {
switch (op) {
DW_Expr_V3_XList(X)
}
} // fall-through
case DW_Version_2:
case DW_Version_1:
case DW_Version_Null:
break;
}
#undef X
result = push_str8f(arena, "%x", op);
exit:;
return result;
}
internal String8
dw_string_from_tag_kind(Arena *arena, DW_TagKind kind)
{
switch (kind) {
case DW_TagKind_Null: return str8_lit("Null");
#define X(_N,_ID) case DW_TagKind_##_N: return str8_lit(Stringify(_N));
DW_TagKind_V3_XList(X)
DW_TagKind_V5_XList(X)
DW_TagKind_GNU_XList(X)
#undef X
}
return push_str8f(arena, "%llx", kind);
}
internal String8
dw_string_from_attrib_kind(Arena *arena, DW_Version ver, DW_Ext ext, DW_AttribKind kind)
{
#define X(_N,...) case DW_AttribKind_##_N:{result = str8_lit(Stringify(_N));}break;
String8 result = {0};
//- rjf: try extensions
if(result.size != 0)
{
while(ext)
{
U64 z = 64-clz64(ext);
if(z == 0)
{
break;
}
U64 flag = 1 << (z-1);
ext &= ~flag;
switch(flag)
{
default:{}break;
case DW_Ext_Null: break;
case DW_Ext_GNU: switch (kind) { DW_AttribKind_GNU_XList(X) } break;
case DW_Ext_LLVM: switch (kind) { DW_AttribKind_LLVM_XList(X) } break;
case DW_Ext_APPLE: switch (kind) { DW_AttribKind_APPLE_XList(X) } break;
case DW_Ext_MIPS: switch (kind) { DW_AttribKind_MIPS_XList(X) } break;
}
}
}
//- rjf: try version
if(result.size == 0)
{
for(U64 retry = 0; retry < 2; retry += 1)
{
DW_Version version = retry ? DW_Version_5 : ver;
switch(version)
{
case DW_Version_5: { switch(kind) { DW_AttribKind_V5_XList(X) } } // fall-through
case DW_Version_4: { switch(kind) { DW_AttribKind_V4_XList(X) } } // fall-through
case DW_Version_3: { switch(kind) { DW_AttribKind_V3_XList(X) } } // fall-through
case DW_Version_2: { switch(kind) { DW_AttribKind_V2_XList(X) } } // fall-through
case DW_Version_1: {}break;
case DW_Version_Null:{}break;
default:{}break;
}
}
}
//- rjf: fallback
if(result.size == 0)
{
result = push_str8f(arena, "#%u", kind);
}
#undef X
return result;
}
internal String8
dw_string_from_form_kind(Arena *arena, DW_Version ver, DW_FormKind kind)
{
#define X(_N,...) case DW_Form_##_N: return str8_lit(Stringify(_N));
switch (ver) {
case DW_Version_5: {
switch (kind) {
DW_Form_V5_XList(X)
}
} // fall-through
case DW_Version_4: {
switch (kind) {
DW_Form_V4_XList(X)
}
} // fall-through
case DW_Version_3:
case DW_Version_2: {
switch (kind) {
DW_Form_V2_XList(X)
}
} // fall-through
case DW_Version_Null: break;
}
#undef X
String8 result = push_str8f(arena, "%x", kind);
return result;
}
internal String8
dw_string_from_language(Arena *arena, DW_Language kind)
{
switch (kind) {
#define X(_N,_ID) case DW_Language_##_N: return str8_lit(Stringify(_N));
DW_Language_XList(X)
#undef X
}
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)
{
switch (kind) {
#define X(_N,_ID) case DW_StdOpcode_##_N: return str8_lit(Stringify(_N));
DW_StdOpcode_XList(X)
#undef X
}
return push_str8f(arena, "%x", kind);
}
internal String8
dw_string_from_ext_opcode(Arena *arena, DW_ExtOpcode kind)
{
switch (kind) {
#define X(_N,_ID) case DW_ExtOpcode_##_N: return str8_lit(Stringify(_N));
DW_ExtOpcode_XList(X)
#undef X
default: InvalidPath; break;
}
return push_str8f(arena, "%x", kind);
}
internal String8
dw_string_from_loc_list_entry_kind(Arena *arena, DW_LLE kind)
{
NotImplemented;
return str8_zero();
}
internal String8
dw_string_from_section_kind(Arena *arena, DW_SectionKind kind)
{
NotImplemented;
return str8_zero();
}
internal String8
dw_string_from_rng_list_entry_kind(Arena *arena, DW_RLE kind)
{
NotImplemented;
return str8_zero();
}
internal String8
dw_string_from_register(Arena *arena, Arch arch, U64 reg_id)
{
String8 reg_str = str8_zero();
switch (arch) {
case Arch_Null: break;
case Arch_x86: {
switch (reg_id) {
#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_RegX64_##_N: reg_str = str8_lit(Stringify(_N)); break;
DW_Regs_X64_XList(X)
#undef X
}
} break;
case Arch_arm32: NotImplemented; break;
case Arch_arm64: NotImplemented; break;
default: InvalidPath; break;
}
if (reg_str.size == 0) {
reg_str = push_str8f(arena, "%#llx", reg_id);
}
return reg_str;
}
+43 -24
View File
@@ -188,7 +188,7 @@ typedef enum DW_IDCaseKindEnum
#undef X
} DW_IDCaseKindEnum;
#define DW_Tag_V3_XList(X) \
#define DW_TagKind_V3_XList(X) \
X(ArrayType, 0x01) \
X(ClassType, 0x02) \
X(EntryPoint, 0x03) \
@@ -247,7 +247,7 @@ X(ImportedUnit, 0x3d) \
X(Condition, 0x3f) \
X(SharedType, 0x40)
#define DW_Tag_V5_XList(X) \
#define DW_TagKind_V5_XList(X) \
X(TypeUnit, 0x41) \
X(RValueReferenceType, 0x42) \
X(TemplateAlias, 0x43) \
@@ -260,21 +260,21 @@ X(CallSiteParameter, 0x49) \
X(SkeletonUnit, 0x4A) \
X(ImmutableType, 0x4B)
#define DW_Tag_GNU_XList(X) \
#define DW_TagKind_GNU_XList(X) \
X(GNU_CallSite, 0x4109) \
X(GNU_CallSiteParameter, 0x410a)
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)
DW_Tag_GNU_XList(X)
DW_TagKind_Null,
#define X(_N,_ID) DW_TagKind_##_N = _ID,
DW_TagKind_V3_XList(X)
DW_TagKind_V5_XList(X)
DW_TagKind_GNU_XList(X)
#undef X
DW_Tag_UserLo = 0x4080,
DW_Tag_UserHi = 0xffff
DW_TagKind_UserLo = 0x4080,
DW_TagKind_UserHi = 0xffff
} DW_TagKindEnum;
//- Attrib Class Encodings
@@ -581,7 +581,7 @@ X(Producer, DW_AttribClass_String)
X(Prototyped, DW_AttribClass_Flag) \
X(ReturnAddr, DW_AttribClass_Block|DW_AttribClass_Const) \
X(StartScope, DW_AttribClass_Const) \
X(BitStride, DW_AttribClass_Const) /* dwarf-v1 DW_Attrib_stride_size*/ \
X(BitStride, DW_AttribClass_Const) /* dwarf-v1 DW_AttribKind_stride_size*/ \
X(UpperBound, DW_AttribClass_Const|DW_AttribClass_Reference) \
X(AbstractOrigin, DW_AttribClass_Reference) \
X(Accessibility, DW_AttribClass_Const) \
@@ -1159,8 +1159,8 @@ X(MIPS_AssumedSize, DW_AttribClass_Reference)
typedef U32 DW_AttribKind;
typedef enum DW_AttribKindEnum
{
DW_Attrib_Null,
#define X(_N,_ID,...) DW_Attrib_##_N = _ID,
DW_AttribKind_Null,
#define X(_N,_ID,...) DW_AttribKind_##_N = _ID,
DW_AttribKind_V2_XList(X)
DW_AttribKind_V3_XList(X)
DW_AttribKind_V4_XList(X)
@@ -1170,8 +1170,8 @@ typedef enum DW_AttribKindEnum
DW_AttribKind_APPLE_XList(X)
DW_AttribKind_MIPS_XList(X)
#undef X
DW_Attrib_UserLo = 0x2000,
DW_Attrib_UserHi = 0x3fff
DW_AttribKind_UserLo = 0x2000,
DW_AttribKind_UserHi = 0x3fff
} DW_AttribKindEnum;
#define DW_ATE_XList(X) \
@@ -1744,18 +1744,18 @@ internal U64 dw_reg_pos_from_code(Arch arch, DW_Reg reg_code);
//- Attrib Class Encodings
// Speced Encodings
internal DW_AttribClass dw_attrib_class_from_attrib_kind_v2(DW_AttribKind k);
internal DW_AttribClass dw_attrib_class_from_attrib_kind_v3(DW_AttribKind k);
internal DW_AttribClass dw_attrib_class_from_attrib_kind_v4(DW_AttribKind k);
internal DW_AttribClass dw_attrib_class_from_attrib_kind_v5(DW_AttribKind k);
internal DW_AttribClass dw_attrib_class_from_attrib_v2(DW_AttribKind k);
internal DW_AttribClass dw_attrib_class_from_attrib_v3(DW_AttribKind k);
internal DW_AttribClass dw_attrib_class_from_attrib_v4(DW_AttribKind k);
internal DW_AttribClass dw_attrib_class_from_attrib_v5(DW_AttribKind k);
// Extensions
internal DW_AttribClass dw_attrib_class_from_attrib_kind_gnu (DW_AttribKind k);
internal DW_AttribClass dw_attrib_class_from_attrib_kind_llvm (DW_AttribKind k);
internal DW_AttribClass dw_attrib_class_from_attrib_kind_apple(DW_AttribKind k);
internal DW_AttribClass dw_attrib_class_from_attrib_kind_mips (DW_AttribKind k);
internal DW_AttribClass dw_attrib_class_from_attrib_gnu (DW_AttribKind k);
internal DW_AttribClass dw_attrib_class_from_attrib_llvm (DW_AttribKind k);
internal DW_AttribClass dw_attrib_class_from_attrib_apple(DW_AttribKind k);
internal DW_AttribClass dw_attrib_class_from_attrib_mips (DW_AttribKind k);
internal DW_AttribClass dw_attrib_class_from_attrib_kind(DW_Version ver, DW_Ext ext, DW_AttribKind v);
internal DW_AttribClass dw_attrib_class_from_attrib(DW_Version ver, DW_Ext ext, DW_AttribKind v);
//- Form Class Encodings
@@ -1779,4 +1779,23 @@ internal DW_AttribClass dw_pick_attrib_value_class(DW_Version ver, DW_Ext ext, B
internal U64 dw_pick_default_lower_bound(DW_Language lang);
////////////////////////////////
//~ rjf: String <=> Enum
internal String8 dw_string_from_expr_op(Arena *arena, DW_Version ver, DW_Ext ext, DW_ExprOp op);
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_from_language(Arena *arena, DW_Language kind);
internal String8 dw_string_from_inl(Arena *arena, DW_InlKind kind);
internal String8 dw_string_from_access_kind(Arena *arena, DW_AccessKind kind);
internal String8 dw_string_from_calling_convetion(Arena *arena, DW_CallingConventionKind kind);
internal String8 dw_string_from_attrib_type_encoding(Arena *arena, DW_ATE kind);
internal String8 dw_string_from_std_opcode(Arena *arena, DW_StdOpcode kind);
internal String8 dw_string_from_ext_opcode(Arena *arena, DW_ExtOpcode kind);
internal String8 dw_string_from_loc_list_entry_kind(Arena *arena, DW_LLE kind);
internal String8 dw_string_from_section_kind(Arena *arena, DW_SectionKind kind);
internal String8 dw_string_from_rng_list_entry_kind(Arena *arena, DW_RLE kind);
internal String8 dw_string_from_register(Arena *arena, Arch arch, U64 reg_id);
#endif // DWARF_H
-2
View File
@@ -64,5 +64,3 @@ dw_input_from_coff_section_table(Arena *arena,
return input;
}
+1
View File
@@ -4,6 +4,7 @@
#ifndef DWARF_COFF_H
#define DWARF_COFF_H
internal B32 dw_is_dwarf_present_coff_section_table(String8 raw_image, String8 string_table, U64 section_count, COFF_SectionHeader *section_table);
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
File diff suppressed because it is too large Load Diff
+86
View File
@@ -0,0 +1,86 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef DWARF_DUMP_H
#define DWARF_DUMP_H
////////////////////////////////
//~ rjf: Dump Subset Types
#define DW_DumpSubset_XList \
X(DebugInfo, debug_info, "DEBUG INFO")\
X(DebugAbbrev, debug_abbrev, "DEBUG ABBREV")\
X(DebugLine, debug_line, "DEBUG LINE")\
X(DebugStr, debug_str, "DEBUG STR")\
X(DebugLoc, debug_loc, "DEBUG LOC")\
X(DebugRanges, debug_ranges, "DEBUG RANGES")\
X(DebugARanges, debug_aranges, "DEBUG ARANGES")\
X(DebugAddr, debug_addr, "DEBUG ADDR")\
X(DebugLocLists, debug_loclists, "DEBUG LOCLISTS")\
X(DebugRngLists, debug_rnglists, "DEBUG RNGLISTS")\
X(DebugPubNames, debug_pubnames, "DEBUG PUBNAMES")\
X(DebugPubTypes, debug_pubtypes, "DEBUG PUBTYPES")\
X(DebugLineStr, debug_linestr, "DEBUG LINESTR")\
X(DebugStrOffsets, debug_stroff, "DEBUG STROFF")\
typedef enum DW_DumpSubset
{
#define X(name, name_lower, title) DW_DumpSubset_##name,
DW_DumpSubset_XList
#undef X
}
DW_DumpSubset;
typedef U32 DW_DumpSubsetFlags;
enum
{
#define X(name, name_lower, title) DW_DumpSubsetFlag_##name = (1<<DW_DumpSubset_##name),
DW_DumpSubset_XList
#undef X
DW_DumpSubsetFlag_All = 0xffffffffu,
};
read_only global String8 dw_name_lowercase_from_dump_subset_table[] =
{
#define X(name, name_lower, title) str8_lit_comp(#name_lower),
DW_DumpSubset_XList
#undef X
};
read_only global String8 dw_name_title_from_dump_subset_table[] =
{
#define X(name, name_lower, title) str8_lit_comp(title),
DW_DumpSubset_XList
#undef X
};
////////////////////////////////
//~ rjf: Stringification Helpers
internal String8 dw_string_from_reg_off(Arena *arena, Arch arch, U64 reg_idx, S64 reg_off);
internal String8List dw_string_list_from_expression (Arena *arena, String8 raw_data, U64 cu_base, U64 address_size, Arch arch, DW_Version ver, DW_Ext ext, DW_Format format);
internal String8 dw_single_line_string_from_expression(Arena *arena, String8 raw_data, U64 cu_base, U64 address_size, Arch arch, DW_Version ver, DW_Ext ext, DW_Format format);
internal String8 dw_string_from_eh_ptr_enc (Arena *arena, DW_EhPtrEnc enc);
#if 0
internal void dw_string_from_cfi_program (Arena *arena, String8List *out, String8 indent, String8 raw_data, DW_CIEUnpacked *cie, DW_EhPtrCtx *ptr_ctx, Arch arch, DW_Version ver, DW_Ext ext, DW_Format format);
internal void dw_print_eh_frame (Arena *arena, String8List *out, String8 indent, String8 raw_eh_frame, Arch arch, DW_Version ver, DW_Ext ext, DW_EhPtrCtx *ptr_ctx);
internal void dw_print_debug_loc (Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ExecutableImageKind image_type, B32 relaxed);
internal void dw_print_debug_ranges (Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ExecutableImageKind image_type, B32 relaxed);
internal void dw_print_debug_aranges (Arena *arena, String8List *out, String8 indent, DW_Input *input);
internal void dw_print_debug_addr (Arena *arena, String8List *out, String8 indent, DW_Input *input);
internal void dw_print_debug_loclists (Arena *arena, String8List *out, String8 indent, DW_Input *input, Rng1U64Array segment_vranges, Arch arch);
internal void dw_print_debug_rnglists (Arena *arena, String8List *out, String8 indent, DW_Input *input, Rng1U64Array segment_vranges);
internal void dw_print_debug_pubnames (Arena *arena, String8List *out, String8 indent, DW_Input *input);
internal void dw_print_debug_pubtypes (Arena *arena, String8List *out, String8 indent, DW_Input *input);
internal void dw_print_debug_line_str (Arena *arena, String8List *out, String8 indent, DW_Input *input);
internal void dw_print_debug_str_offsets(Arena *arena, String8List *out, String8 indent, DW_Input *input);
#endif
////////////////////////////////
//~ rjf: Dump Entry Point
internal String8List dw_dump_list_from_sections(Arena *arena, DW_Input *input, Arch arch, DW_DumpSubsetFlags subset_flags);
#endif // DWARF_DUMP_H
+84 -102
View File
@@ -2,34 +2,25 @@
// 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)
dw_is_dwarf_present_from_elf_bin(String8 data, ELF_Bin *bin)
{
Temp scratch = scratch_begin(0,0);
B32 is_dwarf_present = 0;
ELF_Shdr64Array sections = elf_shdr64_array_from_bin(scratch.arena, raw_image, &bin->hdr);
for (U64 i = 0; i < sections.count; ++i) {
ELF_Shdr64 *shdr = &sections.v[i];
String8 name = elf_name_from_shdr64(raw_image, &bin->hdr, bin->sh_name_range, shdr);
if (shdr->sh_type != ELF_SectionCode_ProgBits) {
continue;
}
for EachIndex(idx, bin->shdrs.count)
{
ELF_Shdr64 *shdr = &bin->shdrs.v[idx];
if(shdr->sh_type != ELF_SectionCode_ProgBits) { continue; }
String8 name = elf_name_from_shdr64(data, bin, shdr);
DW_SectionKind s = dw_section_kind_from_string(name);
if (s == DW_Section_Null) {
if(s == DW_Section_Null)
{
s = dw_section_dwo_kind_from_string(name);
}
is_dwarf_present = s != DW_Section_Null;
if (is_dwarf_present) {
is_dwarf_present = (s != DW_Section_Null);
if(is_dwarf_present)
{
break;
}
}
scratch_end(scratch);
return is_dwarf_present;
}
@@ -37,99 +28,90 @@ dw_is_dwarf_present_elf_section_table(String8 raw_image, ELF_BinInfo *bin)
#include "third_party/sinfl/sinfl.h"
internal DW_Input
dw_input_from_elf_section_table(Arena *arena, String8 raw_image, ELF_BinInfo *bin)
dw_input_from_elf_bin(Arena *arena, String8 data, ELF_Bin *bin)
{
DW_Input result = {0};
B32 is_section_present[ArrayCount(result.sec)] = {0};
Temp scratch = scratch_begin(&arena, 1);
DW_Input result = {0};
B32 sect_status[ArrayCount(result.sec)] = {0};
ELF_Shdr64Array sections = elf_shdr64_array_from_bin(scratch.arena, raw_image, &bin->hdr);
for (U64 sect_idx = 1; sect_idx < sections.count; ++sect_idx) {
ELF_Shdr64 *shdr = &sections.v[sect_idx];
for(U64 section_idx = 1; section_idx < bin->shdrs.count; section_idx += 1)
{
ELF_Shdr64 *shdr = &bin->shdrs.v[section_idx];
if(shdr->sh_type != ELF_SectionCode_ProgBits) { continue; } // skip BSS sections
// skip BSS sections
if (shdr->sh_type != ELF_SectionCode_ProgBits) {
continue;
//- rjf: unpack section
String8 section_name = elf_name_from_shdr64(data, bin, shdr);
DW_SectionKind section_kind = dw_section_kind_from_string(section_name);
String8 section_data__maybe_compressed = str8_substr(data, r1u64(shdr->sh_offset, shdr->sh_offset + shdr->sh_size));
B32 is_dwo = 0;
if(section_kind == DW_Section_Null)
{
section_kind = dw_section_dwo_kind_from_string(section_name);
is_dwo = (section_kind != DW_Section_Null);
}
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);
}
//- rjf: decompress section data if needed
String8 section_data__uncompressed = {0};
if(section_kind != DW_Section_Null)
{
if(!(shdr->sh_flags & ELF_Shf_Compressed))
{
section_data__uncompressed = section_data__maybe_compressed;
}
else
{
// rjf: read compressed-section header
ELF_Chdr64 chdr64 = {0};
U64 chdr_size = 0;
if(ELF_HdrIs64Bit(bin->hdr.e_ident))
{
chdr_size = str8_deserial_read_struct(section_data__maybe_compressed, 0, &chdr64);
}
else if(ELF_HdrIs32Bit(bin->hdr.e_ident))
{
ELF_Chdr32 chdr32 = {0};
chdr_size = str8_deserial_read_struct(section_data__maybe_compressed, 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;
// rjf: decompress
{
String8 section_data__compressed_contents = str8_skip(section_data__maybe_compressed, chdr_size);
switch(chdr64.ch_type)
{
default:
case ELF_CompressType_None:
{
section_data__uncompressed = section_data__compressed_contents;
}break;
case ELF_CompressType_ZLib:
{
U8 *section_data_uncompressed_buffer = push_array_no_zero_aligned(arena, U8, chdr64.ch_size, chdr64.ch_addr_align);
U64 section_data_uncompressed_size = 0;
section_data_uncompressed_size = zsinflate(section_data_uncompressed_buffer, chdr64.ch_size, section_data__compressed_contents.str, section_data__compressed_contents.size);
section_data__uncompressed = str8(section_data_uncompressed_buffer, section_data_uncompressed_size);
}break;
case ELF_CompressType_ZStd:
{
NotImplemented;
}break;
}
}
}
}
//- rjf: store
if(section_kind != DW_Section_Null)
{
is_section_present[section_kind] = 1;
DW_Section *d = &result.sec[section_kind];
d->name = push_str8_copy(arena, section_name);
d->data = section_data__uncompressed;
d->is_dwo = is_dwo;
}
}
scratch_end(scratch);
return result;
}
+2 -3
View File
@@ -4,8 +4,7 @@
#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);
internal B32 dw_is_dwarf_present_from_elf_bin(String8 raw_image, ELF_Bin *bin);
internal DW_Input dw_input_from_elf_bin(Arena *arena, String8 raw_image, ELF_Bin *bin);
#endif // DWARF_ELF_H
-268
View File
@@ -1,268 +0,0 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal String8
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;
if (ext & DW_Ext_GNU) {
switch (op) {
DW_Expr_GNU_XList(X);
}
}
switch (ver) {
case DW_Version_5: {
switch (op) {
DW_Expr_V5_XList(X)
}
} // fall-through
case DW_Version_4: {
switch (op) {
DW_Expr_V4_XList(X)
}
} // fall-through
case DW_Version_3: {
switch (op) {
DW_Expr_V3_XList(X)
}
} // fall-through
case DW_Version_2:
case DW_Version_1:
case DW_Version_Null:
break;
}
#undef X
result = push_str8f(arena, "%x", op);
exit:;
return result;
}
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)
DW_Tag_GNU_XList(X)
#undef X
}
return push_str8f(arena, "%llx", kind);
}
internal String8
dw_string_from_attrib_kind(Arena *arena, DW_Version ver, DW_Ext ext, DW_AttribKind kind)
{
#define X(_N,...) case DW_Attrib_##_N: return str8_lit(Stringify(_N));
while (ext) {
U64 z = 64-clz64(ext);
if (z == 0) {
break;
}
U64 flag = 1 << (z-1);
ext &= ~flag;
switch (flag) {
case DW_Ext_Null: break;
case DW_Ext_GNU: switch (kind) { DW_AttribKind_GNU_XList(X) } break;
case DW_Ext_LLVM: switch (kind) { DW_AttribKind_LLVM_XList(X) } break;
case DW_Ext_APPLE: switch (kind) { DW_AttribKind_APPLE_XList(X) } break;
case DW_Ext_MIPS: switch (kind) { DW_AttribKind_MIPS_XList(X) } break;
default: InvalidPath; break;
}
}
switch (ver) {
case DW_Version_5: {
switch (kind) {
DW_AttribKind_V5_XList(X)
}
} // fall-through
case DW_Version_4: {
switch (kind) {
DW_AttribKind_V4_XList(X)
}
} // fall-through
case DW_Version_3: {
switch (kind) {
DW_AttribKind_V3_XList(X)
}
} // fall-through
case DW_Version_2: {
switch (kind) {
DW_AttribKind_V2_XList(X)
}
} // fall-through
case DW_Version_1: {
} // fall-through
case DW_Version_Null: break;
}
#undef X
return str8_zero();
}
internal String8
dw_string_from_form_kind(Arena *arena, DW_Version ver, DW_FormKind kind)
{
#define X(_N,...) case DW_Form_##_N: return str8_lit(Stringify(_N));
switch (ver) {
case DW_Version_5: {
switch (kind) {
DW_Form_V5_XList(X)
}
} // fall-through
case DW_Version_4: {
switch (kind) {
DW_Form_V4_XList(X)
}
} // fall-through
case DW_Version_3:
case DW_Version_2: {
switch (kind) {
DW_Form_V2_XList(X)
}
} // fall-through
case DW_Version_Null: break;
}
#undef X
String8 result = push_str8f(arena, "%x", kind);
return result;
}
internal String8
dw_string_from_language(Arena *arena, DW_Language kind)
{
switch (kind) {
#define X(_N,_ID) case DW_Language_##_N: return str8_lit(Stringify(_N));
DW_Language_XList(X)
#undef X
}
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)
{
switch (kind) {
#define X(_N,_ID) case DW_StdOpcode_##_N: return str8_lit(Stringify(_N));
DW_StdOpcode_XList(X)
#undef X
}
return push_str8f(arena, "%x", kind);
}
internal String8
dw_string_from_ext_opcode(Arena *arena, DW_ExtOpcode kind)
{
switch (kind) {
#define X(_N,_ID) case DW_ExtOpcode_##_N: return str8_lit(Stringify(_N));
DW_ExtOpcode_XList(X)
#undef X
default: InvalidPath; break;
}
return push_str8f(arena, "%x", kind);
}
internal String8
dw_string_from_loc_list_entry_kind(Arena *arena, DW_LLE kind)
{
NotImplemented;
return str8_zero();
}
internal String8
dw_string_from_section_kind(Arena *arena, DW_SectionKind kind)
{
NotImplemented;
return str8_zero();
}
internal String8
dw_string_from_rng_list_entry_kind(Arena *arena, DW_RLE kind)
{
NotImplemented;
return str8_zero();
}
internal String8
dw_string_from_register(Arena *arena, Arch arch, U64 reg_id)
{
String8 reg_str = str8_zero();
switch (arch) {
case Arch_Null: break;
case Arch_x86: {
switch (reg_id) {
#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_RegX64_##_N: reg_str = str8_lit(Stringify(_N)); break;
DW_Regs_X64_XList(X)
#undef X
}
} break;
case Arch_arm32: NotImplemented; break;
case Arch_arm64: NotImplemented; break;
default: InvalidPath; break;
}
if (reg_str.size == 0) {
reg_str = push_str8f(arena, "%#llx", reg_id);
}
return reg_str;
}
-16
View File
@@ -1,16 +0,0 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef DWARF_ENUM_H
#define DWARF_ENUM_H
internal String8 dw_string_from_expr_op(Arena *arena, DW_Version ver, DW_Ext ext, DW_ExprOp op);
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);
#endif // DWARF_ENUM_H
+10
View File
@@ -0,0 +1,10 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#include "dwarf/dwarf.c"
#include "dwarf/dwarf_expr.c"
#include "dwarf/dwarf_parse.c"
#include "dwarf/dwarf_coff.c"
#include "dwarf/dwarf_elf.c"
#include "dwarf/dwarf_unwind.c"
#include "dwarf/dwarf_dump.c"
+15
View File
@@ -0,0 +1,15 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef DWARF_INC_H
#define DWARF_INC_H
#include "dwarf/dwarf.h"
#include "dwarf/dwarf_expr.h"
#include "dwarf/dwarf_parse.h"
#include "dwarf/dwarf_coff.h"
#include "dwarf/dwarf_elf.h"
#include "dwarf/dwarf_unwind.h"
#include "dwarf/dwarf_dump.h"
#endif // DWARF_INC_H
+62 -62
View File
@@ -1675,7 +1675,7 @@ dw_value_class_from_attrib(DW_CompUnit *cu, DW_Attrib *attrib)
}
internal String8
dw_exprloc_from_attrib_ptr(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
dw_exprloc_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
{
DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib);
AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_ExprLoc || value_class == DW_AttribClass_Block);
@@ -1683,7 +1683,7 @@ 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)
dw_const_u128_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
{
DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib);
AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Const);
@@ -1691,7 +1691,7 @@ dw_const_u128_from_attrib_ptr(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attri
}
internal U64
dw_const_u64_from_attrib_ptr(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
dw_const_u64_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
{
DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib);
AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Const);
@@ -1699,7 +1699,7 @@ 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)
dw_const_u32_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
{
DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib);
AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Const);
@@ -1707,7 +1707,7 @@ 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)
dw_const_s64_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
{
DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib);
AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Const);
@@ -1715,7 +1715,7 @@ 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)
dw_const_s32_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
{
DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib);
AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Const);
@@ -1723,7 +1723,7 @@ 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)
dw_flag_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
{
DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib);
AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Flag);
@@ -1731,7 +1731,7 @@ 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)
dw_address_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
{
DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib);
AssertAlways(value_class == DW_AttribClass_Null ||
@@ -1756,7 +1756,7 @@ 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)
dw_block_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
{
DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib);
AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Block);
@@ -1764,7 +1764,7 @@ 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)
dw_string_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
{
DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib);
AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_String || value_class == DW_AttribClass_StrOffsetsPtr);
@@ -1772,7 +1772,7 @@ 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)
dw_line_ptr_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
{
DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib);
AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_LinePtr);
@@ -1780,7 +1780,7 @@ 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)
dw_file_from_attrib(DW_CompUnit *cu, DW_LineVMHeader *line_vm, DW_Attrib *attrib)
{
DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib);
AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Const);
@@ -1788,7 +1788,7 @@ dw_file_from_attrib_ptr(DW_CompUnit *cu, DW_LineVMHeader *line_vm, DW_Attrib *at
}
internal DW_Reference
dw_ref_from_attrib_ptr(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
dw_ref_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
{
DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib);
AssertAlways(value_class == DW_AttribClass_Null || value_class == DW_AttribClass_Reference);
@@ -1796,7 +1796,7 @@ 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)
dw_loclist_from_attrib(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
{
DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib);
AssertAlways(value_class == DW_AttribClass_Null ||
@@ -1806,7 +1806,7 @@ dw_loclist_from_attrib_ptr(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_At
}
internal Rng1U64List
dw_rnglist_from_attrib_ptr(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
dw_rnglist_from_attrib(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
{
Rng1U64List rnglist = {0};
DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib);
@@ -1837,10 +1837,10 @@ dw_attrib_from_tag(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind k
{
DW_Attrib *attrib = dw_attrib_from_tag_(tag, kind);
if (attrib->attrib_kind == DW_Attrib_Null) {
if (attrib->attrib_kind == DW_AttribKind_Null) {
if (cu && cu->tag_ht) {
DW_Attrib *ao_attrib = dw_attrib_from_tag_(tag, DW_Attrib_AbstractOrigin);
if (ao_attrib->attrib_kind == DW_Attrib_AbstractOrigin) {
DW_Attrib *ao_attrib = dw_attrib_from_tag_(tag, DW_AttribKind_AbstractOrigin);
if (ao_attrib->attrib_kind == DW_AttribKind_AbstractOrigin) {
DW_Reference ref = dw_interp_ref(input, cu, ao_attrib->form_kind, ao_attrib->form);
DW_TagNode *ref_tag = dw_tag_node_from_info_off(ref.cu, ref.info_off);
attrib = dw_attrib_from_tag_(ref_tag->tag, kind);
@@ -1855,103 +1855,103 @@ internal B32
dw_tag_has_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
{
DW_Attrib *attrib = dw_attrib_from_tag(input, cu, tag, kind);
B32 has_attrib = attrib->attrib_kind != DW_Attrib_Null;
B32 has_attrib = attrib->attrib_kind != DW_AttribKind_Null;
return has_attrib;
}
internal String8
dw_exprloc_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
dw_exprloc_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
{
return dw_exprloc_from_attrib_ptr(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
return dw_exprloc_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
}
internal String8
dw_block_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
dw_block_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
{
return dw_block_from_attrib_ptr(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
return dw_block_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
}
internal U128
dw_const_u128_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
dw_const_u128_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
{
return dw_const_u128_from_attrib_ptr(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
return dw_const_u128_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
}
internal U64
dw_const_u64_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
dw_const_u64_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
{
return dw_const_u64_from_attrib_ptr(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
return dw_const_u64_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
}
internal U32
dw_const_u32_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
dw_const_u32_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
{
return dw_const_u32_from_attrib_ptr(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
return dw_const_u32_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
}
internal U64
dw_address_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
dw_address_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
{
return dw_address_from_attrib_ptr(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
return dw_address_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
}
internal String8
dw_string_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
dw_string_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
{
return dw_string_from_attrib_ptr(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
return dw_string_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
}
internal String8
dw_line_ptr_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
dw_line_ptr_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
{
return dw_line_ptr_from_attrib_ptr(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
return dw_line_ptr_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
}
internal DW_Reference
dw_ref_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
dw_ref_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
{
return dw_ref_from_attrib_ptr(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
return dw_ref_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
}
internal DW_LocList
dw_loclist_from_attrib(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
dw_loclist_from_tag_attrib_kind(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
{
return dw_loclist_from_attrib_ptr(arena, input, cu, dw_attrib_from_tag(input, cu, tag, kind));
return dw_loclist_from_attrib(arena, input, cu, dw_attrib_from_tag(input, cu, tag, kind));
}
internal Rng1U64List
dw_rnglist_from_attrib(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
dw_rnglist_from_tag_attrib_kind(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
{
return dw_rnglist_from_attrib_ptr(arena, input, cu, dw_attrib_from_tag(input, cu, tag, kind));
return dw_rnglist_from_attrib(arena, input, cu, dw_attrib_from_tag(input, cu, tag, kind));
}
internal B32
dw_flag_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
dw_flag_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind)
{
return dw_flag_from_attrib_ptr(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
return dw_flag_from_attrib(input, cu, dw_attrib_from_tag(input, cu, tag, kind));
}
internal DW_LineFile *
dw_file_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_LineVMHeader *line_vm, DW_Tag tag, DW_AttribKind kind)
dw_file_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_LineVMHeader *line_vm, DW_Tag tag, DW_AttribKind kind)
{
return dw_file_from_attrib_ptr(cu, line_vm, dw_attrib_from_tag(input, cu, tag, kind));
return dw_file_from_attrib(cu, line_vm, dw_attrib_from_tag(input, cu, tag, kind));
}
internal B32
dw_try_byte_size_from_tag(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, U64 *byte_size_out)
{
B32 has_byte_size = dw_tag_has_attrib(input, cu, tag, DW_Attrib_ByteSize);
B32 has_bit_size = dw_tag_has_attrib(input, cu, tag, DW_Attrib_BitSize );
B32 has_byte_size = dw_tag_has_attrib(input, cu, tag, DW_AttribKind_ByteSize);
B32 has_bit_size = dw_tag_has_attrib(input, cu, tag, DW_AttribKind_BitSize );
if (has_byte_size && has_bit_size) {
Assert(!"ill formated byte size");
}
if (has_byte_size) {
*byte_size_out = dw_const_u64_from_attrib(input, cu, tag, DW_Attrib_ByteSize);
*byte_size_out = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_ByteSize);
return 1;
} else if (has_bit_size) {
U64 bit_size = dw_const_u64_from_attrib(input, cu, tag, DW_Attrib_BitSize);
U64 bit_size = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_BitSize);
*byte_size_out = bit_size / 8;
return 1;
}
@@ -1985,13 +1985,13 @@ dw_u64_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind k
DW_Attrib *attrib = dw_attrib_from_tag(input, cu, tag, kind);
DW_AttribClass attrib_class = dw_value_class_from_attrib(cu, attrib);
if (attrib_class == DW_AttribClass_Const || attrib_class == DW_AttribClass_Block) {
if (dw_tag_has_attrib(input, cu, tag, DW_Attrib_Type)) {
if (dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Type)) {
Temp scratch = scratch_begin(0,0);
DW_Reference type_ref = dw_ref_from_attrib(input, cu, tag, DW_Attrib_Type);
DW_Reference type_ref = dw_ref_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Type);
DW_Tag type_tag = {0};
dw_read_tag_cu(scratch.arena, input, type_ref.cu, type_ref.info_off, &type_tag);
U64 type_byte_size = dw_byte_size_from_tag(input, cu, type_tag);
DW_ATE type_encoding = dw_const_u64_from_attrib(input, type_ref.cu, type_tag, DW_Attrib_Encoding);
DW_ATE type_encoding = dw_const_u64_from_tag_attrib_kind(input, type_ref.cu, type_tag, DW_AttribKind_Encoding);
if (type_encoding == DW_ATE_Unsigned || type_encoding == DW_ATE_UnsignedChar) {
result = dw_interp_const64(type_byte_size, type_encoding, attrib->form_kind, attrib->form);
}
@@ -2121,15 +2121,15 @@ dw_cu_from_info_off(Arena *arena, DW_Input *input, DW_ListUnitInput lu_input, U6
dw_read_tag(arena, data, cursor, range.min, abbrev_table, abbrev_data, version, format, address_size, &cu_tag);
// TODO: handle these unit types
Assert(cu_tag.kind != DW_Tag_SkeletonUnit);
Assert(cu_tag.kind != DW_Tag_TypeUnit);
Assert(cu_tag.kind != DW_TagKind_SkeletonUnit);
Assert(cu_tag.kind != DW_TagKind_TypeUnit);
if (cu_tag.kind == DW_Tag_CompileUnit || cu_tag.kind == DW_Tag_PartialUnit) {
if (cu_tag.kind == DW_TagKind_CompileUnit || cu_tag.kind == DW_TagKind_PartialUnit) {
// fetch attribs for list sections
DW_Attrib *addr_base_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_Attrib_AddrBase );
DW_Attrib *str_offsets_base_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_Attrib_StrOffsetsBase);
DW_Attrib *rnglists_base_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_Attrib_RngListsBase );
DW_Attrib *loclists_base_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_Attrib_LocListsBase );
DW_Attrib *addr_base_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_AttribKind_AddrBase );
DW_Attrib *str_offsets_base_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_AttribKind_StrOffsetsBase);
DW_Attrib *rnglists_base_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_AttribKind_RngListsBase );
DW_Attrib *loclists_base_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_AttribKind_LocListsBase );
// interp attribs as section offsets
U64 addr_sec_off = dw_interp_sec_offset(addr_base_attrib->form_kind, addr_base_attrib->form );
@@ -2150,7 +2150,7 @@ dw_cu_from_info_off(Arena *arena, DW_Input *input, DW_ListUnitInput lu_input, U6
DW_ListUnit *loclists_lu = loclists_lu_idx < lu_input.loclist_count ? &lu_input.loclists[loclists_lu_idx] : 0;
// find compile unit base address
DW_Attrib *low_pc_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_Attrib_LowPc);
DW_Attrib *low_pc_attrib = dw_attrib_from_tag(0, 0, cu_tag, DW_AttribKind_LowPc);
U64 low_pc = dw_interp_address(address_size, max_U64, addr_lu, low_pc_attrib->form_kind, low_pc_attrib->form);
// fill out compile unit
@@ -2195,7 +2195,7 @@ dw_tag_tree_from_data(Arena *arena, String8 info_data, String8 abbrev_data, DW_C
*cursor += tag_size;
// is this sentinel tag?
if (tag.kind == DW_Tag_Null) {
if (tag.kind == DW_TagKind_Null) {
break;
}
@@ -2324,7 +2324,7 @@ dw_read_line_file(String8 data,
DW_LNCT lnct = enc_arr[enc_idx*2 + 0];
DW_FormKind form_kind = enc_arr[enc_idx*2 + 1];
DW_Form form = {0};
U64 bytes_read;
U64 bytes_read = 0;
switch (lnct) {
case DW_LNCT_Path: {
bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form);
+29 -29
View File
@@ -376,36 +376,36 @@ internal DW_Reference dw_interp_ref (DW_Input *input, DW_CompUnit *cu, DW
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);
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);
internal String8 dw_exprloc_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal U128 dw_const_u128_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal U64 dw_const_u64_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal U32 dw_const_u32_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal S64 dw_const_s64_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal S32 dw_const_s32_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal B32 dw_flag_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal U64 dw_address_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal String8 dw_block_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal String8 dw_string_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal String8 dw_line_ptr_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal DW_LineFile * dw_file_from_attrib (DW_CompUnit *cu, DW_LineVMHeader *line_vm, DW_Attrib *attrib);
internal DW_Reference dw_ref_from_attrib (DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal DW_LocList dw_loclist_from_attrib (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
internal Rng1U64List dw_rnglist_from_attrib (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
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);
internal String8 dw_exprloc_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal U128 dw_const_u128_from_tag_attrib_kind(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal U64 dw_const_u64_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal U32 dw_const_u32_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal B32 dw_flag_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal U64 dw_address_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal String8 dw_block_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal String8 dw_string_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal String8 dw_line_ptr_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal String8 dw_line_ptr_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal DW_LineFile * dw_file_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_LineVMHeader *line_vm, DW_Tag tag, DW_AttribKind kind);
internal DW_Reference dw_ref_from_tag_attrib_kind (DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal DW_LocList dw_loclist_from_tag_attrib_kind (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal Rng1U64List dw_rnglist_from_tag_attrib_kind (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
// compile unit
+19 -17
View File
@@ -119,10 +119,10 @@ enum
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,
@@ -169,7 +169,7 @@ enum
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,
@@ -185,22 +185,22 @@ 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,
};
@@ -271,7 +271,7 @@ typedef U32 ELF_DynTag;
enum
{
ELF_DynTag_Null = 0,
ELF_DynTag_Needed = 1,
ELF_DynTag_PltRelsz = 2,
ELF_DynTag_PltGot = 3,
@@ -305,10 +305,10 @@ enum
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,
@@ -322,7 +322,7 @@ enum
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,
@@ -336,7 +336,7 @@ enum
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,
@@ -671,6 +671,9 @@ typedef enum ELF_Identifier
ELF_Identifier_Max = 16,
} ELF_Identifier;
read_only global U8 elf_magic[] = {0x7f, 'E', 'L', 'F'};
read_only global String8 elf_magic_string = {elf_magic, sizeof(elf_magic)};
typedef U16 ELF_Type;
typedef enum ELF_TypeEnum
{
@@ -951,10 +954,10 @@ 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,
};
@@ -975,7 +978,7 @@ typedef struct ELF_Chdr64
////////////////////////////////
internal ELF_Hdr64 elf_hdr64_from_ehdr32(ELF_Hdr32 h32);
internal ELF_Hdr64 elf_hdr64_from_hdr32(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);
@@ -993,4 +996,3 @@ internal String8 elf_string_from_class(Arena *arena, ELF_Class v);
internal Arch arch_from_elf_machine(ELF_MachineKind machine);
#endif // ELF_H
+128 -105
View File
@@ -1,143 +1,166 @@
// 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;
}
//- rjf: top-level binary parsing
internal ELF_BinInfo
elf_bin_from_data(String8 data)
internal ELF_Bin
elf_bin_from_data(Arena *arena, String8 data)
{
ELF_Hdr64 hdr64 = {0};
Rng1U64 sh_name_range = rng_1u64(0,0);
if (elf_check_magic(data)) {
ELF_Bin bin = {0};
if(str8_match(str8_prefix(data, elf_magic_string.size), elf_magic_string, 0) &&
data.size >= ELF_Identifier_Max)
{
//- rjf: parse sig/header
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);
switch(sig[ELF_Identifier_Class])
{
default:
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))
{
bin.hdr = 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))
{
bin.sh_name_range = rng_1u64(shdr.sh_offset, shdr.sh_offset + shdr.sh_size);
}
}
}break;
case ELF_Class_64:
{
ELF_Hdr64 hdr64 = {0};
U64 hdr_size = str8_deserial_read_struct(data, 0, &hdr64);
if(hdr_size == sizeof(hdr64))
{
bin.hdr = 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))
{
bin.sh_name_range = rng_1u64(shdr.sh_offset, shdr.sh_offset + shdr.sh_size);
}
}
}break;
}
//- rjf: gather all shdrs
{
ELF_Hdr64 *hdr = &bin.hdr;
bin.shdrs.count = hdr->e_shnum;
bin.shdrs.v = push_array(arena, ELF_Shdr64, hdr->e_shnum);
Rng1U64 shdr_range = rng_1u64(hdr->e_shoff, hdr->e_shoff + hdr->e_shentsize*hdr->e_shnum);
String8 shdr_data = str8_substr(data, shdr_range);
for EachIndex(shdr_idx, hdr->e_shnum)
{
switch(hdr->e_ident[ELF_Identifier_Class])
{
default:
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);
bin.shdrs.v[shdr_idx] = elf_shdr64_from_shdr32(shdr32);
}break;
case ELF_Class_64:
{
str8_deserial_read_struct(shdr_data, shdr_idx * sizeof(ELF_Shdr64), &bin.shdrs.v[shdr_idx]);
}break;
}
}
} 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);
}
//- rjf: gather all phdrs
{
ELF_Hdr64 *hdr = &bin.hdr;
bin.phdrs.count = hdr->e_phnum;
bin.phdrs.v = push_array(arena, ELF_Phdr64, hdr->e_phnum);
Rng1U64 phdr_range = rng_1u64(hdr->e_phoff, hdr->e_phoff + hdr->e_phentsize*hdr->e_phnum);
String8 phdr_data = str8_substr(data, phdr_range);
for EachIndex(phdr_idx, hdr->e_phnum)
{
switch(hdr->e_ident[ELF_Identifier_Class])
{
default:
case ELF_Class_None:
{}break;
case ELF_Class_32:
{
ELF_Phdr32 phdr32 = {0};
str8_deserial_read_struct(phdr_data, phdr_idx * sizeof(ELF_Phdr32), &phdr32);
bin.phdrs.v[phdr_idx] = elf_phdr64_from_phdr32(phdr32);
}break;
case ELF_Class_64:
{
str8_deserial_read_struct(phdr_data, phdr_idx * sizeof(ELF_Phdr64), &bin.phdrs.v[phdr_idx]);
}break;
}
}
} 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;
return bin;
}
//- rjf: extra bin info extraction
internal String8
elf_name_from_shdr64(String8 raw_data, ELF_Hdr64 *hdr, Rng1U64 sh_name_range, ELF_Shdr64 *shdr)
elf_name_from_shdr64(String8 data, ELF_Bin *bin, ELF_Shdr64 *shdr)
{
String8 sh_names = str8_substr(raw_data, sh_name_range);
String8 sh_names = str8_substr(data, bin->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)
elf_base_addr_from_bin(ELF_Bin *bin)
{
NotImplemented;
return 0;
U64 base_vaddr = 0;
for EachIndex(phdr_idx, bin->phdrs.count)
{
ELF_Phdr64 *phdr = &bin->phdrs.v[phdr_idx];
if(phdr->p_type == ELF_PType_Load &&
(base_vaddr == 0 || phdr->p_vaddr < base_vaddr))
{
base_vaddr = phdr->p_vaddr;
}
}
return base_vaddr;
}
internal B32
elf_parse_debug_link(String8 raw_data, ELF_BinInfo *elf, ELF_GnuDebugLink *debug_link_out)
internal ELF_GnuDebugLink
elf_gnu_debug_link_from_bin(String8 raw_data, ELF_Bin *bin)
{
Temp scratch = scratch_begin(0,0);
B32 is_debug_link_present = 0;
ELF_Shdr64Array sections = elf_shdr64_array_from_bin(scratch.arena, raw_data, &elf->hdr);
for (U64 i = 0; i < sections.count; ++i) {
ELF_Shdr64 *shdr = &sections.v[i];
String8 name = elf_name_from_shdr64(raw_data, &elf->hdr, elf->sh_name_range, shdr);
if (str8_match(name, str8_lit(".gnu_debuglink"), 0)) {
ELF_GnuDebugLink result = {0};
for EachIndex(idx, bin->shdrs.count)
{
ELF_Shdr64 *shdr = &bin->shdrs.v[idx];
String8 name = elf_name_from_shdr64(raw_data, bin, 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;
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;
result.path = path;
result.checksum = checksum;
break;
}
}
scratch_end(scratch);
return is_debug_link_present;
return result;
}
+33 -17
View File
@@ -5,32 +5,48 @@
#define ELF_PARSE_H
////////////////////////////////
//~ rjf: Parsed Structure Types
typedef struct ELF_BinInfo
typedef struct ELF_Shdr64Array ELF_Shdr64Array;
struct ELF_Shdr64Array
{
ELF_Shdr64 *v;
U64 count;
};
typedef struct ELF_Phdr64Array ELF_Phdr64Array;
struct ELF_Phdr64Array
{
ELF_Phdr64 *v;
U64 count;
};
typedef struct ELF_Bin ELF_Bin;
struct ELF_Bin
{
ELF_Hdr64 hdr;
Rng1U64 sh_name_range;
} ELF_BinInfo;
Rng1U64 sh_name_range;
ELF_Shdr64Array shdrs;
ELF_Phdr64Array phdrs;
};
typedef struct ELF_Shdr64Array
{
U64 count;
ELF_Shdr64 *v;
} ELF_Shdr64Array;
typedef struct ELF_GnuDebugLink
typedef struct ELF_GnuDebugLink ELF_GnuDebugLink;
struct ELF_GnuDebugLink
{
String8 path;
U32 checksum;
} ELF_GnuDebugLink;
U32 checksum;
};
////////////////////////////////
//~ rjf: Parsing Functions
internal B32 elf_check_magic(String8 data);
internal ELF_BinInfo elf_bin_from_data(String8 data);
//- rjf: top-level binary parsing
internal ELF_Bin elf_bin_from_data(Arena *arena, 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);
//- rjf: extra bin info extraction
internal B32 elf_is_dwarf_present_from_bin(String8 data, ELF_Bin *bin);
internal String8 elf_name_from_shdr64(String8 raw_data, ELF_Bin *bin, ELF_Shdr64 *shdr);
internal U64 elf_base_addr_from_bin(ELF_Bin *bin);
internal ELF_GnuDebugLink elf_gnu_debug_link_from_bin(String8 raw_data, ELF_Bin *bin);
#endif // ELF_PARSE_H
+1
View File
@@ -93,6 +93,7 @@ E_ExprKindTable:
{ Cast Null 1 "cast(" ")" "" "" }
{ Sizeof UnaryPrefix 1 "sizeof " "" "" "" }
{ Typeof UnaryPrefix 1 "typeof " "" "" "" }
{ Symbolof UnaryPrefix 1 "symbolof " "" "" "" }
{ ByteSwap UnaryPrefix 1 "bswap " "" "" "" }
{ Pos UnaryPrefix 2 "+" "" "" "" }
+28 -25
View File
@@ -1350,38 +1350,41 @@ e_key_wrapf(E_Key key, char *fmt, ...)
////////////////////////////////
//~ rjf: Eval Info Extraction
internal U64
e_base_offset_from_eval(E_Eval eval)
internal Rng1U64
e_range_from_eval(E_Eval eval)
{
if(e_type_kind_is_pointer_or_ref(e_type_kind_from_key(e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative))))
// rjf: choose base offset
U64 base_offset = 0;
{
eval = e_value_eval_from_eval(eval);
}
return eval.value.u64;
}
internal U64
e_range_size_from_eval(E_Eval eval)
{
U64 result = KB(16);
{
E_TypeKey type_core = e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind type_core_kind = e_type_kind_from_key(type_core);
B32 got_size = 0;
// rjf: try getting size from intrinsic type (e.g. arrays/etc.)
if(!got_size)
E_Eval base_off_eval = eval;
if(e_type_kind_is_pointer_or_ref(e_type_kind_from_key(e_type_key_unwrap(base_off_eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative))))
{
if(type_core_kind == E_TypeKind_Array ||
type_core_kind == E_TypeKind_Struct ||
type_core_kind == E_TypeKind_Union ||
type_core_kind == E_TypeKind_Class)
base_off_eval = e_value_eval_from_eval(base_off_eval);
}
base_offset = base_off_eval.value.u64;
}
// rjf: choose size
U64 size = KB(16);
{
E_TypeKey type_key = e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind type_kind = e_type_kind_from_key(type_key);
if(type_kind == E_TypeKind_Ptr)
{
E_Eval ptee_eval = e_eval_wrapf(eval, "*$");
U64 ptee_size = e_type_byte_size_from_key(ptee_eval.irtree.type_key);
if(ptee_size > 8)
{
result = e_type_byte_size_from_key(type_core);
got_size = 1;
size = ptee_size;
}
}
else if(eval.irtree.mode == E_Mode_Offset)
{
size = e_type_byte_size_from_key(type_key);
}
}
Rng1U64 result = r1u64(base_offset, base_offset+size);
return result;
}
+5 -3
View File
@@ -57,9 +57,11 @@ union E_Value
U64 u64;
U32 u32;
U16 u16;
U8 u8;
S64 s64;
S32 s32;
S32 s16;
S16 s16;
S8 s8;
F64 f64;
F32 f32;
};
@@ -760,6 +762,7 @@ struct E_BaseCtx
E_Module *modules;
U64 modules_count;
E_Module *primary_module;
DI_MatchStore *dbgi_match_store;
// rjf: space hooks
void *space_rw_user_data;
@@ -1291,8 +1294,7 @@ internal E_Key e_key_wrapf(E_Key key, char *fmt, ...);
////////////////////////////////
//~ rjf: Eval Info Extraction
internal U64 e_base_offset_from_eval(E_Eval eval);
internal U64 e_range_size_from_eval(E_Eval eval);
internal Rng1U64 e_range_from_eval(E_Eval eval);
////////////////////////////////
//~ rjf: Debug Functions
+4
View File
@@ -206,6 +206,10 @@ e_interpret(String8 bytecode)
result.code = E_InterpretationCode_BadMemRead;
goto done;
}
if(e_space_match(selected_space, e_interpret_ctx->reg_space))
{
selected_space = e_interpret_ctx->primary_space;
}
}break;
case RDI_EvalOp_RegRead:
+261 -256
View File
@@ -644,51 +644,60 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
{
// rjf: unpack left-hand-side
E_Expr *lhs = expr->first;
E_IRTreeAndType lhs_irtree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, 0, 1, lhs);
e_msg_list_concat_in_place(&result.msgs, &lhs_irtree.msgs);
// rjf: try all IR trees in chain
for(E_IRTreeAndType *lhs_irtree_try = &lhs_irtree; lhs_irtree_try != 0; lhs_irtree_try = lhs_irtree_try->prev)
// rjf: try left-hand-side, first *without* autohooks, then *with* autohooks.
for(B32 autohooks_enabled = 0; autohooks_enabled < 2; autohooks_enabled += 1)
{
// rjf: gather inherited lenses from the left-hand-side
E_IRTreeAndType lhs_irtree_try = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, !autohooks_enabled, 1, lhs);
for(E_IRTreeAndType *lhs_irtree_try_chain = &lhs_irtree_try; lhs_irtree_try_chain != 0; lhs_irtree_try_chain = lhs_irtree_try_chain->prev)
{
E_TypeKey k = lhs_irtree_try->type_key;
E_TypeKind kind = e_type_kind_from_key(k);
for(;kind == E_TypeKind_Lens;)
// rjf: pick access hook based on type
E_Type *lhs_type = e_type_from_key(lhs_irtree_try_chain->type_key);
E_TypeAccessFunctionType *lhs_access = lhs_type->access;
for(E_Type *lens_type = lhs_type;
lens_type->kind == E_TypeKind_Lens || lens_type->kind == E_TypeKind_Set;
lens_type = e_type_from_key(lens_type->direct_type_key))
{
E_Type *lens_type = e_type_from_key(k);
if((lens_type->flags & E_TypeFlag_InheritedByMembers && expr->kind == E_ExprKind_MemberAccess) ||
(lens_type->flags & E_TypeFlag_InheritedByElements && expr->kind == E_ExprKind_ArrayIndex))
if(lens_type->access != 0)
{
e_type_key_list_push_front(scratch.arena, &inherited_lenses, k);
lhs_access = lens_type->access;
break;
}
k = e_type_key_direct(k);
kind = e_type_kind_from_key(k);
}
}
// rjf: pick access hook based on type
E_Type *lhs_type = e_type_from_key(lhs_irtree_try->type_key);
E_TypeAccessFunctionType *lhs_access = lhs_type->access;
for(E_Type *lens_type = lhs_type;
lens_type->kind == E_TypeKind_Lens || lens_type->kind == E_TypeKind_Set;
lens_type = e_type_from_key(lens_type->direct_type_key))
{
if(lens_type->access != 0)
if(lhs_access == 0)
{
lhs_access = lens_type->access;
lhs_access = E_TYPE_ACCESS_FUNCTION_NAME(default);
}
// rjf: call into hook to do access
E_IRTreeAndType new_result_maybe = lhs_access(arena, parent, expr, lhs_irtree_try_chain);
// rjf: if we got a valid result -> gather info from this irtree
if(new_result_maybe.root != &e_irnode_nil)
{
E_TypeKey k = lhs_irtree_try_chain->type_key;
E_TypeKind kind = e_type_kind_from_key(k);
for(;kind == E_TypeKind_Lens;)
{
E_Type *lens_type = e_type_from_key(k);
if((lens_type->flags & E_TypeFlag_InheritedByMembers && expr->kind == E_ExprKind_MemberAccess) ||
(lens_type->flags & E_TypeFlag_InheritedByElements && expr->kind == E_ExprKind_ArrayIndex))
{
e_type_key_list_push_front(scratch.arena, &inherited_lenses, k);
}
k = e_type_key_direct(k);
kind = e_type_kind_from_key(k);
}
e_msg_list_concat_in_place(&result.msgs, &lhs_irtree_try_chain->msgs);
}
// rjf: if we got a valid result -> we're done
if(new_result_maybe.root != &e_irnode_nil)
{
result = new_result_maybe;
break;
}
}
if(lhs_access == 0)
{
lhs_access = E_TYPE_ACCESS_FUNCTION_NAME(default);
}
// rjf: call into hook to do access
result = lhs_access(arena, parent, expr, lhs_irtree_try);
// rjf: end chain if we found a result
if(result.root != &e_irnode_nil)
{
break;
@@ -727,7 +736,11 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
String8 full_qualified_name = str8_list_join(scratch.arena, &parts, &(StringJoin){.sep = str8_lit(".")});
E_Expr *leaf_expr_name = e_push_expr(scratch.arena, E_ExprKind_LeafIdentifier, r1u64(0, 0));
leaf_expr_name->string = full_qualified_name;
result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, disallow_autohooks, leaf_expr_name);
E_IRTreeAndType new_result_maybe = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, disallow_autohooks, leaf_expr_name);
if(new_result_maybe.root != &e_irnode_nil)
{
result = new_result_maybe;
}
}
}
}break;
@@ -828,14 +841,18 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
e_msg_list_concat_in_place(&result.msgs, &cast_irtree.msgs);
E_TypeKey cast_type = cast_irtree.type_key;
E_TypeKind cast_type_kind = e_type_kind_from_key(cast_type);
E_TypeKey cast_type_unwrapped = e_type_key_unwrap(cast_irtree.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind cast_type_unwrapped_kind = e_type_kind_from_key(cast_type_unwrapped);
U64 cast_type_byte_size = e_type_byte_size_from_key(cast_type);
E_IRTreeAndType casted_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, casted_expr);
e_msg_list_concat_in_place(&result.msgs, &casted_tree.msgs);
E_TypeKey casted_type = e_type_key_unwrap(casted_tree.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind casted_type_kind = e_type_kind_from_key(casted_type);
E_TypeKey casted_type_unwrapped = e_type_key_unwrap(casted_type, E_TypeUnwrapFlag_Bitfields|E_TypeUnwrapFlag_AllDecorative);
E_TypeKind casted_type_unwrapped_kind = e_type_kind_from_key(casted_type_unwrapped);
U64 casted_type_byte_size = e_type_byte_size_from_key(casted_type);
U8 in_group = e_type_group_from_kind(casted_type_kind);
U8 out_group = e_type_group_from_kind(cast_type_kind);
U8 in_group = e_type_group_from_kind(casted_type_unwrapped_kind);
U8 out_group = e_type_group_from_kind(cast_type_unwrapped_kind);
RDI_EvalConversionKind conversion_rule = rdi_eval_conversion_kind_from_typegroups(in_group, out_group);
// rjf: bad conditions? -> error if applicable, exit
@@ -867,7 +884,11 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
{
new_tree = e_irtree_convert_lo(arena, in_tree, out_group, in_group);
}
if(cast_type_byte_size < casted_type_byte_size && e_type_kind_is_integer(cast_type_kind))
if(cast_type_byte_size < casted_type_byte_size && e_type_kind_is_integer(cast_type_unwrapped_kind))
{
new_tree = e_irtree_trunc(arena, in_tree, cast_type);
}
if(e_type_kind_is_signed(cast_type_unwrapped_kind) && e_type_kind_is_integer(casted_type_unwrapped_kind) && !e_type_kind_is_signed(casted_type_unwrapped_kind))
{
new_tree = e_irtree_trunc(arena, in_tree, cast_type);
}
@@ -932,6 +953,53 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
result.mode = E_Mode_Null;
}break;
//- rjf: symbolof
case E_ExprKind_Symbolof:
{
E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, expr->first);
E_IRNode *r_value_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_tree.type_key);
E_OpList oplist = e_oplist_from_irtree(scratch.arena, r_value_tree);
String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist);
E_Interpretation interpretation = e_interpret(bytecode);
E_Module *module = &e_module_nil;
U32 rdi_idx = 0;
for EachIndex(idx, e_base_ctx->modules_count)
{
E_Module *m = &e_base_ctx->modules[idx];
if(e_space_match(interpretation.space, m->space) && contains_1u64(m->vaddr_range, interpretation.value.u64))
{
module = m;
rdi_idx = (U32)idx;
break;
}
}
if(module != &e_module_nil)
{
U64 voff = interpretation.value.u64 - module->vaddr_range.min;
U64 new_vaddr = 0;
RDI_Procedure *p = rdi_procedure_from_voff(module->rdi, voff);
RDI_GlobalVariable *g = rdi_global_variable_from_voff(module->rdi, voff);
U32 type_idx = 0;
if(p->name_string_idx != 0)
{
type_idx = p->type_idx;
new_vaddr = module->vaddr_range.min + rdi_first_voff_from_procedure(module->rdi, p);
}
else if(g->name_string_idx != 0)
{
type_idx = g->type_idx;
new_vaddr = module->vaddr_range.min + g->voff;
}
if(type_idx != 0)
{
RDI_TypeNode *t = rdi_element_from_name_idx(module->rdi, TypeNodes, type_idx);
result.root = e_irtree_const_u(arena, new_vaddr);
result.mode = E_Mode_Value;
result.type_key = e_type_key_ext(e_type_kind_from_rdi(t->kind), type_idx, rdi_idx);
}
}
}break;
//- rjf: byteswap
case E_ExprKind_ByteSwap:
{
@@ -1385,12 +1453,15 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
e_msg_list_concat_in_place(&result.msgs, &casted_tree.msgs);
E_TypeKey cast_type = lhs_irtree.type_key;
E_TypeKind cast_type_kind = e_type_kind_from_key(cast_type);
E_TypeKey cast_type_unwrapped = e_type_key_unwrap(lhs_irtree.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind cast_type_unwrapped_kind = e_type_kind_from_key(cast_type_unwrapped);
U64 cast_type_byte_size = e_type_byte_size_from_key(cast_type);
E_TypeKey casted_type = casted_tree.type_key;
E_TypeKind casted_type_kind = e_type_kind_from_key(casted_type);
E_TypeKey casted_type_unwrapped = e_type_key_unwrap(casted_type, E_TypeUnwrapFlag_Bitfields|E_TypeUnwrapFlag_AllDecorative);
E_TypeKind casted_type_unwrapped_kind = e_type_kind_from_key(casted_type_unwrapped);
U64 casted_type_byte_size = e_type_byte_size_from_key(casted_type);
U8 in_group = e_type_group_from_kind(casted_type_kind);
U8 out_group = e_type_group_from_kind(cast_type_kind);
U8 in_group = e_type_group_from_kind(casted_type_unwrapped_kind);
U8 out_group = e_type_group_from_kind(cast_type_unwrapped_kind);
RDI_EvalConversionKind conversion_rule = rdi_eval_conversion_kind_from_typegroups(in_group, out_group);
// rjf: bad conditions? -> error if applicable, exit
@@ -1414,7 +1485,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
break;
}
// rjf: generate casted result
// rjf: generate
{
E_IRNode *in_tree = e_irtree_resolve_to_value(arena, casted_tree.mode, casted_tree.root, casted_type);
E_IRNode *new_tree = in_tree;
@@ -1422,7 +1493,11 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
{
new_tree = e_irtree_convert_lo(arena, in_tree, out_group, in_group);
}
if(cast_type_byte_size < casted_type_byte_size && e_type_kind_is_integer(cast_type_kind))
if(cast_type_byte_size < casted_type_byte_size && e_type_kind_is_integer(cast_type_unwrapped_kind))
{
new_tree = e_irtree_trunc(arena, in_tree, cast_type);
}
if(e_type_kind_is_signed(cast_type_unwrapped_kind) && e_type_kind_is_integer(casted_type_unwrapped_kind) && !e_type_kind_is_signed(casted_type_unwrapped_kind))
{
new_tree = e_irtree_trunc(arena, in_tree, cast_type);
}
@@ -1599,7 +1674,6 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
String8 qualifier = expr->qualifier;
String8 string = expr->string;
String8 string__redirected = string;
String8List namespaceified_strings = {0};
B32 string_mapped = 0;
B32 string_is_implicit_member_name = 0;
E_TypeKey mapped_type_key = zero_struct;
@@ -1617,7 +1691,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
{
//- rjf: try to map identifier via this path
E_IdentifierResolutionPath path = identifier_resolution_rule->paths[path_idx];
switch(path)
ProfScope("identifier resolution %i", path) switch(path)
{
default:{}break;
@@ -1673,7 +1747,8 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
for(E_IRTreeAndType *prev = parent; prev != 0; prev = prev->prev)
{
E_Expr *access = e_expr_irext_member_access(scratch.arena, &e_expr_nil, prev, string);
E_IRTreeAndType access_irtree = e_push_irtree_and_type_from_expr(scratch.arena, root_parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, access);
E_IRTreeAndType access_parent = {&e_irnode_nil};
E_IRTreeAndType access_irtree = e_push_irtree_and_type_from_expr(scratch.arena, prev->prev ? prev->prev : &access_parent, &e_default_identifier_resolution_rule, 1, 1, access);
if(access_irtree.root != &e_irnode_nil)
{
string_mapped = 1;
@@ -1682,7 +1757,10 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = access_irtree.mode;
e_msg_list_concat_in_place(&result.msgs, &access_irtree.msgs);
break;
if(!prev->auto_hook)
{
break;
}
}
}
}break;
@@ -1739,239 +1817,166 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
}
}break;
//- rjf: globals / procedures / types / constants
case E_IdentifierResolutionPath_Globals:
case E_IdentifierResolutionPath_Procedures:
case E_IdentifierResolutionPath_ThreadLocals:
case E_IdentifierResolutionPath_Constants:
//- rjf: built-in constants
case E_IdentifierResolutionPath_BuiltInConstants:
{
//- rjf: form namespaceified fallback versions of this lookup string
if(!string_mapped)
// rjf: "true"
if(!string_mapped && str8_match(string, str8_lit("true"), 0))
{
E_Module *module = e_base_ctx->primary_module;
RDI_Parsed *rdi = module->rdi;
RDI_Procedure *procedure = e_cache->thread_ip_procedure;
U64 name_size = 0;
U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size);
String8 containing_procedure_name = str8(name_ptr, name_size);
U64 last_past_scope_resolution_pos = 0;
for(;;)
{
U64 past_next_dbl_colon_pos = str8_find_needle(containing_procedure_name, last_past_scope_resolution_pos, str8_lit("::"), 0)+2;
U64 past_next_dot_pos = str8_find_needle(containing_procedure_name, last_past_scope_resolution_pos, str8_lit("."), 0)+1;
U64 past_next_scope_resolution_pos = Min(past_next_dbl_colon_pos, past_next_dot_pos);
if(past_next_scope_resolution_pos >= containing_procedure_name.size)
{
break;
}
String8 new_namespace_prefix_possibility = str8_prefix(containing_procedure_name, past_next_scope_resolution_pos);
String8 namespaceified_string = push_str8f(scratch.arena, "%S%S", new_namespace_prefix_possibility, string);
str8_list_push_front(scratch.arena, &namespaceified_strings, namespaceified_string);
last_past_scope_resolution_pos = past_next_scope_resolution_pos;
}
string_mapped = 1;
E_OpList oplist = {0};
e_oplist_push_uconst(arena, &oplist, 1);
mapped_type_key = e_type_key_basic(E_TypeKind_Bool);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Value;
}
//- rjf: try globals
if(path == E_IdentifierResolutionPath_Globals && !string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("global"), 0)))
// rjf: "false"
if(!string_mapped && str8_match(string, str8_lit("false"), 0))
{
for(U64 module_idx = 0; module_idx < e_base_ctx->modules_count; module_idx += 1)
{
E_Module *module = &e_base_ctx->modules[module_idx];
RDI_Parsed *rdi = module->rdi;
RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_GlobalVariables);
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, string.str, string.size);
U32 matches_count = 0;
U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count);
for(String8Node *n = namespaceified_strings.first;
n != 0 && matches_count == 0;
n = n->next)
{
node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size);
matches_count = 0;
matches = rdi_matches_from_map_node(rdi, node, &matches_count);
}
if(matches_count != 0)
{
U32 match_idx = matches[matches_count-1];
RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, match_idx);
U32 type_idx = global_var->type_idx;
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx);
E_OpList oplist = {0};
e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + global_var->voff));
string_mapped = 1;
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Offset;
mapped_bytecode_space = module->space;
break;
}
}
string_mapped = 1;
E_OpList oplist = {0};
e_oplist_push_uconst(arena, &oplist, 0);
mapped_type_key = e_type_key_basic(E_TypeKind_Bool);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Value;
}
//- rjf: try thread-locals
if(path == E_IdentifierResolutionPath_ThreadLocals && !string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("thread_local"), 0)))
}break;
//- rjf: built-in types
case E_IdentifierResolutionPath_BuiltInTypes:
{
mapped_type_key = e_leaf_builtin_type_key_from_name(string);
string_mapped = !e_type_key_match(mapped_type_key, e_type_key_zero());
}break;
//- rjf: debug info matches
case E_IdentifierResolutionPath_DebugInfoMatch:
{
if(!string_mapped && e_base_ctx->dbgi_match_store != 0 && (qualifier.size == 0 || str8_match(qualifier, str8_lit("symbol"), 0)))
{
for(U64 module_idx = 0; module_idx < e_base_ctx->modules_count; module_idx += 1)
DI_Match match = di_match_from_name(e_base_ctx->dbgi_match_store, string, 0);
if(match.idx == 0)
{
E_Module *module = &e_base_ctx->modules[module_idx];
RDI_Parsed *rdi = module->rdi;
RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_ThreadVariables);
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, string.str, string.size);
U32 matches_count = 0;
U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count);
for(String8Node *n = namespaceified_strings.first;
n != 0 && matches_count == 0;
n = n->next)
String8List namespaceified_strings = {0};
{
node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size);
matches_count = 0;
matches = rdi_matches_from_map_node(rdi, node, &matches_count);
}
if(matches_count != 0)
{
U32 match_idx = matches[matches_count-1];
RDI_ThreadVariable *thread_var = rdi_element_from_name_idx(rdi, ThreadVariables, match_idx);
U32 type_idx = thread_var->type_idx;
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx);
E_OpList oplist = {0};
e_oplist_push_op(arena, &oplist, RDI_EvalOp_TLSOff, e_value_u64(thread_var->tls_off));
string_mapped = 1;
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Offset;
mapped_bytecode_space = module->space;
break;
}
}
}
//- rjf: try constants
if(path == E_IdentifierResolutionPath_Constants && !string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("constant"), 0)))
{
if(str8_match(string, str8_lit("true"), 0))
{
string_mapped = 1;
E_OpList oplist = {0};
e_oplist_push_uconst(arena, &oplist, 1);
mapped_type_key = e_type_key_basic(E_TypeKind_Bool);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Value;
}
else if(str8_match(string, str8_lit("false"), 0))
{
string_mapped = 1;
E_OpList oplist = {0};
e_oplist_push_uconst(arena, &oplist, 0);
mapped_type_key = e_type_key_basic(E_TypeKind_Bool);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Value;
}
else for(U64 module_idx = 0; module_idx < e_base_ctx->modules_count; module_idx += 1)
{
E_Module *module = &e_base_ctx->modules[module_idx];
RDI_Parsed *rdi = module->rdi;
RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Constants);
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, string.str, string.size);
U32 matches_count = 0;
U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count);
for(String8Node *n = namespaceified_strings.first;
n != 0 && matches_count == 0;
n = n->next)
{
node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size);
matches_count = 0;
matches = rdi_matches_from_map_node(rdi, node, &matches_count);
}
if(matches_count != 0)
{
U32 match_idx = matches[matches_count-1];
RDI_Constant *constant = rdi_element_from_name_idx(rdi, Constants, match_idx);
U32 type_idx = constant->type_idx;
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx);
RDI_U32 constant_value_off = *rdi_element_from_name_idx(rdi, ConstantValueTable, constant->constant_value_idx);
RDI_U32 constant_value_size = *rdi_element_from_name_idx(rdi, ConstantValueTable, constant->constant_value_idx+1) - constant_value_off;
if(constant_value_size <= 8)
E_Module *module = e_base_ctx->primary_module;
RDI_Parsed *rdi = module->rdi;
RDI_Procedure *procedure = e_cache->thread_ip_procedure;
U64 name_size = 0;
U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size);
String8 containing_procedure_name = str8(name_ptr, name_size);
U64 last_past_scope_resolution_pos = 0;
for(;;)
{
RDI_U64 constant_value_data_size = 0;
RDI_U8 *constant_value_data = rdi_table_from_name(rdi, ConstantValueData, &constant_value_data_size);
if(0 <= constant_value_off && constant_value_off + constant_value_size <= constant_value_data_size)
U64 past_next_dbl_colon_pos = str8_find_needle(containing_procedure_name, last_past_scope_resolution_pos, str8_lit("::"), 0)+2;
U64 past_next_dot_pos = str8_find_needle(containing_procedure_name, last_past_scope_resolution_pos, str8_lit("."), 0)+1;
U64 past_next_scope_resolution_pos = Min(past_next_dbl_colon_pos, past_next_dot_pos);
if(past_next_scope_resolution_pos >= containing_procedure_name.size)
{
RDI_U64 value = 0;
MemoryCopy(&value, constant_value_data+constant_value_off, constant_value_size);
E_OpList oplist = {0};
e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(value));
string_mapped = 1;
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Value;
mapped_bytecode_space = module->space;
break;
}
String8 new_namespace_prefix_possibility = str8_prefix(containing_procedure_name, past_next_scope_resolution_pos);
String8 namespaceified_string = push_str8f(scratch.arena, "%S%S", new_namespace_prefix_possibility, string);
str8_list_push_front(scratch.arena, &namespaceified_strings, namespaceified_string);
last_past_scope_resolution_pos = past_next_scope_resolution_pos;
}
}
for(String8Node *n = namespaceified_strings.first; n != 0; n = n->next)
{
match = di_match_from_name(e_base_ctx->dbgi_match_store, n->string, 0);
if(match.idx != 0)
{
break;
}
}
}
}
//- rjf: try procedures
if(path == E_IdentifierResolutionPath_Procedures && !string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("procedure"), 0)))
{
for(U64 module_idx = 0; module_idx < e_base_ctx->modules_count; module_idx += 1)
if(match.idx != 0 && match.dbgi_idx < e_base_ctx->modules_count)
{
E_Module *module = &e_base_ctx->modules[module_idx];
E_Module *module = &e_base_ctx->modules[match.dbgi_idx];
RDI_Parsed *rdi = module->rdi;
RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures);
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, string.str, string.size);
U32 matches_count = 0;
U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count);
for(String8Node *n = namespaceified_strings.first;
n != 0 && matches_count == 0;
n = n->next)
switch(match.section)
{
node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size);
matches_count = 0;
matches = rdi_matches_from_map_node(rdi, node, &matches_count);
}
if(matches_count != 0)
{
U32 match_idx = matches[matches_count-1];
RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, match_idx);
RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx);
U64 voff = *rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_first);
U32 type_idx = procedure->type_idx;
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx);
E_OpList oplist = {0};
e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + voff));
string_mapped = 1;
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Value;
mapped_bytecode_space = module->space;
break;
default:{}break;
case RDI_SectionKind_GlobalVariables:
{
RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, match.idx);
U32 type_idx = global_var->type_idx;
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx);
E_OpList oplist = {0};
e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + global_var->voff));
string_mapped = 1;
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)match.dbgi_idx);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Offset;
mapped_bytecode_space = module->space;
}break;
case RDI_SectionKind_ThreadVariables:
{
RDI_ThreadVariable *thread_var = rdi_element_from_name_idx(rdi, ThreadVariables, match.idx);
U32 type_idx = thread_var->type_idx;
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx);
E_OpList oplist = {0};
e_oplist_push_op(arena, &oplist, RDI_EvalOp_TLSOff, e_value_u64(thread_var->tls_off));
string_mapped = 1;
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)match.dbgi_idx);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Offset;
mapped_bytecode_space = module->space;
}break;
case RDI_SectionKind_Constants:
{
RDI_Constant *constant = rdi_element_from_name_idx(rdi, Constants, match.idx);
U32 type_idx = constant->type_idx;
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx);
RDI_U32 constant_value_off = *rdi_element_from_name_idx(rdi, ConstantValueTable, constant->constant_value_idx);
RDI_U32 constant_value_size = *rdi_element_from_name_idx(rdi, ConstantValueTable, constant->constant_value_idx+1) - constant_value_off;
if(constant_value_size <= 8)
{
RDI_U64 constant_value_data_size = 0;
RDI_U8 *constant_value_data = rdi_table_from_name(rdi, ConstantValueData, &constant_value_data_size);
if(0 <= constant_value_off && constant_value_off + constant_value_size <= constant_value_data_size)
{
RDI_U64 value = 0;
MemoryCopy(&value, constant_value_data+constant_value_off, constant_value_size);
E_OpList oplist = {0};
e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(value));
string_mapped = 1;
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)match.dbgi_idx);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Value;
mapped_bytecode_space = module->space;
break;
}
}
}break;
case RDI_SectionKind_Procedures:
{
RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, match.idx);
RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx);
U64 voff = *rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_first);
U32 type_idx = procedure->type_idx;
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx);
E_OpList oplist = {0};
e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + voff));
string_mapped = 1;
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)match.dbgi_idx);
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
mapped_bytecode_mode = E_Mode_Value;
mapped_bytecode_space = module->space;
}break;
case RDI_SectionKind_TypeNodes:
{
U32 type_idx = match.idx;
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx);
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)match.dbgi_idx);
string_mapped = 1;
}break;
}
}
}
}break;
//- rjf: try types
case E_IdentifierResolutionPath_Types:
if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("type"), 0)))
{
mapped_type_key = e_leaf_type_from_name(string);
if(!e_type_key_match(e_type_key_zero(), mapped_type_key))
{
string_mapped = 1;
}
}break;
//- rjf: try registers
case E_IdentifierResolutionPath_Registers:
if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("reg"), 0)))
+9 -15
View File
@@ -14,11 +14,9 @@ typedef enum E_IdentifierResolutionPath
E_IdentifierResolutionPath_ParentExprMember,
E_IdentifierResolutionPath_ImplicitThisMember,
E_IdentifierResolutionPath_Local,
E_IdentifierResolutionPath_Globals,
E_IdentifierResolutionPath_ThreadLocals,
E_IdentifierResolutionPath_Constants,
E_IdentifierResolutionPath_Procedures,
E_IdentifierResolutionPath_Types,
E_IdentifierResolutionPath_DebugInfoMatch,
E_IdentifierResolutionPath_BuiltInConstants,
E_IdentifierResolutionPath_BuiltInTypes,
E_IdentifierResolutionPath_Registers,
E_IdentifierResolutionPath_RegisterAliases,
E_IdentifierResolutionPath_Macros,
@@ -87,11 +85,9 @@ E_IdentifierResolutionPath e_default_identifier_resolution_paths[] =
E_IdentifierResolutionPath_ParentExprMember,
E_IdentifierResolutionPath_ImplicitThisMember,
E_IdentifierResolutionPath_Local,
E_IdentifierResolutionPath_Globals,
E_IdentifierResolutionPath_ThreadLocals,
E_IdentifierResolutionPath_Constants,
E_IdentifierResolutionPath_Procedures,
E_IdentifierResolutionPath_Types,
E_IdentifierResolutionPath_BuiltInConstants,
E_IdentifierResolutionPath_BuiltInTypes,
E_IdentifierResolutionPath_DebugInfoMatch,
E_IdentifierResolutionPath_Registers,
E_IdentifierResolutionPath_RegisterAliases,
E_IdentifierResolutionPath_Macros,
@@ -110,11 +106,9 @@ E_IdentifierResolutionPath e_callable_identifier_resolution_paths[] =
E_IdentifierResolutionPath_ParentExprMember,
E_IdentifierResolutionPath_ImplicitThisMember,
E_IdentifierResolutionPath_Local,
E_IdentifierResolutionPath_Globals,
E_IdentifierResolutionPath_ThreadLocals,
E_IdentifierResolutionPath_Constants,
E_IdentifierResolutionPath_Procedures,
E_IdentifierResolutionPath_Types,
E_IdentifierResolutionPath_BuiltInConstants,
E_IdentifierResolutionPath_BuiltInTypes,
E_IdentifierResolutionPath_DebugInfoMatch,
E_IdentifierResolutionPath_Registers,
E_IdentifierResolutionPath_RegisterAliases,
};
+81 -145
View File
@@ -526,152 +526,73 @@ 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)
e_leaf_builtin_type_key_from_name(String8 name)
{
E_TypeKey key = zero_struct;
B32 found = 0;
if(!found)
E_TypeKey result = {0};
if(0){}
#define BuiltInType_XList \
BasicCase("uint8", U8)\
BasicCase("uint8_t", U8)\
BasicCase("uchar", UChar8)\
BasicCase("uchar8", UChar8)\
BasicCase("uint16", U16)\
BasicCase("uint16_t", U16)\
BasicCase("uchar16", UChar16)\
BasicCase("uint32", U32)\
BasicCase("uint32_t", U32)\
BasicCase("uchar32", UChar32)\
BasicCase("uint64", U64)\
BasicCase("uint64_t", U64)\
BasicCase("uint128", U128)\
BasicCase("uint128_t", U128)\
BasicCase("uint256", U256)\
BasicCase("uint256_t", U256)\
BasicCase("uint512", U512)\
BasicCase("uint512_t", U512)\
BasicCase("int8", S8)\
BasicCase("int8_t", S8)\
BasicCase("char", Char8)\
BasicCase("char8", Char8)\
BasicCase("int16", S16)\
BasicCase("int16_t", S16)\
BasicCase("char16", Char16)\
BasicCase("int32", S32)\
BasicCase("int32_t", S32)\
BasicCase("char32", Char32)\
BasicCase("int64", S64)\
BasicCase("int64_t", S64)\
BasicCase("int128", S128)\
BasicCase("int128_t", S128)\
BasicCase("int256", S256)\
BasicCase("int256_t", S256)\
BasicCase("int512", S512)\
BasicCase("int512_t", S512)\
BasicCase("void", Void)\
BasicCase("bool", Bool)\
BasicCase("float", F32)\
BasicCase("float32", F32)\
BasicCase("double", F64)\
BasicCase("float64", F64)
#define BasicCase(str, kind) else if(str8_match(name, str8_lit(str), 0)) {result = e_type_key_basic(E_TypeKind_##kind);}
BuiltInType_XList
#undef BasicCase
return result;
}
internal E_TypeKey
e_leaf_type_key_from_name(String8 name)
{
E_TypeKey key = e_leaf_builtin_type_key_from_name(name);
if(!e_type_key_match(e_type_key_zero(), key))
{
#define Case(str) (str8_match(name, str8_lit(str), 0))
if(0){}
else if(Case("uint8") || Case("uint8_t"))
DI_Match match = di_match_from_name(e_base_ctx->dbgi_match_store, name, 0);
if(match.section == RDI_SectionKind_TypeNodes)
{
found = 1;
key = e_type_key_basic(E_TypeKind_U8);
}
else if(Case("uchar8") || Case("uchar"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_UChar8);
}
else if(Case("uint16") || Case("uint16_t"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_U16);
}
else if(Case("uchar16"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_UChar16);
}
else if(Case("uint32") || Case("uint32_t"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_U32);
}
else if(Case("uchar32"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_UChar32);
}
else if(Case("uint64") || Case("uint64_t"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_U64);
}
else if(Case("uint128") || Case("uint128_t"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_U128);
}
else if(Case("uint256") || Case("uint256_t"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_U256);
}
else if(Case("uint512") || Case("uint512_t"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_U512);
}
else if(Case("s8") || Case("b8") || Case("B8") || Case("i8") || Case("int8") || Case("int8_t"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_S8);
}
else if(Case("char8") || Case("char"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_Char8);
}
else if(Case("int16") || Case("int16_t"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_S16);
}
else if(Case("char16"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_Char16);
}
else if(Case("int32") || Case("int32_t") || Case("char32"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_S32);
}
else if(Case("char32"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_Char32);
}
else if(Case("int64") || Case("int64_t"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_S64);
}
else if(Case("int256") || Case("int256_t"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_S256);
}
else if(Case("int512") || Case("int512_t"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_S512);
}
else if(Case("void"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_Void);
}
else if(Case("bool"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_Bool);
}
else if(Case("float") || Case("float32"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_F32);
}
else if(Case("double") || Case("float64"))
{
found = 1;
key = e_type_key_basic(E_TypeKind_F64);
}
#undef Case
}
if(!found)
{
for(U64 module_idx = 0; module_idx < e_base_ctx->modules_count; module_idx += 1)
{
RDI_Parsed *rdi = e_base_ctx->modules[module_idx].rdi;
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);
if(node != 0)
{
U32 match_count = 0;
U32 *matches = rdi_matches_from_map_node(rdi, node, &match_count);
if(match_count != 0)
{
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, matches[0]);
found = (type_node->kind != RDI_TypeKind_NULL);
key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), matches[0], module_idx);
break;
}
}
E_Module *module = &e_base_ctx->modules[match.dbgi_idx];
RDI_Parsed *rdi = module->rdi;
U32 type_idx = match.idx;
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx);
key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)match.dbgi_idx);
}
}
return key;
@@ -688,7 +609,7 @@ e_type_key_from_expr(E_Expr *expr)
default:{}break;
case E_ExprKind_LeafIdentifier:
{
result = e_leaf_type_from_name(expr->string);
result = e_leaf_type_key_from_name(expr->string);
}break;
case E_ExprKind_TypeIdent:
{
@@ -742,7 +663,7 @@ e_push_type_parse_from_text_tokens(Arena *arena, String8 text, E_TokenArray toke
{
token_string = str8_substr(token_string, r1u64(1, token_string.size-1));
}
E_TypeKey type_key = e_leaf_type_from_name(token_string);
E_TypeKey type_key = e_leaf_type_key_from_name(token_string);
if(!e_type_key_match(e_type_key_zero(), type_key))
{
token_it += 1;
@@ -1080,6 +1001,21 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
{
E_Token token = e_token_at_it(it, &tokens);
String8 token_string = str8_substr(text, token.range);
// rjf: skip no-op prefix keywords
if(token.kind == E_TokenKind_Identifier &&
(str8_match(token_string, str8_lit("struct"), 0) ||
str8_match(token_string, str8_lit("union"), 0) ||
str8_match(token_string, str8_lit("enum"), 0) ||
str8_match(token_string, str8_lit("class"), 0) ||
str8_match(token_string, str8_lit("typename"), 0)))
{
it += 1;
token = e_token_at_it(it, &tokens);
token_string = str8_substr(text, token.range);
}
// rjf: build identifier atom
if(token.kind == E_TokenKind_Identifier)
{
String8 identifier_string = token_string;
+2 -1
View File
@@ -34,7 +34,8 @@ internal String8 e_string_from_expr(Arena *arena, E_Expr *expr, String8 parent_e
////////////////////////////////
//~ rjf: Parsing Functions
internal E_TypeKey e_leaf_type_from_name(String8 name);
internal E_TypeKey e_leaf_builtin_type_key_from_name(String8 name);
internal E_TypeKey e_leaf_type_key_from_name(String8 name);
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);
+3 -2
View File
@@ -927,7 +927,7 @@ e_push_type_from_key(Arena *arena, E_TypeKey key)
type->byte_size = bit_size_from_arch(e_base_ctx->modules[rdi_idx].arch)/8;
type->direct_type_key = direct_type_key;
type->count = count;
type->param_type_keys = push_array_no_zero(arena, E_TypeKey, type->count);
type->param_type_keys = push_array(arena, E_TypeKey, type->count);
type->arch = e_base_ctx->modules[rdi_idx].arch;
for(U32 idx = 0; idx < type->count; idx += 1)
{
@@ -1509,6 +1509,7 @@ e_type_key_unwrap(E_TypeKey key, E_TypeUnwrapFlags flags)
case E_TypeKind_MetaExpr: {done = !(flags & E_TypeUnwrapFlag_Meta);}break;
case E_TypeKind_Enum: {done = !(flags & E_TypeUnwrapFlag_Enums);}break;
case E_TypeKind_Alias: {done = !(flags & E_TypeUnwrapFlag_Aliases);}break;
case E_TypeKind_Bitfield: {done = !(flags & E_TypeUnwrapFlag_Bitfields);}break;
case E_TypeKind_Array:
case E_TypeKind_Ptr:
case E_TypeKind_RRef:
@@ -2541,7 +2542,7 @@ E_TYPE_EXPAND_INFO_FUNCTION_DEF(array)
{
E_Type *type = e_type_from_key(eval.irtree.type_key);
U64 count = 1;
if(type->args != 0 && type->count > 0) E_ParentKey(e_key_match(e_key_zero(), eval.parent_key) ? eval.key : eval.parent_key)
if(type->args != 0 && type->count > 0) E_ParentKey(eval.key)
{
E_Key count_key = e_key_from_expr(type->args[0]);
E_Value count_value = e_value_from_key(count_key);
+2 -1
View File
@@ -16,8 +16,9 @@ enum
E_TypeUnwrapFlag_Meta = (1<<3),
E_TypeUnwrapFlag_Enums = (1<<4),
E_TypeUnwrapFlag_Aliases = (1<<5),
E_TypeUnwrapFlag_Bitfields = (1<<6),
E_TypeUnwrapFlag_All = 0xffffffff,
E_TypeUnwrapFlag_AllDecorative = (E_TypeUnwrapFlag_All & ~E_TypeUnwrapFlag_Pointers)
E_TypeUnwrapFlag_AllDecorative = (E_TypeUnwrapFlag_All & ~(E_TypeUnwrapFlag_Pointers|E_TypeUnwrapFlag_Bitfields))
};
////////////////////////////////
+4 -2
View File
@@ -144,7 +144,7 @@ U8 e_type_kind_basic_byte_size_table[61] =
0,
};
String8 e_expr_kind_strings[49] =
String8 e_expr_kind_strings[50] =
{
str8_lit_comp("Nil"),
str8_lit_comp("Ref"),
@@ -155,6 +155,7 @@ str8_lit_comp("Address"),
str8_lit_comp("Cast"),
str8_lit_comp("Sizeof"),
str8_lit_comp("Typeof"),
str8_lit_comp("Symbolof"),
str8_lit_comp("ByteSwap"),
str8_lit_comp("Pos"),
str8_lit_comp("Neg"),
@@ -197,7 +198,7 @@ str8_lit_comp("Unsigned"),
str8_lit_comp("Define"),
};
E_OpInfo e_expr_kind_op_info_table[49] =
E_OpInfo e_expr_kind_op_info_table[50] =
{
{ 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("") },
@@ -208,6 +209,7 @@ E_OpInfo e_expr_kind_op_info_table[49] =
{ 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("symbolof "), 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("") },
+3 -2
View File
@@ -107,6 +107,7 @@ E_ExprKind_Address,
E_ExprKind_Cast,
E_ExprKind_Sizeof,
E_ExprKind_Typeof,
E_ExprKind_Symbolof,
E_ExprKind_ByteSwap,
E_ExprKind_Pos,
E_ExprKind_Neg,
@@ -170,8 +171,8 @@ C_LINKAGE_BEGIN
extern String8 e_token_kind_strings[6];
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_expr_kind_strings[50];
extern E_OpInfo e_expr_kind_op_info_table[50];
extern String8 e_interpretation_code_display_strings[11];
C_LINKAGE_END
@@ -528,6 +528,18 @@ ev_block_tree_from_eval(Arena *arena, EV_View *view, String8 filter, E_Eval root
// rjf: unpack eval
E_Mode mode = t->eval.irtree.mode;
E_Eval eval = t->eval;
// rjf: pointers/reference evaluations -> dereference for expansion
{
E_TypeKey type_key = e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_Modifiers|E_TypeUnwrapFlag_Meta);
E_TypeKind type_kind = e_type_kind_from_key(type_key);
if(e_type_kind_is_pointer_or_ref(type_kind))
{
eval = e_eval_wrapf(eval, "*($)");
}
}
// rjf: unpack type key we'll use for expanding this eval
E_TypeKey expansion_type_key = ev_expansion_type_from_key(eval.irtree.type_key);
if(!e_type_key_match(expansion_type_key, e_type_key_zero()))
{
@@ -1292,6 +1304,8 @@ ev_string_from_simple_typed_eval(Arena *arena, EV_StringParams *params, E_Eval e
{
digit_group_separator = 0;
}
S64 s64 = 0;
U64 u64 = 0;
F64 f64 = 0;
switch(type_kind)
{
@@ -1366,20 +1380,22 @@ ev_string_from_simple_typed_eval(Arena *arena, EV_StringParams *params, E_Eval e
}
}break;
case E_TypeKind_S8:
case E_TypeKind_S16:
case E_TypeKind_S32:
case E_TypeKind_S64:
case E_TypeKind_S8: s64 = (S64)eval.value.s8; goto sint_path;
case E_TypeKind_S16: s64 = (S64)eval.value.s16; goto sint_path;
case E_TypeKind_S32: s64 = (S64)eval.value.s32; goto sint_path;
case E_TypeKind_S64: s64 = (S64)eval.value.s64; goto sint_path;
sint_path:;
{
result = str8_from_s64(arena, eval.value.s64, params->radix, params->min_digits, digit_group_separator);
result = str8_from_s64(arena, s64, params->radix, params->min_digits, digit_group_separator);
}break;
case E_TypeKind_U8:
case E_TypeKind_U16:
case E_TypeKind_U32:
case E_TypeKind_U64:
case E_TypeKind_U8: u64 = (U64)eval.value.u8; goto uint_path;
case E_TypeKind_U16: u64 = (U64)eval.value.u16; goto uint_path;
case E_TypeKind_U32: u64 = (U64)eval.value.u32; goto uint_path;
case E_TypeKind_U64: u64 = (U64)eval.value.u64; goto uint_path;
uint_path:;
{
result = str8_from_u64(arena, eval.value.u64, params->radix, params->min_digits, digit_group_separator);
result = str8_from_u64(arena, u64, params->radix, params->min_digits, digit_group_separator);
}break;
case E_TypeKind_U128:
@@ -1776,6 +1792,7 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
B32 ptee_has_content;
B32 ptee_has_string;
B32 did_prefix_content;
B32 did_prefix_string;
B32 did_redirect;
};
EV_StringPtrData *ptr_data = it->top_task->user_data;
@@ -1849,6 +1866,10 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
{
string = str8_prefix(string, params->limit_strings_size);
}
else if(type_kind == E_TypeKind_Array && ptr_data->type->count != 0)
{
string = str8_prefix(string, ptr_data->type->count);
}
// rjf: escape and quote
B32 string__is_escaped_and_quoted = (!(params->flags & EV_StringFlag_DisableStringQuotes) || depth > 0);
@@ -1862,6 +1883,7 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
// rjf: report
*out_string = push_str8_copy(arena, string__escaped_and_quoted);
ptr_data->did_prefix_content = 1;
ptr_data->did_prefix_string = 1;
scratch_end(scratch);
}
@@ -1929,7 +1951,8 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
}
if(inline_site != 0)
{
E_TypeKey type = e_type_key_ext(E_TypeKind_Function, inline_site->type_idx, module_idx);
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, inline_site->type_idx);
E_TypeKey type = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), inline_site->type_idx, module_idx);
String8 name = {0};
name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size);
if(inline_site->type_idx != 0)
@@ -1958,7 +1981,8 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
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, module_idx);
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, procedure->type_idx);
E_TypeKey type = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), procedure->type_idx, module_idx);
String8 name = {0};
name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &name.size);
if(procedure->type_idx != 0)
@@ -2043,7 +2067,9 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
//
// rjf: [read only] if we did prefix content, do a parenthesized pointer value
if(!(params->flags & EV_StringFlag_DisableAddresses) && params->flags & EV_StringFlag_ReadOnlyDisplayRules && ptr_data->did_prefix_content)
if(!(params->flags & EV_StringFlag_DisableAddresses) && params->flags & EV_StringFlag_ReadOnlyDisplayRules &&
ptr_data->did_prefix_content &&
(!ptr_data->did_prefix_string || ptr_data->value_eval.value.u64 == 0))
{
*out_string = push_str8f(arena, " (%S)", ptr_value_string);
}
@@ -68,9 +68,9 @@ fp_metrics_from_font(FP_Handle handle)
FP_Metrics result = {0};
if(font.face != 0)
{
result.design_units_per_em = (F32)(font.face->units_per_EM * 72.f/96.f);
result.design_units_per_em = (F32)(font.face->units_per_EM);
result.ascent = (F32)font.face->ascender;
result.descent = (F32)font.face->descender;
result.descent = -(F32)font.face->descender;
result.line_gap = (F32)(font.face->height - font.face->ascender + font.face->descender);
result.capital_height = (F32)(font.face->ascender);
}
+5 -3
View File
@@ -70,6 +70,7 @@
//~ Global Symbols
#if !defined(RADDBG_MARKUP_STUBS)
extern unsigned char raddbg_is_attached_byte_marker[1];
int raddbg_is_attached__impl(void);
int raddbg_thread_id__impl(void);
void raddbg_thread_name__impl(int id, char *fmt, ...);
@@ -97,8 +98,9 @@ void raddbg_annotate_vaddr_range__impl(void *ptr, unsigned __int64 size, char *f
#include <stdio.h>
#endif
//- first byte of exe data section -> is attached
static raddbg_exe_data unsigned char raddbg_is_attached_byte_marker[1];
//- special section gets "is attached" byte
#pragma section(".rdbgia", read, write)
__declspec(allocate(".rdbgia")) unsigned char raddbg_is_attached_byte_marker[1] = {0};
//- types
@@ -316,7 +318,7 @@ raddbg_thread_name__impl(int id, char *fmt, ...)
#pragma warning(disable: 6320 6322)
__try
{
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info);
RaiseException(0x406D1388u, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info);
}
__except(1)
{
@@ -2,13 +2,13 @@
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////////////////////////////////////
//~ RAD Debug Info, (R)AD(D)BG(I) Format Library
//~ (R)AD (D)ebug (I)nfo Format Library
//
// Defines standard RDI debug information format types and
// functions.
#ifndef RDI_FORMAT_C
#define RDI_FORMAT_C
#ifndef RDI_C
#define RDI_C
RDI_U16 rdi_section_element_size_table[40] =
{
@@ -357,4 +357,4 @@ rdi_explanation_string_from_eval_conversion_kind(RDI_EvalConversionKind kind, RD
return rdi_eval_conversion_kind_message_string_table[kind].str;
}
#endif // RDI_FORMAT_C
#endif // RDI_C
@@ -2,13 +2,13 @@
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////////////////////////////////////
//~ RAD Debug Info, (R)AD(D)BG(I) Format Library
//~ (R)AD (D)ebug (I)nfo Format Library
//
// Defines standard RDI debug information format types and
// functions.
#ifndef RDI_FORMAT_H
#define RDI_FORMAT_H
#ifndef RDI_H
#define RDI_H
////////////////////////////////////////////////////////////////
//~ Overridable Procedure Decoration
@@ -1571,4 +1571,4 @@ extern RDI_U16 rdi_section_element_size_table[40];
extern RDI_U8 rdi_section_is_required_table[40];
extern RDI_U16 rdi_eval_op_ctrlbits_table[52];
#endif // RDI_FORMAT_H
#endif // RDI_H
File diff suppressed because it is too large Load Diff
@@ -1,233 +1,236 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////////////////////////////////////
//~ RAD Debug Info, (R)AD(D)BG(I) Format Parsing Library
//
// Defines helper types and functions for extracting data from
// RDI files.
////////////////////////////////////////////////////////////////
//~ Usage Samples
//
#if 0
// Procedure Name -> Line
{
RDI_Parsed *rdi = ...;
char *name = "mule_main";
RDI_Procedure *procedure = rdi_procedure_from_name_cstr(rdi, name); // 1. name -> procedure
RDI_U64 procedure_first_voff = rdi_first_voff_from_procedure(rdi, procedure); // 2. procedure -> virtual offset
RDI_Line line = rdi_line_from_voff(rdi, procedure_first_voff); // 3. virtual offset -> line
RDI_SourceFile *file = rdi_source_file_from_line(rdi, &line); // 4. line -> source file
RDI_U64 file_path_size = 0; // 5. source file -> path
RDI_U8 *file_path = rdi_normal_path_from_source_file(rdi, file, &file_path_size);
printf("%s is at %.*s:%u\n", name, (int)file_path_size, file_path, line.line_num);
}
// Line -> Procedure Name
{
RDI_Parsed *rdi = ...;
char *path = "c:/devel/raddebugger/src/mule/mule_main.cpp";
RDI_U32 line_num = 2557;
RDI_SourceFile *file = rdi_source_file_from_normal_path_cstr(rdi, path); // 1. path -> source file
RDI_U64 voff = rdi_first_voff_from_source_file_line_num(rdi, file, line_num); // 2. (source file, line) -> virtual offset
RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, voff); // 3. virtual offset -> procedure
RDI_U64 name_size = 0; // 4. procedure -> name
RDI_U8 *name = rdi_name_from_procedure(rdi, procedure, &name_size);
printf("%s:%u is inside %.*s\n", path, line_num, (int)name_size, name);
}
#endif
#ifndef RDI_FORMAT_PARSE_H
#define RDI_FORMAT_PARSE_H
////////////////////////////////////////////////////////////////
//~ Parsed Information Types
typedef enum RDI_ParseStatus
{
RDI_ParseStatus_Good = 0,
RDI_ParseStatus_HeaderDoesNotMatch = 1,
RDI_ParseStatus_UnsupportedVersionNumber = 2,
RDI_ParseStatus_InvalidDataSecionLayout = 3,
RDI_ParseStatus_MissingRequiredSection = 4,
}
RDI_ParseStatus;
typedef struct RDI_Parsed RDI_Parsed;
struct RDI_Parsed
{
RDI_U8 *raw_data;
RDI_U64 raw_data_size;
RDI_Section *sections;
RDI_U64 sections_count;
};
typedef struct RDI_ParsedLineTable RDI_ParsedLineTable;
struct RDI_ParsedLineTable
{
// NOTE: Mapping VOFF -> LINE_INFO
//
// * [ voff[i], voff[i + 1] ) forms the voff range
// * for the line info at lines[i] (and cols[i] if i < col_count)
RDI_U64* voffs; // [count + 1] sorted
RDI_Line* lines; // [count]
RDI_Column* cols; // [col_count]
RDI_U64 count;
RDI_U64 col_count;
};
typedef struct RDI_ParsedSourceLineMap RDI_ParsedSourceLineMap;
struct RDI_ParsedSourceLineMap
{
// NOTE: Mapping LINE_NUMBER -> VOFFs
//
// * nums[i] gives a line number
// * that line number has one or more associated voffs
//
// * to find all associated voffs for the line number nums[i] :
// * let k span over the range [ ranges[i], ranges[i + 1] )
// * voffs[k] gives the associated voffs
RDI_U32* nums; // [count] sorted
RDI_U32* ranges; // [count + 1]
RDI_U64* voffs; // [voff_count]
RDI_U64 count;
RDI_U64 voff_count;
};
typedef struct RDI_ParsedNameMap RDI_ParsedNameMap;
struct RDI_ParsedNameMap
{
RDI_NameMapBucket *buckets;
RDI_NameMapNode *nodes;
RDI_U64 bucket_count;
RDI_U64 node_count;
};
////////////////////////////////
//~ Global Nils
static union
{
RDI_TopLevelInfo top_level_info;
RDI_BinarySection binary_section;
RDI_FilePathNode file_path_node;
RDI_SourceFile source_file;
RDI_LineTable line_table;
RDI_SourceLineMap source_line_map;
RDI_Line line;
RDI_Column column;
RDI_Unit unit;
RDI_VMapEntry vmap_entry;
RDI_TypeNode type_node;
RDI_UDT udt;
RDI_Member member;
RDI_EnumMember enum_member;
RDI_GlobalVariable global_variable;
RDI_ThreadVariable thread_variable;
RDI_Procedure procedure;
RDI_Scope scope;
RDI_U64 voff;
RDI_LocationBlock location_block;
RDI_Local local;
}
rdi_nil_element_union = {0};
static RDI_Parsed rdi_parsed_nil = {0};
////////////////////////////////
//~ Top-Level Parsing API
RDI_PROC RDI_ParseStatus rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out);
////////////////////////////////
//~ Base Parsed Info Extraction Helpers
//- section table/element raw data extraction
RDI_PROC void *rdi_section_raw_data_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_SectionEncoding *encoding_out, RDI_U64 *size_out);
RDI_PROC void *rdi_section_raw_table_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 *count_out);
RDI_PROC void *rdi_section_raw_element_from_kind_idx(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 idx);
#define rdi_table_from_name(rdi, name, count_out) ((RDI_SectionElementType_##name *)rdi_section_raw_table_from_kind((rdi), RDI_SectionKind_##name, (count_out)))
#define rdi_element_from_name_idx(rdi, name, idx) ((RDI_SectionElementType_##name *)rdi_section_raw_element_from_kind_idx((rdi), RDI_SectionKind_##name, (idx)))
//- info about whole parse
RDI_PROC RDI_U64 rdi_decompressed_size_from_parsed(RDI_Parsed *rdi);
//- strings
RDI_PROC RDI_U8 *rdi_string_from_idx(RDI_Parsed *rdi, RDI_U32 idx, RDI_U64 *len_out);
//- index runs
RDI_PROC RDI_U32 *rdi_idx_run_from_first_count(RDI_Parsed *rdi, RDI_U32 raw_first, RDI_U32 raw_count, RDI_U32 *n_out);
//- line info
RDI_PROC void rdi_parsed_from_line_table(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_ParsedLineTable *out);
RDI_PROC RDI_U64 rdi_line_info_idx_range_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff, RDI_U64 *n_out);
RDI_PROC RDI_U64 rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff);
RDI_PROC void rdi_parsed_from_source_line_map(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_ParsedSourceLineMap *out);
RDI_PROC RDI_U64 *rdi_line_voffs_from_num(RDI_ParsedSourceLineMap *map, RDI_U32 linenum, RDI_U32 *n_out);
//- vmap lookups
RDI_PROC RDI_U64 rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U64 vmap_count, RDI_U64 voff);
//- name maps
RDI_PROC RDI_NameMap *rdi_name_map_from_kind(RDI_Parsed *p, RDI_NameMapKind kind);
RDI_PROC void rdi_name_map_parse(RDI_Parsed* p, RDI_NameMap *mapptr, RDI_ParsedNameMap *out);
RDI_PROC RDI_NameMapNode *rdi_name_map_lookup(RDI_Parsed *p, RDI_ParsedNameMap *map, RDI_U8 *str, RDI_U64 len);
RDI_PROC RDI_U32 *rdi_matches_from_map_node(RDI_Parsed *p, RDI_NameMapNode *node, RDI_U32 *n_out);
////////////////////////////////
//~ High-Level Composite Lookup Functions
//- procedures
RDI_PROC RDI_Procedure *rdi_procedure_from_name(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size);
RDI_PROC RDI_Procedure *rdi_procedure_from_name_cstr(RDI_Parsed *rdi, char *cstr);
RDI_PROC RDI_U8 *rdi_name_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure, RDI_U64 *len_out);
RDI_PROC RDI_Scope *rdi_root_scope_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure);
RDI_PROC RDI_UDT *rdi_container_udt_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure);
RDI_PROC RDI_Procedure *rdi_container_procedure_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure);
RDI_PROC RDI_U64 rdi_first_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure);
RDI_PROC RDI_U64 rdi_opl_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure);
RDI_PROC RDI_Procedure *rdi_procedure_from_voff(RDI_Parsed *rdi, RDI_U64 voff);
//- scopes
RDI_PROC RDI_U64 rdi_first_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope);
RDI_PROC RDI_U64 rdi_opl_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope);
RDI_PROC RDI_Scope *rdi_scope_from_voff(RDI_Parsed *rdi, RDI_U64 voff);
RDI_PROC RDI_Scope *rdi_parent_from_scope(RDI_Parsed *rdi, RDI_Scope *scope);
RDI_PROC RDI_Procedure *rdi_procedure_from_scope(RDI_Parsed *rdi, RDI_Scope *scope);
RDI_PROC RDI_InlineSite *rdi_inline_site_from_scope(RDI_Parsed *rdi, RDI_Scope *scope);
//- global variables
RDI_PROC RDI_GlobalVariable *rdi_global_variable_from_voff(RDI_Parsed *rdi, RDI_U64 voff);
//- units
RDI_PROC RDI_Unit *rdi_unit_from_voff(RDI_Parsed *rdi, RDI_U64 voff);
RDI_PROC RDI_LineTable *rdi_line_table_from_unit(RDI_Parsed *rdi, RDI_Unit *unit);
//- line tables
RDI_PROC RDI_Line rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff);
RDI_PROC RDI_Line rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff);
RDI_PROC RDI_SourceFile *rdi_source_file_from_line(RDI_Parsed *rdi, RDI_Line *line);
//- source files
RDI_PROC RDI_SourceFile *rdi_source_file_from_normal_path(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size);
RDI_PROC RDI_SourceFile *rdi_source_file_from_normal_path_cstr(RDI_Parsed *rdi, char *cstr);
RDI_PROC RDI_U8 *rdi_normal_path_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U64 *len_out);
RDI_PROC RDI_FilePathNode *rdi_file_path_node_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file);
RDI_PROC RDI_SourceLineMap *rdi_source_line_map_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file);
RDI_PROC RDI_U64 rdi_first_voff_from_source_file_line_num(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U32 line_num);
//- source line maps
RDI_PROC RDI_U64 rdi_first_voff_from_source_line_map_num(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_U32 line_num);
//- file path nodes
RDI_PROC RDI_FilePathNode *rdi_parent_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node);
RDI_PROC RDI_U8 *rdi_name_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node, RDI_U64 *len_out);
////////////////////////////////
//~ Parser Helpers
#define rdi_parse__min(a,b) (((a)<(b))?(a):(b))
RDI_PROC RDI_U64 rdi_cstring_length(char *cstr);
RDI_PROC RDI_U64 rdi_size_from_bytecode_stream(RDI_U8 *ptr, RDI_U8 *opl);
#endif // RDI_FORMAT_PARSE_H
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////////////////////////////////////
//~ (R)AD (D)ebug (I)nfo Format Parsing Library
//
// Defines helper types and functions for extracting data from
// RDI files.
////////////////////////////////////////////////////////////////
//~ Usage Samples
//
#if 0
// Procedure Name -> Line
{
RDI_Parsed *rdi = ...;
char *name = "mule_main";
RDI_Procedure *procedure = rdi_procedure_from_name_cstr(rdi, name); // 1. name -> procedure
RDI_U64 procedure_first_voff = rdi_first_voff_from_procedure(rdi, procedure); // 2. procedure -> virtual offset
RDI_Line line = rdi_line_from_voff(rdi, procedure_first_voff); // 3. virtual offset -> line
RDI_SourceFile *file = rdi_source_file_from_line(rdi, &line); // 4. line -> source file
RDI_U64 file_path_size = 0; // 5. source file -> path
RDI_U8 *file_path = rdi_normal_path_from_source_file(rdi, file, &file_path_size);
printf("%s is at %.*s:%u\n", name, (int)file_path_size, file_path, line.line_num);
}
// Line -> Procedure Name
{
RDI_Parsed *rdi = ...;
char *path = "c:/devel/raddebugger/src/mule/mule_main.cpp";
RDI_U32 line_num = 2557;
RDI_SourceFile *file = rdi_source_file_from_normal_path_cstr(rdi, path); // 1. path -> source file
RDI_U64 voff = rdi_first_voff_from_source_file_line_num(rdi, file, line_num); // 2. (source file, line) -> virtual offset
RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, voff); // 3. virtual offset -> procedure
RDI_U64 name_size = 0; // 4. procedure -> name
RDI_U8 *name = rdi_name_from_procedure(rdi, procedure, &name_size);
printf("%s:%u is inside %.*s\n", path, line_num, (int)name_size, name);
}
#endif
#ifndef RDI_PARSE_H
#define RDI_PARSE_H
////////////////////////////////////////////////////////////////
//~ Parsed Information Types
typedef enum RDI_ParseStatus
{
RDI_ParseStatus_Good = 0,
RDI_ParseStatus_HeaderDoesNotMatch = 1,
RDI_ParseStatus_UnsupportedVersionNumber = 2,
RDI_ParseStatus_InvalidDataSecionLayout = 3,
RDI_ParseStatus_MissingRequiredSection = 4,
}
RDI_ParseStatus;
typedef struct RDI_Parsed RDI_Parsed;
struct RDI_Parsed
{
RDI_U8 *raw_data;
RDI_U64 raw_data_size;
RDI_Section *sections;
RDI_U64 sections_count;
};
typedef struct RDI_ParsedLineTable RDI_ParsedLineTable;
struct RDI_ParsedLineTable
{
// NOTE: Mapping VOFF -> LINE_INFO
//
// * [ voff[i], voff[i + 1] ) forms the voff range
// * for the line info at lines[i] (and cols[i] if i < col_count)
RDI_U64* voffs; // [count + 1] sorted
RDI_Line* lines; // [count]
RDI_Column* cols; // [col_count]
RDI_U64 count;
RDI_U64 col_count;
};
typedef struct RDI_ParsedSourceLineMap RDI_ParsedSourceLineMap;
struct RDI_ParsedSourceLineMap
{
// NOTE: Mapping LINE_NUMBER -> VOFFs
//
// * nums[i] gives a line number
// * that line number has one or more associated voffs
//
// * to find all associated voffs for the line number nums[i] :
// * let k span over the range [ ranges[i], ranges[i + 1] )
// * voffs[k] gives the associated voffs
RDI_U32* nums; // [count] sorted
RDI_U32* ranges; // [count + 1]
RDI_U64* voffs; // [voff_count]
RDI_U64 count;
RDI_U64 voff_count;
};
typedef struct RDI_ParsedNameMap RDI_ParsedNameMap;
struct RDI_ParsedNameMap
{
RDI_NameMapBucket *buckets;
RDI_NameMapNode *nodes;
RDI_U64 bucket_count;
RDI_U64 node_count;
};
////////////////////////////////
//~ Global Nils
static union
{
RDI_TopLevelInfo top_level_info;
RDI_BinarySection binary_section;
RDI_FilePathNode file_path_node;
RDI_SourceFile source_file;
RDI_LineTable line_table;
RDI_SourceLineMap source_line_map;
RDI_Line line;
RDI_Column column;
RDI_Unit unit;
RDI_VMapEntry vmap_entry;
RDI_TypeNode type_node;
RDI_UDT udt;
RDI_Member member;
RDI_EnumMember enum_member;
RDI_GlobalVariable global_variable;
RDI_ThreadVariable thread_variable;
RDI_Procedure procedure;
RDI_Scope scope;
RDI_U64 voff;
RDI_LocationBlock location_block;
RDI_Local local;
}
rdi_nil_element_union = {0};
static RDI_Parsed rdi_parsed_nil = {0};
////////////////////////////////
//~ Top-Level Parsing API
RDI_PROC RDI_ParseStatus rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out);
////////////////////////////////
//~ Base Parsed Info Extraction Helpers
//- section table/element raw data extraction
RDI_PROC void *rdi_section_raw_data_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_SectionEncoding *encoding_out, RDI_U64 *size_out);
RDI_PROC void *rdi_section_raw_table_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 *count_out);
RDI_PROC void *rdi_section_raw_element_from_kind_idx(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 idx);
#define rdi_table_from_name(rdi, name, count_out) ((RDI_SectionElementType_##name *)rdi_section_raw_table_from_kind((rdi), RDI_SectionKind_##name, (count_out)))
#define rdi_element_from_name_idx(rdi, name, idx) ((RDI_SectionElementType_##name *)rdi_section_raw_element_from_kind_idx((rdi), RDI_SectionKind_##name, (idx)))
//- info about whole parse
RDI_PROC RDI_U64 rdi_decompressed_size_from_parsed(RDI_Parsed *rdi);
//- decompression
internal void rdi_decompress_parsed(U8 *decompressed_data, U64 decompressed_size, RDI_Parsed *og_rdi);
//- strings
RDI_PROC RDI_U8 *rdi_string_from_idx(RDI_Parsed *rdi, RDI_U32 idx, RDI_U64 *len_out);
//- index runs
RDI_PROC RDI_U32 *rdi_idx_run_from_first_count(RDI_Parsed *rdi, RDI_U32 raw_first, RDI_U32 raw_count, RDI_U32 *n_out);
//- line info
RDI_PROC void rdi_parsed_from_line_table(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_ParsedLineTable *out);
RDI_PROC RDI_U64 rdi_line_info_idx_range_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff, RDI_U64 *n_out);
RDI_PROC RDI_U64 rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff);
RDI_PROC void rdi_parsed_from_source_line_map(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_ParsedSourceLineMap *out);
RDI_PROC RDI_U64 *rdi_line_voffs_from_num(RDI_ParsedSourceLineMap *map, RDI_U32 linenum, RDI_U32 *n_out);
//- vmap lookups
RDI_PROC RDI_U64 rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U64 vmap_count, RDI_U64 voff);
//- name maps
RDI_PROC RDI_NameMap *rdi_name_map_from_kind(RDI_Parsed *p, RDI_NameMapKind kind);
RDI_PROC void rdi_name_map_parse(RDI_Parsed* p, RDI_NameMap *mapptr, RDI_ParsedNameMap *out);
RDI_PROC RDI_NameMapNode *rdi_name_map_lookup(RDI_Parsed *p, RDI_ParsedNameMap *map, RDI_U8 *str, RDI_U64 len);
RDI_PROC RDI_U32 *rdi_matches_from_map_node(RDI_Parsed *p, RDI_NameMapNode *node, RDI_U32 *n_out);
////////////////////////////////
//~ High-Level Composite Lookup Functions
//- procedures
RDI_PROC RDI_Procedure *rdi_procedure_from_name(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size);
RDI_PROC RDI_Procedure *rdi_procedure_from_name_cstr(RDI_Parsed *rdi, char *cstr);
RDI_PROC RDI_U8 *rdi_name_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure, RDI_U64 *len_out);
RDI_PROC RDI_Scope *rdi_root_scope_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure);
RDI_PROC RDI_UDT *rdi_container_udt_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure);
RDI_PROC RDI_Procedure *rdi_container_procedure_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure);
RDI_PROC RDI_U64 rdi_first_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure);
RDI_PROC RDI_U64 rdi_opl_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure);
RDI_PROC RDI_Procedure *rdi_procedure_from_voff(RDI_Parsed *rdi, RDI_U64 voff);
//- scopes
RDI_PROC RDI_U64 rdi_first_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope);
RDI_PROC RDI_U64 rdi_opl_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope);
RDI_PROC RDI_Scope *rdi_scope_from_voff(RDI_Parsed *rdi, RDI_U64 voff);
RDI_PROC RDI_Scope *rdi_parent_from_scope(RDI_Parsed *rdi, RDI_Scope *scope);
RDI_PROC RDI_Procedure *rdi_procedure_from_scope(RDI_Parsed *rdi, RDI_Scope *scope);
RDI_PROC RDI_InlineSite *rdi_inline_site_from_scope(RDI_Parsed *rdi, RDI_Scope *scope);
//- global variables
RDI_PROC RDI_GlobalVariable *rdi_global_variable_from_voff(RDI_Parsed *rdi, RDI_U64 voff);
//- units
RDI_PROC RDI_Unit *rdi_unit_from_voff(RDI_Parsed *rdi, RDI_U64 voff);
RDI_PROC RDI_LineTable *rdi_line_table_from_unit(RDI_Parsed *rdi, RDI_Unit *unit);
//- line tables
RDI_PROC RDI_Line rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff);
RDI_PROC RDI_Line rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff);
RDI_PROC RDI_SourceFile *rdi_source_file_from_line(RDI_Parsed *rdi, RDI_Line *line);
//- source files
RDI_PROC RDI_SourceFile *rdi_source_file_from_normal_path(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size);
RDI_PROC RDI_SourceFile *rdi_source_file_from_normal_path_cstr(RDI_Parsed *rdi, char *cstr);
RDI_PROC RDI_U8 *rdi_normal_path_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U64 *len_out);
RDI_PROC RDI_FilePathNode *rdi_file_path_node_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file);
RDI_PROC RDI_SourceLineMap *rdi_source_line_map_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file);
RDI_PROC RDI_U64 rdi_first_voff_from_source_file_line_num(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U32 line_num);
//- source line maps
RDI_PROC RDI_U64 rdi_first_voff_from_source_line_map_num(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_U32 line_num);
//- file path nodes
RDI_PROC RDI_FilePathNode *rdi_parent_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node);
RDI_PROC RDI_U8 *rdi_name_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node, RDI_U64 *len_out);
////////////////////////////////
//~ Parser Helpers
#define rdi_parse__min(a,b) (((a)<(b))?(a):(b))
RDI_PROC RDI_U64 rdi_cstring_length(char *cstr);
RDI_PROC RDI_U64 rdi_size_from_bytecode_stream(RDI_U8 *ptr, RDI_U8 *opl);
#endif // RDI_FORMAT_PARSE_H
-864
View File
@@ -1,864 +0,0 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ Top-Level Parsing API
RDI_PROC RDI_ParseStatus
rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out)
{
RDI_ParseStatus result = RDI_ParseStatus_Good;
//////////////////////////////
//- rjf: extract header
//
RDI_Header *hdr = 0;
if(result == RDI_ParseStatus_Good)
{
if(sizeof(*hdr) <= size)
{
hdr = (RDI_Header*)data;
}
if(hdr == 0 || hdr->magic != RDI_MAGIC_CONSTANT)
{
hdr = 0;
result = RDI_ParseStatus_HeaderDoesNotMatch;
}
if(hdr != 0 && hdr->encoding_version != RDI_ENCODING_VERSION)
{
hdr = 0;
result = RDI_ParseStatus_UnsupportedVersionNumber;
}
}
//////////////////////////////
//- rjf: extract data sections
//
RDI_Section *dsecs = 0;
RDI_U32 dsec_count = 0;
if(result == RDI_ParseStatus_Good)
{
RDI_U64 opl = (RDI_U64)hdr->data_section_off + (RDI_U64)hdr->data_section_count*sizeof(*dsecs);
if(opl <= size)
{
dsecs = (RDI_Section*)(data + hdr->data_section_off);
dsec_count = hdr->data_section_count;
}
if(dsecs == 0)
{
result = RDI_ParseStatus_InvalidDataSecionLayout;
}
}
//////////////////////////////
//- rjf: fill result
//
if(result == RDI_ParseStatus_Good)
{
out->raw_data = data;
out->raw_data_size = size;
out->sections = dsecs;
out->sections_count = dsec_count;
}
//////////////////////////////
//- rjf: validate results
//
if(result == RDI_ParseStatus_Good)
{
for(RDI_SectionKind k = (RDI_SectionKind)(RDI_SectionKind_NULL+1); k < RDI_SectionKind_COUNT; k = (RDI_SectionKind)(k+1))
{
if(rdi_section_is_required_table[k])
{
RDI_U64 data_size = 0;
RDI_SectionEncoding encoding = 0;
void *data = rdi_section_raw_data_from_kind(out, k, &encoding, &data_size);
if(data == 0 || data == &rdi_nil_element_union || data_size == 0)
{
result = RDI_ParseStatus_MissingRequiredSection;
break;
}
}
}
}
return result;
}
////////////////////////////////
//~ Base Parsed Info Extraction Helpers
//- section table/element raw data extraction
RDI_PROC void *
rdi_section_raw_data_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_SectionEncoding *encoding_out, RDI_U64 *size_out)
{
void *result = 0;
#if !defined(RDI_DISABLE_NILS)
result = &rdi_nil_element_union;
*size_out = rdi_section_element_size_table[kind];
#endif
if(0 <= kind && kind < rdi->sections_count &&
rdi->sections[kind].off < rdi->raw_data_size)
{
result = rdi->raw_data+rdi->sections[kind].off;
*size_out = rdi->sections[kind].encoded_size;
*encoding_out = rdi->sections[kind].encoding;
}
return result;
}
RDI_PROC void *
rdi_section_raw_table_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 *count_out)
{
void *result = 0;
RDI_U64 all_elements_size = 0;
RDI_SectionEncoding all_elements_encoding = 0;
void *all_elements = rdi_section_raw_data_from_kind(rdi, kind, &all_elements_encoding, &all_elements_size);
if(all_elements_encoding == RDI_SectionEncoding_Unpacked)
{
RDI_U64 element_size = (RDI_U64)rdi_section_element_size_table[kind];
RDI_U64 all_elements_count = all_elements_size/element_size;
result = all_elements;
*count_out = all_elements_count;
}
return result;
}
RDI_PROC void *
rdi_section_raw_element_from_kind_idx(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 idx)
{
RDI_U64 count = 0;
void *table = rdi_section_raw_table_from_kind(rdi, kind, &count);
void *result = table;
if(idx < count)
{
RDI_U64 element_size = (RDI_U64)rdi_section_element_size_table[kind];
result = (RDI_U8 *)table + element_size*idx;
}
return result;
}
//- info about whole parse
RDI_PROC RDI_U64
rdi_decompressed_size_from_parsed(RDI_Parsed *rdi)
{
RDI_U64 decompressed_size = rdi->raw_data_size;
for(RDI_U64 section_idx = 0; section_idx < rdi->sections_count; section_idx += 1)
{
decompressed_size += (rdi->sections[section_idx].unpacked_size - rdi->sections[section_idx].encoded_size);
}
return decompressed_size;
}
//- strings
RDI_PROC RDI_U8 *
rdi_string_from_idx(RDI_Parsed *rdi, RDI_U32 idx, RDI_U64 *len_out)
{
RDI_U8 *result_base = 0;
RDI_U64 result_size = 0;
{
RDI_U64 string_offs_count = 0;
RDI_U32 *string_offs = rdi_table_from_name(rdi, StringTable, &string_offs_count);
if(idx < string_offs_count)
{
RDI_U64 string_data_size = 0;
RDI_U8 *string_data = rdi_table_from_name(rdi, StringData, &string_data_size);
RDI_U32 off_raw = string_offs[idx];
RDI_U32 opl_raw = string_offs[idx + 1];
RDI_U32 opl = rdi_parse__min(opl_raw, string_data_size);
RDI_U32 off = rdi_parse__min(off_raw, opl);
result_base = string_data + off;
result_size = opl - off;
}
}
*len_out = result_size;
return result_base;
}
//- index runs
RDI_PROC RDI_U32*
rdi_idx_run_from_first_count(RDI_Parsed *rdi, RDI_U32 raw_first, RDI_U32 raw_count, RDI_U32 *n_out)
{
RDI_U64 idx_run_count = 0;
RDI_U32 *idx_run_data = rdi_table_from_name(rdi, IndexRuns, &idx_run_count);
RDI_U32 raw_opl = raw_first + raw_count;
RDI_U32 opl = rdi_parse__min(raw_opl, idx_run_count);
RDI_U32 first = rdi_parse__min(raw_first, opl);
RDI_U32 *result = 0;
if(first < idx_run_count)
{
result = idx_run_data + first;
}
*n_out = opl - first;
return result;
}
//- line info
RDI_PROC void
rdi_parsed_from_line_table(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_ParsedLineTable *out)
{
//- rjf: extract top-level line info tables
RDI_U64 all_voffs_count = 0;
RDI_U64 *all_voffs = rdi_table_from_name(rdi, LineInfoVOffs, &all_voffs_count);
RDI_U64 *all_voffs_opl = all_voffs + all_voffs_count;
RDI_U64 all_lines_count = 0;
RDI_Line *all_lines = rdi_table_from_name(rdi, LineInfoLines, &all_lines_count);
RDI_Line *all_lines_opl = all_lines + all_lines_count;
RDI_U64 all_cols_count = 0;
RDI_Column *all_cols = rdi_table_from_name(rdi, LineInfoColumns, &all_cols_count);
RDI_Column *all_cols_opl = all_cols + all_cols_count;
//- rjf: extract ranges of top-level tables belonging to this line table
RDI_U64 *lt_voffs = all_voffs + line_table->voffs_base_idx;
RDI_Line *lt_lines = all_lines + line_table->lines_base_idx;
RDI_Column *lt_cols = all_cols + line_table->cols_base_idx;
RDI_U64 lines_count = line_table->lines_count;
RDI_U64 cols_count = line_table->cols_count;
if(lt_voffs >= all_voffs_opl) {lt_voffs = all_voffs; lines_count = 0;}
if(lt_lines >= all_lines_opl) {lt_lines = all_lines; lines_count = 0;}
if(lt_cols >= all_cols_opl) {lt_cols = all_cols; cols_count = 0;}
//- rjf: fill result
out->voffs = lt_voffs;
out->lines = lt_lines;
out->cols = lt_cols;
out->count = lines_count;
out->col_count = cols_count;
}
RDI_PROC RDI_U64
rdi_line_info_idx_range_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff, RDI_U64 *n_out)
{
RDI_U64 result = 0;
RDI_U64 n = 0;
if(line_info->count > 0 && line_info->voffs[0] <= voff && voff < line_info->voffs[line_info->count - 1])
{
//- rjf: find i such that: (vmap[i].voff <= voff) && (voff < vmap[i + 1].voff)
// assuming: (i < j) -> (vmap[i].voff < vmap[j].voff)
RDI_U32 first = 0;
RDI_U32 opl = line_info->count;
for(;;)
{
RDI_U32 mid = (first + opl)/2;
if(line_info->voffs[mid] < voff)
{
first = mid;
}
else if(line_info->voffs[mid] > voff)
{
opl = mid;
}
else
{
first = mid;
break;
}
if(opl - first <= 1)
{
break;
}
}
result = (RDI_U64)first;
//- rjf: scan leftward, to find shallowest line info matching this voff
for(;result != 0;)
{
if(line_info->voffs[result-1] == voff)
{
result -= 1;
}
else
{
break;
}
}
//- rjf: scan rightward, to count # of line info with this voff
for(RDI_U64 idx = result; idx < line_info->count; idx += 1)
{
if(line_info->voffs[idx] == voff)
{
n += 1;
}
else
{
break;
}
}
}
if(n_out)
{
*n_out = n;
}
return result;
}
RDI_PROC RDI_U64
rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff)
{
RDI_U64 count = 0;
RDI_U64 result = rdi_line_info_idx_range_from_voff(line_info, voff, &count);
for(RDI_S64 idx = count-1; idx >= 0; idx -= 1)
{
if(result + idx < line_info->count && line_info->lines[result+idx].file_idx != 0)
{
result += idx;
break;
}
}
return result;
}
RDI_PROC void
rdi_parsed_from_source_line_map(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_ParsedSourceLineMap *out)
{
//- rjf: extract top-level line info tables
RDI_U64 all_nums_count = 0;
RDI_U32 *all_nums = rdi_table_from_name(rdi, SourceLineMapNumbers, &all_nums_count);
RDI_U32 *all_nums_opl = all_nums + all_nums_count;
RDI_U64 all_rngs_count = 0;
RDI_U32 *all_rngs = rdi_table_from_name(rdi, SourceLineMapRanges, &all_rngs_count);
RDI_U32 *all_rngs_opl = all_rngs + all_rngs_count;
RDI_U64 all_voffs_count = 0;
RDI_U64 *all_voffs = rdi_table_from_name(rdi, SourceLineMapVOffs, &all_voffs_count);
RDI_U64 *all_voffs_opl = all_voffs + all_voffs_count;
//- rjf: extract ranges of top-level tables belonging to this line map
RDI_U32 *map_nums = all_nums + map->line_map_nums_base_idx;
RDI_U32 *map_rngs = all_rngs + map->line_map_range_base_idx;
RDI_U64 *map_voffs= all_voffs+ map->line_map_voff_base_idx;
RDI_U64 lines_count = (RDI_U64)map->line_count;
RDI_U64 voffs_count = (RDI_U64)map->voff_count;
if(map_nums >= all_nums_opl) {map_nums = all_nums; lines_count = 0;}
if(map_rngs >= all_rngs_opl) {map_rngs = all_rngs; lines_count = 0;}
if(map_voffs>= all_voffs_opl){map_voffs= all_voffs;voffs_count = 0;}
//- rjf: fill result
out->nums = map_nums;
out->ranges = map_rngs;
out->voffs = map_voffs;
out->count = lines_count;
out->voff_count = voffs_count;
}
RDI_PROC RDI_U64 *
rdi_line_voffs_from_num(RDI_ParsedSourceLineMap *map, RDI_U32 linenum, RDI_U32 *n_out)
{
RDI_U64 *result = 0;
*n_out = 0;
RDI_U32 closest_i = 0;
if(map->count > 0 && map->nums[0] <= linenum)
{
// assuming: (i < j) -> (nums[i] < nums[j])
// find i such that: (nums[i] <= linenum) && (linenum < nums[i + 1])
RDI_U32 *nums = map->nums;
RDI_U32 first = 0;
RDI_U32 opl = map->count;
for(;;)
{
RDI_U32 mid = (first + opl)/2;
if(nums[mid] < linenum)
{
first = mid;
}
else if(nums[mid] > linenum)
{
opl = mid;
}
else
{
first = mid;
break;
}
if(opl - first <= 1)
{
break;
}
}
closest_i = first;
}
// round up instead of down if possible
if(closest_i + 1 < map->count && map->nums[closest_i] < linenum)
{
closest_i += 1;
}
// set result if possible
if(closest_i < map->count)
{
RDI_U32 first = map->ranges[closest_i];
RDI_U32 opl = map->ranges[closest_i + 1];
if(opl <= map->voff_count)
{
result = map->voffs + first;
*n_out = opl - first;
}
}
return result;
}
//- vmap lookups
RDI_PROC RDI_U64
rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U64 vmap_count, RDI_U64 voff)
{
RDI_U64 result = 0;
if(vmap_count > 0 && vmap[0].voff <= voff && voff < vmap[vmap_count - 1].voff)
{
// assuming: (i < j) -> (vmap[i].voff < vmap[j].voff)
// find i such that: (vmap[i].voff <= voff) && (voff < vmap[i + 1].voff)
RDI_U32 first = 0;
RDI_U32 opl = vmap_count;
for(;;)
{
RDI_U32 mid = (first + opl)/2;
if(vmap[mid].voff < voff)
{
first = mid;
}
else if(vmap[mid].voff > voff)
{
opl = mid;
}
else
{
first = mid;
break;
}
if(opl - first <= 1)
{
break;
}
}
result = (RDI_U64)vmap[first].idx;
}
return result;
}
RDI_PROC RDI_U64
rdi_vmap_idx_from_section_kind_voff(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 voff)
{
RDI_U64 vmaps_count = 0;
RDI_VMapEntry *vmaps = rdi_section_raw_table_from_kind(rdi, kind, &vmaps_count);
RDI_U64 result = rdi_vmap_idx_from_voff(vmaps, vmaps_count, voff);
return result;
}
//- name maps
RDI_PROC void
rdi_parsed_from_name_map(RDI_Parsed *rdi, RDI_NameMap *mapptr, RDI_ParsedNameMap *out)
{
out->buckets = 0;
out->bucket_count = 0;
if(mapptr != 0)
{
RDI_U64 all_buckets_count = 0;
RDI_NameMapBucket *all_buckets = rdi_table_from_name(rdi, NameMapBuckets, &all_buckets_count);
RDI_U64 all_nodes_count = 0;
RDI_NameMapNode *all_nodes = rdi_table_from_name(rdi, NameMapNodes, &all_nodes_count);
out->buckets = all_buckets+mapptr->bucket_base_idx;
out->nodes = all_nodes+mapptr->node_base_idx;
out->bucket_count = mapptr->bucket_count;
out->node_count = mapptr->node_count;
if(mapptr->bucket_base_idx > all_buckets_count)
{
out->buckets = 0;
out->bucket_count = 0;
}
if(mapptr->node_base_idx > all_nodes_count)
{
out->nodes = 0;
out->node_count = 0;
}
}
}
RDI_PROC RDI_NameMapNode*
rdi_name_map_lookup(RDI_Parsed *p, RDI_ParsedNameMap *map, RDI_U8 *str, RDI_U64 len)
{
RDI_NameMapNode *result = 0;
if(map->bucket_count > 0)
{
RDI_NameMapBucket *buckets = map->buckets;
RDI_U64 bucket_count = map->bucket_count;
RDI_U64 hash = rdi_hash(str, len);
RDI_U64 bucket_index = hash%bucket_count;
RDI_NameMapBucket *bucket = map->buckets + bucket_index;
RDI_NameMapNode *node = map->nodes + bucket->first_node;
RDI_NameMapNode *node_opl = node + bucket->node_count;
for(;node < node_opl; node += 1)
{
// extract a string from this node
RDI_U64 nlen = 0;
RDI_U8 *nstr = rdi_string_from_idx(p, node->string_idx, &nlen);
// compare this to the needle string
RDI_S32 match = 0;
if(nlen == len)
{
RDI_U8 *a = str;
RDI_U8 *aopl = str + len;
RDI_U8 *b = nstr;
for (;a < aopl && *a == *b; a += 1, b += 1);
match = (a == aopl);
}
// stop with a matching node in result
if(match)
{
result = node;
break;
}
}
}
return result;
}
RDI_PROC RDI_U32*
rdi_matches_from_map_node(RDI_Parsed *p, RDI_NameMapNode *node, RDI_U32 *n_out)
{
RDI_U32 *result = 0;
*n_out = 0;
if(node != 0)
{
if(node->match_count == 1)
{
result = &node->match_idx_or_idx_run_first;
*n_out = 1;
}
else
{
result = rdi_idx_run_from_first_count(p, node->match_idx_or_idx_run_first, node->match_count, n_out);
}
}
return result;
}
////////////////////////////////
//~ High-Level Composite Lookup Functions
//- procedures
RDI_PROC RDI_Procedure *
rdi_procedure_from_name(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size)
{
RDI_NameMap *map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures);
RDI_ParsedNameMap map_parsed = {0};
rdi_parsed_from_name_map(rdi, map, &map_parsed);
RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map_parsed, name, name_size);
RDI_U32 id_count = 0;
RDI_U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count);
RDI_U32 procedure_idx = 0;
if(id_count > 0)
{
procedure_idx = ids[0];
}
RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_idx);
return procedure;
}
RDI_PROC RDI_Procedure *
rdi_procedure_from_name_cstr(RDI_Parsed *rdi, char *cstr)
{
RDI_Procedure *result = rdi_procedure_from_name(rdi, (RDI_U8 *)cstr, rdi_cstring_length(cstr));
return result;
}
RDI_PROC RDI_U8 *
rdi_name_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure, RDI_U64 *len_out)
{
return rdi_string_from_idx(rdi, procedure->name_string_idx, len_out);
}
RDI_PROC RDI_Scope *
rdi_root_scope_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure)
{
RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx);
return scope;
}
RDI_PROC RDI_UDT *
rdi_container_udt_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure)
{
RDI_U64 idx = 0;
if(procedure->link_flags & RDI_LinkFlag_TypeScoped)
{
idx = procedure->container_idx;
}
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, idx);
return udt;
}
RDI_PROC RDI_Procedure *
rdi_container_procedure_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure)
{
RDI_U64 idx = 0;
if(procedure->link_flags & RDI_LinkFlag_ProcScoped)
{
idx = procedure->container_idx;
}
RDI_Procedure *container_procedure = rdi_element_from_name_idx(rdi, Procedures, idx);
return container_procedure;
}
RDI_PROC RDI_U64
rdi_first_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure)
{
RDI_Scope *scope = rdi_root_scope_from_procedure(rdi, procedure);
RDI_U64 result = rdi_first_voff_from_scope(rdi, scope);
return result;
}
RDI_PROC RDI_U64
rdi_opl_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure)
{
RDI_Scope *scope = rdi_root_scope_from_procedure(rdi, procedure);
RDI_U64 result = rdi_opl_voff_from_scope(rdi, scope);
return result;
}
RDI_PROC RDI_Procedure *
rdi_procedure_from_voff(RDI_Parsed *rdi, RDI_U64 voff)
{
RDI_Scope *scope = rdi_scope_from_voff(rdi, voff);
RDI_Procedure *procedure = rdi_procedure_from_scope(rdi, scope);
return procedure;
}
//- scopes
RDI_PROC RDI_U64
rdi_first_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope)
{
RDI_U64 *voffs = rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_first);
RDI_U64 result = *voffs;
return result;
}
RDI_PROC RDI_U64
rdi_opl_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope)
{
RDI_U64 result = 0;
if(scope->voff_range_opl != 0)
{
RDI_U64 *voffs = rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_opl-1);
result = *voffs;
}
return result;
}
RDI_PROC RDI_Scope *
rdi_scope_from_voff(RDI_Parsed *rdi, RDI_U64 voff)
{
RDI_U32 idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff);
RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, idx);
return scope;
}
RDI_PROC RDI_Scope *
rdi_parent_from_scope(RDI_Parsed *rdi, RDI_Scope *scope)
{
RDI_Scope *parent = rdi_element_from_name_idx(rdi, Scopes, scope->parent_scope_idx);
return parent;
}
RDI_PROC RDI_Procedure *
rdi_procedure_from_scope(RDI_Parsed *rdi, RDI_Scope *scope)
{
RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx);
return procedure;
}
RDI_PROC RDI_InlineSite *
rdi_inline_site_from_scope(RDI_Parsed *rdi, RDI_Scope *scope)
{
RDI_InlineSite *inline_site = rdi_element_from_name_idx(rdi, InlineSites, scope->inline_site_idx);
return inline_site;
}
//- global variables
RDI_PROC RDI_GlobalVariable *
rdi_global_variable_from_voff(RDI_Parsed *rdi, RDI_U64 voff)
{
RDI_U32 idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_GlobalVMap, voff);
RDI_GlobalVariable *gvar = rdi_element_from_name_idx(rdi, GlobalVariables, idx);
return gvar;
}
//- units
RDI_PROC RDI_Unit *
rdi_unit_from_voff(RDI_Parsed *rdi, RDI_U64 voff)
{
RDI_U32 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, voff);
RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx);
return unit;
}
RDI_PROC RDI_LineTable *
rdi_line_table_from_unit(RDI_Parsed *rdi, RDI_Unit *unit)
{
RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx);
return line_table;
}
//- line info
RDI_PROC RDI_Line
rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff)
{
RDI_Unit *unit = rdi_unit_from_voff(rdi, voff);
RDI_LineTable *line_table = rdi_line_table_from_unit(rdi, unit);
RDI_Line line = rdi_line_from_line_table_voff(rdi, line_table, voff);
return line;
}
RDI_PROC RDI_Line
rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff)
{
RDI_ParsedLineTable parsed = {0};
rdi_parsed_from_line_table(rdi, line_table, &parsed);
RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed, voff);
RDI_Line result = {0};
if(line_info_idx < parsed.count)
{
result = parsed.lines[line_info_idx];
}
return result;
}
RDI_PROC RDI_SourceFile *
rdi_source_file_from_line(RDI_Parsed *rdi, RDI_Line *line)
{
RDI_SourceFile *result = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx);
return result;
}
//- source files
RDI_PROC RDI_SourceFile *
rdi_source_file_from_normal_path(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size)
{
RDI_NameMap *map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths);
RDI_ParsedNameMap map_parsed = {0};
rdi_parsed_from_name_map(rdi, map, &map_parsed);
RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map_parsed, name, name_size);
RDI_U32 id_count = 0;
RDI_U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count);
RDI_U32 file_idx = 0;
if(id_count > 0)
{
file_idx = ids[0];
}
RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, file_idx);
return file;
}
RDI_PROC RDI_SourceFile *
rdi_source_file_from_normal_path_cstr(RDI_Parsed *rdi, char *cstr)
{
RDI_SourceFile *result = rdi_source_file_from_normal_path(rdi, (RDI_U8 *)cstr, rdi_cstring_length(cstr));
return result;
}
RDI_PROC RDI_U8 *
rdi_normal_path_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U64 *len_out)
{
return rdi_string_from_idx(rdi, src_file->normal_full_path_string_idx, len_out);
}
RDI_PROC RDI_FilePathNode *
rdi_file_path_node_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file)
{
RDI_FilePathNode *result = rdi_element_from_name_idx(rdi, FilePathNodes, src_file->file_path_node_idx);
return result;
}
RDI_PROC RDI_SourceLineMap *
rdi_source_line_map_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file)
{
RDI_SourceLineMap *result = rdi_element_from_name_idx(rdi, SourceLineMaps, src_file->source_line_map_idx);
return result;
}
RDI_PROC RDI_U64
rdi_first_voff_from_source_file_line_num(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U32 line_num)
{
RDI_SourceLineMap *source_line_map = rdi_source_line_map_from_source_file(rdi, src_file);
RDI_U64 voff = rdi_first_voff_from_source_line_map_num(rdi, source_line_map, line_num);
return voff;
}
//- source line maps
RDI_PROC RDI_U64
rdi_first_voff_from_source_line_map_num(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_U32 line_num)
{
RDI_ParsedSourceLineMap parsed = {0};
rdi_parsed_from_source_line_map(rdi, map, &parsed);
RDI_U32 all_voffs_count = 0;
RDI_U64 *all_voffs = rdi_line_voffs_from_num(&parsed, line_num, &all_voffs_count);
RDI_U64 voff = 0;
if(all_voffs_count != 0)
{
voff = all_voffs[0];
}
return voff;
}
//- file path nodes
RDI_PROC RDI_FilePathNode *
rdi_parent_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node)
{
RDI_FilePathNode *result = rdi_element_from_name_idx(rdi, FilePathNodes, node->parent_path_node);
return result;
}
RDI_PROC RDI_U8 *
rdi_name_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node, RDI_U64 *len_out)
{
return rdi_string_from_idx(rdi, node->name_string_idx, len_out);
}
////////////////////////////////
//~ Parser Helpers
RDI_PROC RDI_U64
rdi_cstring_length(char *cstr)
{
RDI_U64 result = 0;
for(;cstr[result] != 0; result += 1){}
return result;
}
RDI_PROC RDI_U64
rdi_size_from_bytecode_stream(RDI_U8 *ptr, RDI_U8 *opl)
{
RDI_U64 bytecode_size = 0;
RDI_U8 *off_first = ptr + sizeof(RDI_LocationKind);
for(RDI_U8 *off = off_first, *next_off = opl; off < opl; off = next_off)
{
RDI_U8 op = *off;
if(op == 0)
{
break;
}
RDI_U16 ctrlbits = rdi_eval_op_ctrlbits_table[op];
RDI_U32 p_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits);
bytecode_size += (1 + p_size);
next_off = (off + 1 + p_size);
}
return bytecode_size;
}
+34 -49
View File
@@ -196,6 +196,21 @@ rdim_str8_match(RDIM_String8 a, RDIM_String8 b, RDIM_StringMatchFlags flags)
return result;
}
RDI_PROC RDIM_String8
rdim_lower_from_str8(RDIM_Arena *arena, RDIM_String8 string)
{
RDIM_String8 result = rdim_str8_copy(arena, string);
for(RDI_U64 idx = 0; idx < result.RDIM_String8_SizeMember; idx += 1)
{
RDI_U8 byte = result.RDIM_String8_BaseMember[idx];
if('A' <= byte && byte <= 'Z')
{
result.RDIM_String8_BaseMember[idx] += ('a' - 'A');
}
}
return result;
}
//- rjf: string lists
RDI_PROC void
@@ -464,7 +479,7 @@ rdim_rng1u64_chunk_list_push(RDIM_Arena *arena, RDIM_Rng1U64ChunkList *list, RDI
//~ Data Model
RDI_PROC RDI_TypeKind
rdim_short_type_from_data_model(RDIM_DataModel data_model)
rdim_short_type_kind_from_data_model(RDIM_DataModel data_model)
{
switch(data_model)
{
@@ -480,7 +495,7 @@ rdim_short_type_from_data_model(RDIM_DataModel data_model)
}
RDI_PROC RDI_TypeKind
rdim_unsigned_short_type_from_data_model(RDIM_DataModel data_model)
rdim_unsigned_short_type_kind_from_data_model(RDIM_DataModel data_model)
{
switch(data_model)
{
@@ -528,7 +543,7 @@ rdim_unsigned_int_type_from_data_model(RDIM_DataModel data_model)
}
RDI_PROC RDI_TypeKind
rdim_long_type_from_data_model(RDIM_DataModel data_model)
rdim_long_type_kind_from_data_model(RDIM_DataModel data_model)
{
switch(data_model)
{
@@ -544,7 +559,7 @@ rdim_long_type_from_data_model(RDIM_DataModel data_model)
}
RDI_PROC RDI_TypeKind
rdim_unsigned_long_type_from_data_model(RDIM_DataModel data_model)
rdim_unsigned_long_type_kind_from_data_model(RDIM_DataModel data_model)
{
switch(data_model)
{
@@ -560,7 +575,7 @@ rdim_unsigned_long_type_from_data_model(RDIM_DataModel data_model)
}
RDI_PROC RDI_TypeKind
rdim_long_long_type_from_data_model(RDIM_DataModel data_model)
rdim_long_long_type_kind_from_data_model(RDIM_DataModel data_model)
{
switch(data_model)
{
@@ -576,7 +591,7 @@ rdim_long_long_type_from_data_model(RDIM_DataModel data_model)
}
RDI_PROC RDI_TypeKind
rdim_unsigned_long_long_type_from_data_model(RDIM_DataModel data_model)
rdim_unsigned_long_long_type_kind_from_data_model(RDIM_DataModel data_model)
{
switch(data_model)
{
@@ -592,7 +607,7 @@ rdim_unsigned_long_long_type_from_data_model(RDIM_DataModel data_model)
}
RDI_PROC RDI_TypeKind
rdim_pointer_size_t_type_from_data_model(RDIM_DataModel data_model)
rdim_pointer_size_t_type_kind_from_data_model(RDIM_DataModel data_model)
{
switch(data_model)
{
@@ -1331,41 +1346,6 @@ rdim_count_from_location_block_chunk_list(RDIM_String8List *list)
return count;
}
////////////////////////////////
RDI_PROC RDIM_Type *
rdim_builtin_type_from_kind(RDIM_TypeChunkList list, RDI_TypeKind type_kind)
{
return &list.first->v[type_kind];
}
RDI_PROC RDIM_TypeChunkList
rdim_init_type_chunk_list(RDIM_Arena *arena, RDI_Arch arch)
{
RDIM_TypeChunkList list = {0};
RDI_U64 type_cap = (RDI_TypeKind_LastBuiltIn - RDI_TypeKind_FirstBuiltIn) + 2;
// RDI_TypeKind_NULL
rdim_type_chunk_list_push(arena, &list, type_cap);
for(RDI_TypeKind type_kind = RDI_TypeKind_FirstBuiltIn; type_kind <= RDI_TypeKind_LastBuiltIn; type_kind += 1)
{
RDIM_Type *type = rdim_type_chunk_list_push(arena, &list, type_cap);
type->name.str = rdi_string_from_type_kind(type_kind, &type->name.size);
type->kind = type_kind;
type->byte_size = rdi_size_from_basic_type_kind(type_kind);
}
RDIM_Type *void_type = rdim_builtin_type_from_kind(list, RDI_TypeKind_Void);
void_type->byte_size = rdi_addr_size_from_arch(arch);
RDIM_Type *handle_type = rdim_builtin_type_from_kind(list, RDI_TypeKind_Handle);
handle_type->byte_size = rdi_addr_size_from_arch(arch);
return list;
}
////////////////////////////////
//~ rjf: [Baking Helpers] Baked VMap Building
@@ -1949,7 +1929,7 @@ rdim_bake_path_node_from_string(RDIM_BakePathTree *tree, RDIM_String8 string)
RDIM_BakePathNode *sub_dir_node = 0;
for(RDIM_BakePathNode *child = node->first_child; child != 0; child = child->next_sibling)
{
if(rdim_str8_match(child->name, sub_dir, RDIM_StringMatchFlag_CaseInsensitive))
if(rdim_str8_match(child->name, sub_dir, 0))
{
sub_dir_node = child;
}
@@ -2022,7 +2002,7 @@ rdim_bake_path_tree_insert(RDIM_Arena *arena, RDIM_BakePathTree *tree, RDIM_Stri
RDIM_BakePathNode *sub_dir_node = 0;
for(RDIM_BakePathNode *child = node->first_child; child != 0; child = child->next_sibling)
{
if(rdim_str8_match(child->name, sub_dir, RDIM_StringMatchFlag_CaseInsensitive))
if(rdim_str8_match(child->name, sub_dir, 0))
{
sub_dir_node = child;
}
@@ -2210,7 +2190,8 @@ rdim_bake_string_map_loose_push_src_file_slice(RDIM_Arena *arena, RDIM_BakeStrin
{
for(RDI_U64 idx = 0; idx < count; idx += 1)
{
rdim_bake_string_map_loose_insert(arena, top, map, 1, v[idx].normal_full_path);
RDIM_String8 normalized_path = rdim_lower_from_str8(arena, v[idx].path);
rdim_bake_string_map_loose_insert(arena, top, map, 1, normalized_path);
}
}
@@ -2438,7 +2419,8 @@ rdim_bake_name_map_from_kind_params(RDIM_Arena *arena, RDI_NameMapKind kind, RDI
for(RDI_U64 idx = 0; idx < n->count; idx += 1)
{
RDI_U64 src_file_idx = rdim_idx_from_src_file(&n->v[idx]);
rdim_bake_name_map_push(arena, map, n->v[idx].normal_full_path, (RDI_U32)src_file_idx); // TODO(rjf): @u64_to_u32
RDIM_String8 normalized_path = rdim_lower_from_str8(arena, n->v[idx].path);
rdim_bake_name_map_push(arena, map, normalized_path, (RDI_U32)src_file_idx); // TODO(rjf): @u64_to_u32
}
}
}break;
@@ -2545,7 +2527,7 @@ rdim_bake_path_tree_from_params(RDIM_Arena *arena, RDIM_BakeParams *params)
{
for(RDI_U64 idx = 0; idx < n->count; idx += 1)
{
RDIM_BakePathNode *node = rdim_bake_path_tree_insert(arena, tree, n->v[idx].normal_full_path);
RDIM_BakePathNode *node = rdim_bake_path_tree_insert(arena, tree, n->v[idx].path);
node->src_file = &n->v[idx];
}
}
@@ -3056,9 +3038,12 @@ rdim_bake_src_files(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_Ba
////////////////////////
//- rjf: fill file info
//
dst_file->file_path_node_idx = rdim_bake_path_node_idx_from_string(path_tree, src_file->normal_full_path);
dst_file->normal_full_path_string_idx = rdim_bake_idx_from_string(strings, src_file->normal_full_path);
RDI_U64 scratch_pos_restore = rdim_arena_pos(scratch.arena);
RDIM_String8 normalized_path = rdim_lower_from_str8(scratch.arena, src_file->path);
dst_file->file_path_node_idx = rdim_bake_path_node_idx_from_string(path_tree, src_file->path);
dst_file->normal_full_path_string_idx = rdim_bake_idx_from_string(strings, normalized_path);
dst_file->source_line_map_idx = (RDI_U32)(dst_map ? (dst_map - dst_maps) : 0);
rdim_arena_pop_to(scratch.arena, scratch_pos_restore);
}
}
+10 -14
View File
@@ -535,7 +535,7 @@ typedef struct RDIM_SrcFile RDIM_SrcFile;
struct RDIM_SrcFile
{
struct RDIM_SrcFileChunkNode *chunk;
RDIM_String8 normal_full_path;
RDIM_String8 path;
RDIM_SrcFileLineMapFragment *first_line_map_fragment;
RDIM_SrcFileLineMapFragment *last_line_map_fragment;
};
@@ -1411,6 +1411,7 @@ RDI_PROC RDI_S32 rdim_str8_match(RDIM_String8 a, RDIM_String8 b, RDIM_StringMatc
#define rdim_str8_lit(S) rdim_str8((RDI_U8*)(S), sizeof(S) - 1)
#define rdim_str8_struct(S) rdim_str8((RDI_U8*)(S), sizeof(*(S)))
#define rdim_str8_struct_array(S, C) rdim_str8((RDI_U8*)(S), sizeof(*(S)) * (C))
RDI_PROC RDIM_String8 rdim_lower_from_str8(RDIM_Arena *arena, RDIM_String8 string);
//- rjf: string lists
RDI_PROC void rdim_str8_list_push(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 string);
@@ -1428,15 +1429,15 @@ RDI_PROC void rdim_rng1u64_chunk_list_push(RDIM_Arena *arena, RDIM_Rng1U64ChunkL
////////////////////////////////
//~ Data Model
RDI_PROC RDI_TypeKind rdim_short_type_from_data_model(RDIM_DataModel data_model);
RDI_PROC RDI_TypeKind rdim_unsigned_short_type_from_data_model(RDIM_DataModel data_model);
RDI_PROC RDI_TypeKind rdim_short_type_kind_from_data_model(RDIM_DataModel data_model);
RDI_PROC RDI_TypeKind rdim_unsigned_short_type_kind_from_data_model(RDIM_DataModel data_model);
RDI_PROC RDI_TypeKind rdim_int_type_from_data_model(RDIM_DataModel data_model);
RDI_PROC RDI_TypeKind rdim_unsigned_int_type_from_data_model(RDIM_DataModel data_model);
RDI_PROC RDI_TypeKind rdim_long_type_from_data_model(RDIM_DataModel data_model);
RDI_PROC RDI_TypeKind rdim_unsigned_long_type_from_data_model(RDIM_DataModel data_model);
RDI_PROC RDI_TypeKind rdim_long_long_type_from_data_model(RDIM_DataModel data_model);
RDI_PROC RDI_TypeKind rdim_unsigned_long_long_type_from_data_model(RDIM_DataModel data_model);
RDI_PROC RDI_TypeKind rdim_pointer_size_t_type_from_data_model(RDIM_DataModel data_model);
RDI_PROC RDI_TypeKind rdim_long_type_kind_from_data_model(RDIM_DataModel data_model);
RDI_PROC RDI_TypeKind rdim_unsigned_long_type_kind_from_data_model(RDIM_DataModel data_model);
RDI_PROC RDI_TypeKind rdim_long_long_type_kind_from_data_model(RDIM_DataModel data_model);
RDI_PROC RDI_TypeKind rdim_unsigned_long_long_type_kind_from_data_model(RDIM_DataModel data_model);
RDI_PROC RDI_TypeKind rdim_pointer_size_t_type_kind_from_data_model(RDIM_DataModel data_model);
////////////////////////////////
//~ rjf: [Building] Binary Section Info Building
@@ -1519,15 +1520,10 @@ RDI_PROC RDIM_Location *rdim_push_location_val_reg(RDIM_Arena *arena, RDI_U8 reg
//- rjf: location sets
RDI_PROC void rdim_location_set_push_case(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_LocationSet *locset, RDIM_Rng1U64 voff_range, RDIM_Location *location);
//- rjf:location block chunk list
//- rjf: location block chunk list
RDI_PROC RDI_LocationBlock *rdim_location_block_chunk_list_push_array(RDIM_Arena *arena, RDIM_String8List *list, RDI_U32 count);
RDI_PROC RDI_U32 rdim_count_from_location_block_chunk_list(RDIM_String8List *list);
////////////////////////////////
RDI_PROC RDIM_TypeChunkList rdim_init_type_chunk_list(RDIM_Arena *arena, RDI_Arch arch);
RDI_PROC RDIM_Type * rdim_builtin_type_from_kind(RDIM_TypeChunkList list, RDI_TypeKind type_kind);
////////////////////////////////
//~ rjf: [Baking Helpers] Baked VMap Building
+1 -12
View File
@@ -1,17 +1,6 @@
// Copyright (c) 2024 Epic Games Tools
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal String8
push_cstr(Arena *arena, String8 str)
{
U64 buffer_size = str.size + 1;
U8 *buffer = push_array_no_zero(arena, U8, buffer_size);
MemoryCopy(buffer, str.str, str.size);
buffer[str.size] = 0;
String8 result = str8(buffer, buffer_size);
return result;
}
internal U32 *
push_u32(Arena *arena, U32 value)
{
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2024 Epic Games Tools
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#pragma once
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2024 Epic Games Tools
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal U64
+7 -1
View File
@@ -1,8 +1,14 @@
// Copyright (c) 2024 Epic Games Tools
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#pragma once
typedef struct U32Node
{
struct U32Node *next;
U32 data;
} U32Node;
typedef struct U64Node
{
struct U64Node *next;
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2024 Epic Games Tools
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal U32Array
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2024 Epic Games Tools
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#pragma once
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2024 Epic Games Tools
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#if defined(__clang__)
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2024 Epic Games Tools
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#pragma once
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2024 Epic Games Tools
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#include "../third_party_ext/blake3/blake3_portable.c"
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2024 Epic Games Tools
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_BLAKE3_H
+27 -11
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2024 Epic Games Tools
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal U16
@@ -8,16 +8,12 @@ safe_cast_u16x(U64 x)
return (U16)x;
}
////////////////////////////////
internal U64
u128_mod64(U128 a, U64 b)
{
return a.u64[1] % b;
}
////////////////////////////////
internal Version
make_version(U64 major, U64 minor)
{
@@ -45,8 +41,6 @@ version_compar(Version a, Version b)
return cmp;
}
////////////////////////////////
internal ISectOff
isect_off(U32 isect, U32 off)
{
@@ -54,8 +48,6 @@ isect_off(U32 isect, U32 off)
return result;
}
////////////////////////////////
internal int
u16_compar(const void *raw_a, const void *raw_b)
{
@@ -123,7 +115,6 @@ u64_compar_is_before(void *raw_a, void *raw_b)
return is_before;
}
internal int
u8_is_before(void *raw_a, void *raw_b)
{
@@ -212,8 +203,33 @@ pair_u64_compar_v1(const void *raw_a, const void *raw_b)
return u64_compar(&a->v1, &b->v1);
}
internal U64
pair_u64_nearest_v0(PairU64 *arr, U64 count, U64 v)
{
U64 result = max_U64;
////////////////////////////////
if (count > 1 && arr[0].v0 <= v && v < arr[count-1].v0) {
U64 l = 0;
U64 r = count - 1;
for (; l <= r; ) {
U64 m = l + (r - l) / 2;
if (arr[m].v0 == v) {
return m;
} else if (arr[m].v0 < v) {
l = m + 1;
} else {
r = m - 1;
}
}
result = l;
} else if (count == 1 && arr[0].v0 == v) {
result = 0;
} else if (count > 0 && v >= arr[count-1].v0) {
result = count-1;
}
return result;
}
internal void
str8_list_concat_in_place_array(String8List *list, String8List *arr, U64 count)
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2024 Epic Games Tools
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#pragma once
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2024 Epic Games Tools
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal U32
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2024 Epic Games Tools
// Copyright (c) 2025 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#pragma once

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