diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index b2de41ba..2c30d5fc 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -17,9 +17,7 @@ jobs: target: - raddbg - radlink - - rdi_from_pdb - - raddump - - rdi_breakpad_from_pdb + - radbin compiler: - msvc - clang diff --git a/build.bat b/build.bat index d8a2ca72..76ce1902 100644 --- a/build.bat +++ b/build.bat @@ -24,6 +24,7 @@ cd /D "%~dp0" :: :: - `asan`: enable address sanitizer :: - `telemetry`: enable RAD telemetry profiling support +:: - `spall`: enable spall profiling support :: --- Unpack Arguments ------------------------------------------------------- for %%a in (%*) do set "%%a=1" @@ -39,21 +40,22 @@ if "%~1"=="release" if "%~2"=="" echo [default mode, assuming `raddbg` build] && :: --- Unpack Command Line Build Arguments ------------------------------------ set auto_compile_flags= if "%telemetry%"=="1" set auto_compile_flags=%auto_compile_flags% -DPROFILE_TELEMETRY=1 && echo [telemetry profiling enabled] +if "%spall%"=="1" set auto_compile_flags=%auto_compile_flags% -DPROFILE_SPALL=1 && echo [spall profiling enabled] if "%asan%"=="1" set auto_compile_flags=%auto_compile_flags% -fsanitize=address && echo [asan enabled] if "%opengl%"=="1" set auto_compile_flags=%auto_compile_flags% -DR_BACKEND=R_BACKEND_OPENGL && echo [opengl render backend] :: --- Compile/Link Line Definitions ------------------------------------------ set cl_common= /I..\src\ /I..\local\ /nologo /FC /Z7 -set clang_common= -I..\src\ -I..\local\ -gcodeview -fdiagnostics-absolute-paths -Wall -Wno-unknown-warning-option -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Wno-initializer-overrides -Wno-incompatible-pointer-types-discards-qualifiers -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf -ferror-limit=10000 set cl_debug= call cl /Od /Ob1 /DBUILD_DEBUG=1 %cl_common% %auto_compile_flags% set cl_release= call cl /O2 /DBUILD_DEBUG=0 %cl_common% %auto_compile_flags% +set cl_link= /link /MANIFEST:EMBED /INCREMENTAL:NO /pdbaltpath:%%%%_PDB%%%% /NATVIS:"%~dp0\src\natvis\base.natvis" /noexp +set cl_out= /out: +set cl_linker= +set clang_common= -I..\src\ -I..\local\ -gcodeview -fdiagnostics-absolute-paths -Wall -Wno-unknown-warning-option -Wno-missing-braces -Wno-unused-function -Wno-unused-parameter -Wno-writable-strings -Wno-missing-field-initializers -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Wno-initializer-overrides -Wno-incompatible-pointer-types-discards-qualifiers -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf -ferror-limit=10000 set clang_debug= call clang -g -O0 -DBUILD_DEBUG=1 %clang_common% %auto_compile_flags% set clang_release= call clang -g -O2 -DBUILD_DEBUG=0 %clang_common% %auto_compile_flags% -set cl_link= /link /MANIFEST:EMBED /INCREMENTAL:NO /pdbaltpath:%%%%_PDB%%%% /NATVIS:"%~dp0\src\natvis\base.natvis" /noexp set clang_link= -fuse-ld=lld -Xlinker /MANIFEST:EMBED -Xlinker /pdbaltpath:%%%%_PDB%%%% -Xlinker /NATVIS:"%~dp0\src\natvis\base.natvis" -set cl_out= /out: set clang_out= -o -set cl_linker= set clang_linker= -Xlinker :: --- Per-Build Settings ----------------------------------------------------- @@ -108,11 +110,8 @@ if not "%no_meta%"=="1" ( pushd build if "%raddbg%"=="1" set didbuild=1 && %compile% ..\src\raddbg\raddbg_main.c %compile_link% %link_icon% %out%raddbg.exe || exit /b 1 if "%radlink%"=="1" set didbuild=1 && %compile% ..\src\linker\lnk.c %compile_link% %linker% /NOIMPLIB %linker% /NATVIS:"%~dp0\src\linker\linker.natvis" %out%radlink.exe || exit /b 1 -if "%radcon%"=="1" set didbuild=1 && %compile% ..\src\radcon\radcon_main.c %compile_link% %out%radcon.exe || exit /b 1 +if "%radbin%"=="1" set didbuild=1 && %compile% ..\src\radbin\radbin_main.c %compile_link% %out%radbin.exe || exit /b 1 if "%raddump%"=="1" set didbuild=1 && %compile% ..\src\raddump\raddump_main.c %compile_link% %out%raddump.exe || exit /b 1 -if "%rdi_from_pdb%"=="1" set didbuild=1 && %compile% ..\src\rdi_from_pdb\rdi_from_pdb_main.c %compile_link% %out%rdi_from_pdb.exe || exit /b 1 -if "%rdi_from_dwarf%"=="1" set didbuild=1 && %compile% ..\src\rdi_from_dwarf\rdi_from_dwarf_main.c %compile_link% %out%rdi_from_dwarf.exe || exit /b 1 -if "%rdi_breakpad_from_pdb%"=="1" set didbuild=1 && %compile% ..\src\rdi_breakpad_from_pdb\rdi_breakpad_from_pdb_main.c %compile_link% %out%rdi_breakpad_from_pdb.exe || exit /b 1 if "%tester%"=="1" set didbuild=1 && %compile% ..\src\tester\tester_main.c %compile_link% %out%tester.exe || exit /b 1 if "%ryan_scratch%"=="1" set didbuild=1 && %compile% ..\src\scratch\ryan_scratch.c %compile_link% %out%ryan_scratch.exe || exit /b 1 if "%eval_scratch%"=="1" set didbuild=1 && %compile% ..\src\scratch\eval_scratch.c %compile_link% %out%eval_scratch.exe || exit /b 1 diff --git a/project.4coder b/project.4coder index 32a1e737..da1093ae 100644 --- a/project.4coder +++ b/project.4coder @@ -46,7 +46,7 @@ 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, }, //- 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, }, @@ -54,6 +54,9 @@ commands = //- rjf: [tester] // .f1 = { .win = "raddbg_stable --ipc kill_all && build no_meta tester", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, + //- rjf: [radbin] + .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 = "pushd build && raddbg --user:dev.raddbg_user && popd", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, diff --git a/src/async/async.c b/src/async/async.c index ec84c372..85ff743b 100644 --- a/src/async/async.c +++ b/src/async/async.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR @@ -234,6 +234,39 @@ async_execute_work(ASYNC_Work work) } } +//////////////////////////////// +//~ rjf: Root Allocation/Deallocation + +internal ASYNC_Root * +async_root_alloc(void) +{ + Arena *arena = arena_alloc(); + ASYNC_Root *root = push_array(arena, ASYNC_Root, 1); + root->arenas = push_array(arena, Arena *, async_thread_count()); + root->arenas[0] = arena; + for(U64 idx = 1; idx < async_thread_count(); idx += 1) + { + root->arenas[idx] = arena_alloc(); + } + return root; +} + +internal void +async_root_release(ASYNC_Root *root) +{ + for(U64 idx = 1; idx < async_thread_count(); idx += 1) + { + arena_release(root->arenas[idx]); + } + arena_release(root->arenas[0]); +} + +internal Arena * +async_root_thread_arena(ASYNC_Root *root) +{ + return root->arenas[async_work_thread_idx]; +} + //////////////////////////////// //~ rjf: Work Thread Entry Point diff --git a/src/async/async.h b/src/async/async.h index 6d9f2b00..a25492cb 100644 --- a/src/async/async.h +++ b/src/async/async.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef ASYNC_H @@ -70,6 +70,15 @@ struct ASYNC_TaskList U64 count; }; +//////////////////////////////// +//~ rjf: Root (Per-Worker-Thread Arena Bundle) + +typedef struct ASYNC_Root ASYNC_Root; +struct ASYNC_Root +{ + Arena **arenas; +}; + //////////////////////////////// //~ rjf: Shared State Bundle @@ -138,6 +147,13 @@ internal void *async_task_join(ASYNC_Task *task); internal ASYNC_Work async_pop_work(void); internal void async_execute_work(ASYNC_Work work); +//////////////////////////////// +//~ rjf: Root Allocation/Deallocation + +internal ASYNC_Root *async_root_alloc(void); +internal void async_root_release(ASYNC_Root *root); +internal Arena *async_root_thread_arena(ASYNC_Root *root); + //////////////////////////////// //~ rjf: Work Thread Entry Point diff --git a/src/base/base_arena.c b/src/base/base_arena.c index 68ad2544..314fcd9e 100644 --- a/src/base/base_arena.c +++ b/src/base/base_arena.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -37,6 +37,7 @@ arena_alloc_(ArenaParams *params) base = os_reserve(reserve_size); os_commit(base, commit_size); } + raddbg_annotate_vaddr_range(base, reserve_size, "arena %s:%i", params->allocation_site_file, params->allocation_site_line); } // rjf: panic on arena creation failure @@ -58,6 +59,8 @@ arena_alloc_(ArenaParams *params) arena->pos = ARENA_HEADER_SIZE; arena->cmt = commit_size; arena->res = reserve_size; + arena->allocation_site_file = params->allocation_site_file; + arena->allocation_site_line = params->allocation_site_line; #if ARENA_FREE_LIST arena->free_size = 0; arena->free_last = 0; @@ -123,7 +126,9 @@ arena_push(Arena *arena, U64 size, U64 align) } new_block = arena_alloc(.reserve_size = res_size, .commit_size = cmt_size, - .flags = current->flags); + .flags = current->flags, + .allocation_site_file = current->allocation_site_file, + .allocation_site_line = current->allocation_site_line); } new_block->base_pos = current->base_pos + current->res; diff --git a/src/base/base_arena.h b/src/base/base_arena.h index 8696f49f..47c5238d 100644 --- a/src/base/base_arena.h +++ b/src/base/base_arena.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_ARENA_H @@ -26,6 +26,8 @@ struct ArenaParams U64 reserve_size; U64 commit_size; void *optional_backing_buffer; + char *allocation_site_file; + int allocation_site_line; }; typedef struct Arena Arena; @@ -40,6 +42,8 @@ struct Arena U64 pos; U64 cmt; U64 res; + char *allocation_site_file; + int allocation_site_line; #if ARENA_FREE_LIST U64 free_size; Arena *free_last; @@ -66,7 +70,7 @@ global ArenaFlags arena_default_flags = 0; //- rjf: arena creation/destruction internal Arena *arena_alloc_(ArenaParams *params); -#define arena_alloc(...) arena_alloc_(&(ArenaParams){.reserve_size = arena_default_reserve_size, .commit_size = arena_default_commit_size, .flags = arena_default_flags, __VA_ARGS__}) +#define arena_alloc(...) arena_alloc_(&(ArenaParams){.reserve_size = arena_default_reserve_size, .commit_size = arena_default_commit_size, .flags = arena_default_flags, .allocation_site_file = __FILE__, .allocation_site_line = __LINE__, __VA_ARGS__}) internal void arena_release(Arena *arena); //- rjf: arena push/pop/pos core functions diff --git a/src/base/base_command_line.c b/src/base/base_command_line.c index ec726752..7792afde 100644 --- a/src/base/base_command_line.c +++ b/src/base/base_command_line.c @@ -1,19 +1,8 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// -//~ NOTE(rjf): Command Line Option Parsing - -internal U64 -cmd_line_hash_from_string(String8 string) -{ - U64 result = 5381; - for(U64 i = 0; i < string.size; i += 1) - { - result = ((result << 5) + result) + string.str[i]; - } - return result; -} +//~ rjf: Command Line Parsing Functions internal CmdLineOpt ** cmd_line_slot_from_string(CmdLine *cmd_line, String8 string) @@ -21,7 +10,7 @@ cmd_line_slot_from_string(CmdLine *cmd_line, String8 string) CmdLineOpt **slot = 0; if(cmd_line->option_table_size != 0) { - U64 hash = cmd_line_hash_from_string(string); + U64 hash = u64_hash_from_str8(string); U64 bucket = hash % cmd_line->option_table_size; slot = &cmd_line->option_table[bucket]; } @@ -64,7 +53,7 @@ cmd_line_insert_opt(Arena *arena, CmdLine *cmd_line, String8 string, String8List { var = push_array(arena, CmdLineOpt, 1); var->hash_next = *slot; - var->hash = cmd_line_hash_from_string(string); + var->hash = u64_hash_from_str8(string); var->string = push_str8_copy(arena, string); var->value_strings = values; StringJoin join = {0}; @@ -83,28 +72,25 @@ cmd_line_from_string_list(Arena *arena, String8List command_line) { CmdLine parsed = {0}; parsed.exe_name = command_line.first->string; + parsed.option_table_size = 64; + parsed.option_table = push_array(arena, CmdLineOpt *, parsed.option_table_size); - // NOTE(rjf): Set up config option table. - { - parsed.option_table_size = 4096; - parsed.option_table = push_array(arena, CmdLineOpt *, parsed.option_table_size); - } - - // NOTE(rjf): Parse command line. + //- rjf: parse options / inputs B32 after_passthrough_option = 0; B32 first_passthrough = 1; for(String8Node *node = command_line.first->next, *next = 0; node != 0; node = next) { next = node->next; - String8 option_name = node->string; - // NOTE(rjf): Look at --, -, or / (only on Windows) at the start of an - // argument to determine if it's a flag option. All arguments after a + //- rjf: look at --, -, or / (only on Windows) at the start of an + // argument to determine if it's a flag option. all arguments after a // single "--" (with no trailing string on the command line will be - // considered as input files. - B32 is_option = 1; - if(after_passthrough_option == 0) + // considered as passthrough input strings. + B32 is_option = 0; + String8 option_name = node->string; + if(!after_passthrough_option) { + is_option = 1; if(str8_match(node->string, str8_lit("--"), 0)) { after_passthrough_option = 1; @@ -128,69 +114,61 @@ cmd_line_from_string_list(Arena *arena, String8List command_line) is_option = 0; } } - else - { - is_option = 0; - } - // NOTE(rjf): This string is an option. + //- rjf: string is an option if(is_option) { - B32 has_arguments = 0; - U64 arg_signifier_position1 = str8_find_needle(option_name, 0, str8_lit(":"), 0); - U64 arg_signifier_position2 = str8_find_needle(option_name, 0, str8_lit("="), 0); - U64 arg_signifier_position = Min(arg_signifier_position1, arg_signifier_position2); - String8 arg_portion_this_string = str8_skip(option_name, arg_signifier_position+1); - if(arg_signifier_position < option_name.size) + // rjf: unpack option prefix + B32 has_values = 0; + U64 value_signifier_position1 = str8_find_needle(option_name, 0, str8_lit(":"), 0); + U64 value_signifier_position2 = str8_find_needle(option_name, 0, str8_lit("="), 0); + U64 value_signifier_position = Min(value_signifier_position1, value_signifier_position2); + String8 value_portion_this_string = str8_skip(option_name, value_signifier_position+1); + if(value_signifier_position < option_name.size) { - has_arguments = 1; + has_values = 1; } - option_name = str8_prefix(option_name, arg_signifier_position); + option_name = str8_prefix(option_name, value_signifier_position); - String8List arguments = {0}; - - // NOTE(rjf): Parse arguments. - if(has_arguments) + // rjf: parse option's values + String8List values = {0}; + if(has_values) { for(String8Node *n = node; n; n = n->next) { next = n->next; - String8 string = n->string; if(n == node) { - string = arg_portion_this_string; + string = value_portion_this_string; } - U8 splits[] = { ',' }; - String8List args_in_this_string = str8_split(arena, string, splits, ArrayCount(splits), 0); - for(String8Node *sub_arg = args_in_this_string.first; sub_arg; sub_arg = sub_arg->next) + String8List values_in_this_string = str8_split(arena, string, splits, ArrayCount(splits), 0); + for(String8Node *sub_val = values_in_this_string.first; sub_val; sub_val = sub_val->next) { - str8_list_push(arena, &arguments, sub_arg->string); + str8_list_push(arena, &values, sub_val->string); } if(!str8_match(str8_postfix(n->string, 1), str8_lit(","), 0) && - (n != node || arg_portion_this_string.size != 0)) + (n != node || value_portion_this_string.size != 0)) { break; } } } - // NOTE(rjf): Register config variable. - cmd_line_insert_opt(arena, &parsed, option_name, arguments); + // rjf: store + cmd_line_insert_opt(arena, &parsed, option_name, values); } - // NOTE(rjf): Default path, treat as a passthrough config option to be - // handled by tool-specific code. + //- rjf: default path - treat as a passthrough input else if(!str8_match(node->string, str8_lit("--"), 0) || !first_passthrough) { str8_list_push(arena, &parsed.inputs, node->string); - after_passthrough_option = 1; first_passthrough = 0; } } - // rjf: fill argc/argv + //- rjf: fill argc/argv parsed.argc = command_line.node_count; parsed.argv = push_array(arena, char *, parsed.argc); { @@ -239,12 +217,12 @@ internal B32 cmd_line_has_flag(CmdLine *cmd_line, String8 name) { CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name); - return(var != 0); + return (var != 0); } internal B32 cmd_line_has_argument(CmdLine *cmd_line, String8 name) { CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name); - return(var != 0 && var->value_strings.node_count > 0); + return (var != 0 && var->value_strings.node_count > 0); } diff --git a/src/base/base_command_line.h b/src/base/base_command_line.h index acd7f17b..3bb79cd0 100644 --- a/src/base/base_command_line.h +++ b/src/base/base_command_line.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_COMMAND_LINE_H @@ -39,9 +39,8 @@ struct CmdLine }; //////////////////////////////// -//~ NOTE(rjf): Command Line Option Parsing +//~ rjf: Command Line Parsing Functions -internal U64 cmd_line_hash_from_string(String8 string); internal CmdLineOpt** cmd_line_slot_from_string(CmdLine *cmd_line, String8 string); internal CmdLineOpt* cmd_line_opt_from_slot(CmdLineOpt **slot, String8 string); internal void cmd_line_push_opt(CmdLineOptList *list, CmdLineOpt *var); diff --git a/src/base/base_context_cracking.h b/src/base/base_context_cracking.h index 976ff941..b0a9b2b0 100644 --- a/src/base/base_context_cracking.h +++ b/src/base/base_context_cracking.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_CONTEXT_CRACKING_H @@ -159,7 +159,7 @@ #endif #if !defined(BUILD_VERSION_PATCH) -# define BUILD_VERSION_PATCH 18 +# define BUILD_VERSION_PATCH 20 #endif #define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH) diff --git a/src/base/base_core.c b/src/base/base_core.c index e5faadde..0b8c1ec8 100644 --- a/src/base/base_core.c +++ b/src/base/base_core.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -523,7 +523,7 @@ date_time_from_unix_time(U64 unix_time) date.sec = (U32)unix_time % 60; date.min = (U32)(unix_time / 60) % 60; date.hour = (U32)(unix_time / 3600) % 24; - + for(;;) { for(date.month = 0; date.month < 12; ++date.month) @@ -564,7 +564,7 @@ date_time_from_unix_time(U64 unix_time) ++date.year; } exit:; - + return date; } diff --git a/src/base/base_core.h b/src/base/base_core.h index ab7b35f3..511020f8 100644 --- a/src/base/base_core.h +++ b/src/base/base_core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_CORE_H @@ -346,7 +346,7 @@ C_LINKAGE void __asan_unpoison_memory_region(void const volatile *addr, size_t s #else # error Missing pointer-to-integer cast for this architecture. #endif -#define PtrFromInt(i) (void*)((U8*)0 + (i)) +#define PtrFromInt(i) (void*)(i) #define Compose64Bit(a,b) ((((U64)a) << 32) | ((U64)b)); #define AlignPow2(x,b) (((x) + (b) - 1)&(~((b) - 1))) @@ -487,14 +487,16 @@ typedef enum OperatingSystem } OperatingSystem; -typedef enum ImageType +typedef enum ExecutableImageKind { - Image_Null, - Image_CoffPe, - Image_Elf32, - Image_Elf64, - Image_Macho -} ImageType; + ExecutableImageKind_Null, + ExecutableImageKind_CoffPe, + ExecutableImageKind_Elf32, + ExecutableImageKind_Elf64, + ExecutableImageKind_Macho, + ExecutableImageKind_COUNT +} +ExecutableImageKind; typedef enum Arch { diff --git a/src/base/base_entry_point.c b/src/base/base_entry_point.c index 6d489e66..feaa45e1 100644 --- a/src/base/base_entry_point.c +++ b/src/base/base_entry_point.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) global U64 global_update_tick_idx = 0; @@ -17,6 +17,11 @@ main_thread_base_entry_point(int arguments_count, char **arguments) tmInitialize(sizeof(tm_data), tm_data); #endif + //- rjf: set up spall +#if PROFILE_SPALL + spall_profile = spall_init_file_ex("spall_capture", 1, 0); +#endif + //- rjf: parse command line String8List command_line_argument_strings = os_string_list_from_argcv(scratch.arena, arguments_count, arguments); CmdLine cmdline = cmd_line_from_string_list(scratch.arena, command_line_argument_strings); @@ -36,9 +41,6 @@ main_thread_base_entry_point(int arguments_count, char **arguments) #if defined(ASYNC_H) && !defined(ASYNC_INIT_MANUAL) async_init(&cmdline); #endif -#if defined(RDI_FROM_PDB_H) && !defined(P2R_INIT_MANUAL) - p2r_init(); -#endif #if defined(HASH_STORE_H) && !defined(HS_INIT_MANUAL) hs_init(); #endif diff --git a/src/base/base_entry_point.h b/src/base/base_entry_point.h index 318f8d9f..346df5df 100644 --- a/src/base/base_entry_point.h +++ b/src/base/base_entry_point.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_ENTRY_POINT_H diff --git a/src/base/base_inc.c b/src/base/base_inc.c index 299d9042..45e1fe84 100644 --- a/src/base/base_inc.c +++ b/src/base/base_inc.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/base/base_inc.h b/src/base/base_inc.h index a878cacc..e6adf0d3 100644 --- a/src/base/base_inc.h +++ b/src/base/base_inc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_INC_H diff --git a/src/base/base_log.c b/src/base/base_log.c index 1c2a05f8..3916ce1c 100644 --- a/src/base/base_log.c +++ b/src/base/base_log.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/base/base_log.h b/src/base/base_log.h index ba181ce2..1cc58ff0 100644 --- a/src/base/base_log.h +++ b/src/base/base_log.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_LOG_H @@ -48,9 +48,9 @@ internal void log_select(Log *log); internal void log_msg(LogMsgKind kind, String8 string); internal void log_msgf(LogMsgKind kind, char *fmt, ...); -#define log_info(s) log_msg(LogMsgKind_Info, (s)) +#define log_info(s) log_msg(LogMsgKind_Info, (s)) #define log_infof(...) log_msgf(LogMsgKind_Info, __VA_ARGS__) -#define log_user_error(s) log_msg(LogMsgKind_UserError, (s)) +#define log_user_error(s) log_msg(LogMsgKind_UserError, (s)) #define log_user_errorf(...) log_msgf(LogMsgKind_UserError, __VA_ARGS__) #define LogInfoNamedBlock(s) DeferLoop(log_infof("%S:\n{\n", (s)), log_infof("}\n")) diff --git a/src/base/base_markup.c b/src/base/base_markup.c index 5ad47ef5..0efbaab8 100644 --- a/src/base/base_markup.c +++ b/src/base/base_markup.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal void diff --git a/src/base/base_markup.h b/src/base/base_markup.h index 2de3aa5d..4389d9b1 100644 --- a/src/base/base_markup.h +++ b/src/base/base_markup.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_MARKUP_H diff --git a/src/base/base_math.c b/src/base/base_math.c index 7a65b45b..1a4d4293 100644 --- a/src/base/base_math.c +++ b/src/base/base_math.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/base/base_math.h b/src/base/base_math.h index eb322865..b33b139d 100644 --- a/src/base/base_math.h +++ b/src/base/base_math.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_MATH_H diff --git a/src/base/base_meta.c b/src/base/base_meta.c index 2bf14eb6..a489a39d 100644 --- a/src/base/base_meta.c +++ b/src/base/base_meta.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/base/base_meta.h b/src/base/base_meta.h index 62faafeb..18a69d9e 100644 --- a/src/base/base_meta.h +++ b/src/base/base_meta.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_META_H diff --git a/src/base/base_profile.c b/src/base/base_profile.c index 8ac6bce5..2216a282 100644 --- a/src/base/base_profile.c +++ b/src/base/base_profile.c @@ -1,2 +1,31 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) + +#if PROFILE_SPALL +internal inline void +spall_begin(char *fmt, ...) +{ + if(spall_buffer.data == 0) + { + spall_buffer.length = MB(1); + spall_buffer.data = os_reserve(spall_buffer.length); + os_commit(spall_buffer.data, spall_buffer.length); + spall_buffer_init(&spall_profile, &spall_buffer); + } + if(spall_pid == 0) + { + spall_pid = os_get_process_info()->pid; + } + if(spall_tid == 0) + { + spall_tid = os_tid(); + } + Temp scratch = scratch_begin(0, 0); + va_list args; + va_start(args, fmt); + String8 string = push_str8fv(scratch.arena, fmt, args); + spall_buffer_begin_ex(&spall_profile, &spall_buffer, string.str, string.size, os_now_microseconds(), spall_tid, spall_pid); + va_end(args); + scratch_end(scratch); +} +#endif diff --git a/src/base/base_profile.h b/src/base/base_profile.h index b39a2fc5..3a97d4f3 100644 --- a/src/base/base_profile.h +++ b/src/base/base_profile.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_PROFILE_H @@ -10,6 +10,9 @@ #if !defined(PROFILE_TELEMETRY) # define PROFILE_TELEMETRY 0 #endif +#if !defined(PROFILE_SPALL) +# define PROFILE_SPALL 0 +#endif //////////////////////////////// //~ rjf: Third Party Includes @@ -19,6 +22,8 @@ # if OS_WINDOWS # pragma comment(lib, "rad_tm_win64.lib") # endif +#elif PROFILE_SPALL +# include "spall.h" #endif //////////////////////////////// @@ -61,6 +66,34 @@ scratch_end(scratch); \ } #endif +//////////////////////////////// +//~ rjf: Spall Profile Defines + +#if PROFILE_SPALL +global U64 spall_capturing = 0; +global SpallProfile spall_profile = {0}; +thread_static SpallBuffer spall_buffer = {0}; +thread_static U32 spall_tid = 0; +thread_static U32 spall_pid = 0; +internal inline void spall_begin(char *fmt, ...); +# define ProfBegin(...) (spall_capturing ? (spall_begin(__VA_ARGS__), 0) : 0) +# define ProfBeginDynamic(...) (spall_capturing ? (spall_begin(__VA_ARGS__), 0) : 0) +# define ProfEnd(...) (spall_capturing ? (spall_buffer_end_ex(&spall_profile, &spall_buffer, os_now_microseconds(), spall_tid, spall_pid)), 0 : 0) +# define ProfTick(...) +# define ProfIsCapturing(...) (!!spall_capturing) +# define ProfBeginCapture(...) (spall_capturing = 1) +# define ProfEndCapture(...) (spall_capturing = 0, spall_flush(&spall_profile)) +# define ProfThreadName(...) +# define ProfMsg(...) +# define ProfBeginLockWait(...) +# define ProfEndLockWait(...) +# define ProfLockTake(...) +# define ProfLockDrop(...) +# define ProfColor(color) +# define ProfBeginV(...) +# define ProfNoteV(...) +#endif + //////////////////////////////// //~ rjf: Zeroify Undefined Defines diff --git a/src/base/base_strings.c b/src/base/base_strings.c index f98d6e44..70840acf 100644 --- a/src/base/base_strings.c +++ b/src/base/base_strings.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -2484,3 +2484,26 @@ str8_deserial_read_block(String8 string, U64 off, U64 size, String8 *block_out) *block_out = str8_substr(string, range); return block_out->size; } + +//////////////////////////////// +//~ rjf: Basic String Hashes + +#if !defined(XXH_IMPLEMENTATION) +# define XXH_IMPLEMENTATION +# define XXH_STATIC_LINKING_ONLY +# include "third_party/xxHash/xxhash.h" +#endif + +internal U64 +u64_hash_from_seed_str8(U64 seed, String8 string) +{ + U64 result = XXH3_64bits_withSeed(string.str, string.size, seed); + return result; +} + +internal U64 +u64_hash_from_str8(String8 string) +{ + U64 result = u64_hash_from_seed_str8(5381, string); + return result; +} diff --git a/src/base/base_strings.h b/src/base/base_strings.h index b9b155ee..7ab4679d 100644 --- a/src/base/base_strings.h +++ b/src/base/base_strings.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_STRINGS_H @@ -433,4 +433,10 @@ internal U64 str8_deserial_read_block(String8 string, U64 off, U64 size, Stri #define str8_deserial_read_array(string, off, ptr, count) str8_deserial_read((string), (off), (ptr), sizeof(*(ptr))*(count), sizeof(*(ptr))) #define str8_deserial_read_struct(string, off, ptr) str8_deserial_read_array(string, off, ptr, 1) +//////////////////////////////// +//~ rjf: Basic String Hashes + +internal U64 u64_hash_from_seed_str8(U64 seed, String8 string); +internal U64 u64_hash_from_str8(String8 string); + #endif // BASE_STRINGS_H diff --git a/src/base/base_thread_context.c b/src/base/base_thread_context.c index 1a3f84ed..43bf16f3 100644 --- a/src/base/base_thread_context.c +++ b/src/base/base_thread_context.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -10,10 +10,12 @@ C_LINKAGE thread_static TCTX* tctx_thread_local = 0; #endif internal void -tctx_init_and_equip(TCTX *tctx){ +tctx_init_and_equip(TCTX *tctx) +{ MemoryZeroStruct(tctx); Arena **arena_ptr = tctx->arenas; - for (U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1){ + for(U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1) + { *arena_ptr = arena_alloc(); } tctx_thread_local = tctx; @@ -28,37 +30,42 @@ tctx_release(void) } } -internal TCTX* -tctx_get_equipped(void){ - return(tctx_thread_local); +internal TCTX * +tctx_get_equipped(void) +{ + return tctx_thread_local; } -internal Arena* -tctx_get_scratch(Arena **conflicts, U64 count){ +internal Arena * +tctx_get_scratch(Arena **conflicts, U64 count) +{ TCTX *tctx = tctx_get_equipped(); - Arena *result = 0; Arena **arena_ptr = tctx->arenas; - for (U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1){ + for(U64 i = 0; i < ArrayCount(tctx->arenas); i += 1, arena_ptr += 1) + { Arena **conflict_ptr = conflicts; B32 has_conflict = 0; - for (U64 j = 0; j < count; j += 1, conflict_ptr += 1){ - if (*arena_ptr == *conflict_ptr){ + for(U64 j = 0; j < count; j += 1, conflict_ptr += 1) + { + if(*arena_ptr == *conflict_ptr) + { has_conflict = 1; break; } } - if (!has_conflict){ + if(!has_conflict) + { result = *arena_ptr; break; } } - - return(result); + return result; } internal void -tctx_set_thread_name(String8 string){ +tctx_set_thread_name(String8 string) +{ TCTX *tctx = tctx_get_equipped(); U64 size = ClampTop(string.size, sizeof(tctx->thread_name)); MemoryCopy(tctx->thread_name, string.str, size); @@ -66,21 +73,24 @@ tctx_set_thread_name(String8 string){ } internal String8 -tctx_get_thread_name(void){ +tctx_get_thread_name(void) +{ TCTX *tctx = tctx_get_equipped(); String8 result = str8(tctx->thread_name, tctx->thread_name_size); - return(result); + return result; } internal void -tctx_write_srcloc(char *file_name, U64 line_number){ +tctx_write_srcloc(char *file_name, U64 line_number) +{ TCTX *tctx = tctx_get_equipped(); tctx->file_name = file_name; tctx->line_number = line_number; } internal void -tctx_read_srcloc(char **file_name, U64 *line_number){ +tctx_read_srcloc(char **file_name, U64 *line_number) +{ TCTX *tctx = tctx_get_equipped(); *file_name = tctx->file_name; *line_number = tctx->line_number; diff --git a/src/base/base_thread_context.h b/src/base/base_thread_context.h index 90a396fe..44ff7ab2 100644 --- a/src/base/base_thread_context.h +++ b/src/base/base_thread_context.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef BASE_THREAD_CONTEXT_H diff --git a/src/codeview/codeview.c b/src/codeview/codeview.c index fbae1c89..742ead97 100644 --- a/src/codeview/codeview.c +++ b/src/codeview/codeview.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -14,30 +14,30 @@ cv_arch_from_coff_machine(COFF_MachineType machine) CV_Arch arch = 0; switch(machine) { - case COFF_MachineType_X64: arch = CV_Arch_X64; break; - case COFF_MachineType_X86: arch = CV_Arch_8086; break; - case COFF_MachineType_Am33: arch = CV_Arch_AM33; break; - case COFF_MachineType_Arm: NotImplemented; break; - case COFF_MachineType_Arm64: arch = CV_Arch_ARM64; break; - case COFF_MachineType_ArmNt: arch = CV_Arch_ARMNT; break; - case COFF_MachineType_Ebc: arch = CV_Arch_EBC; break; - case COFF_MachineType_Ia64: arch = CV_Arch_IA64; break; - case COFF_MachineType_M32R: arch = CV_Arch_M32R; break; - case COFF_MachineType_Mips16: arch = CV_Arch_MIPS16; break; - case COFF_MachineType_MipsFpu: NotImplemented; break; - case COFF_MachineType_MipsFpu16: NotImplemented; break; - case COFF_MachineType_PowerPc: NotImplemented; break; - case COFF_MachineType_PowerPcFp: arch = CV_Arch_PPCFP; break; - case COFF_MachineType_R4000: NotImplemented; break; - case COFF_MachineType_RiscV32: NotImplemented; break; - case COFF_MachineType_RiscV64: NotImplemented; break; - case COFF_MachineType_RiscV128: NotImplemented; break; - case COFF_MachineType_Sh3: arch = CV_Arch_SH3; break; - case COFF_MachineType_Sh3Dsp: arch = CV_Arch_SH3DSP; break; - case COFF_MachineType_Sh4: arch = CV_Arch_SH4; break; - case COFF_MachineType_Sh5: NotImplemented; break; - case COFF_MachineType_Thumb: arch = CV_Arch_THUMB; break; - case COFF_MachineType_WceMipsV2: NotImplemented; break; + case COFF_MachineType_X64: arch = CV_Arch_X64; break; + case COFF_MachineType_X86: arch = CV_Arch_8086; break; + case COFF_MachineType_Am33: arch = CV_Arch_AM33; break; + case COFF_MachineType_Arm: NotImplemented; break; + case COFF_MachineType_Arm64: arch = CV_Arch_ARM64; break; + case COFF_MachineType_ArmNt: arch = CV_Arch_ARMNT; break; + case COFF_MachineType_Ebc: arch = CV_Arch_EBC; break; + case COFF_MachineType_Ia64: arch = CV_Arch_IA64; break; + case COFF_MachineType_M32R: arch = CV_Arch_M32R; break; + case COFF_MachineType_Mips16: arch = CV_Arch_MIPS16; break; + case COFF_MachineType_MipsFpu: NotImplemented; break; + case COFF_MachineType_MipsFpu16: NotImplemented; break; + case COFF_MachineType_PowerPc: NotImplemented; break; + case COFF_MachineType_PowerPcFp: arch = CV_Arch_PPCFP; break; + case COFF_MachineType_R4000: NotImplemented; break; + case COFF_MachineType_RiscV32: NotImplemented; break; + case COFF_MachineType_RiscV64: NotImplemented; break; + case COFF_MachineType_RiscV128: NotImplemented; break; + case COFF_MachineType_Sh3: arch = CV_Arch_SH3; break; + case COFF_MachineType_Sh3Dsp: arch = CV_Arch_SH3DSP; break; + case COFF_MachineType_Sh4: arch = CV_Arch_SH4; break; + case COFF_MachineType_Sh5: NotImplemented; break; + case COFF_MachineType_Thumb: arch = CV_Arch_THUMB; break; + case COFF_MachineType_WceMipsV2: NotImplemented; break; } return arch; } @@ -47,9 +47,9 @@ cv_size_from_reg(CV_Arch arch, CV_Reg reg) { switch(arch) { - case CV_Arch_8086: return cv_size_from_reg_x86(reg); - case CV_Arch_X64 : return cv_size_from_reg_x64(reg); - default: NotImplemented; + case CV_Arch_8086: return cv_size_from_reg_x86(reg); + case CV_Arch_X64 : return cv_size_from_reg_x64(reg); + default: NotImplemented; } return 0; } @@ -59,9 +59,9 @@ cv_is_reg_sp(CV_Arch arch, CV_Reg reg) { switch(arch) { - case CV_Arch_8086: return reg == CV_Regx86_ESP; - case CV_Arch_X64: return reg == CV_Regx64_RSP; - default: NotImplemented; + case CV_Arch_8086: return reg == CV_Regx86_ESP; + case CV_Arch_X64: return reg == CV_Regx64_RSP; + default: NotImplemented; } return 0; } @@ -84,7 +84,7 @@ cv_size_from_reg_x64(CV_Reg reg) switch(reg) { #define X(NAME, CODE, RDI_NAME, BYTE_POS, BYTE_SIZE) case CV_Regx64_##NAME: return BYTE_SIZE; - CV_Reg_X64_XList(X) + CV_Reg_X64_XList(X) #undef X } return 0; @@ -111,30 +111,30 @@ cv_decode_fp_reg(CV_Arch arch, CV_EncodedFramePtrReg encoded_reg) CV_Reg fp_reg = 0; switch (arch) { - case CV_Arch_8086: - { - switch (encoded_reg) - { - case CV_EncodedFramePtrReg_None : break; - case CV_EncodedFramePtrReg_StackPtr: AssertAlways(!"TODO: not tested, this is a guess"); - fp_reg = CV_Regx86_ESP; break; - case CV_EncodedFramePtrReg_FramePtr: fp_reg = CV_Regx86_EBP; break; - case CV_EncodedFramePtrReg_BasePtr : fp_reg = CV_Regx86_EBX; break; - default: InvalidPath; - } - } break; - case CV_Arch_X64: - { - switch (encoded_reg) - { - case CV_EncodedFramePtrReg_None : break; - case CV_EncodedFramePtrReg_StackPtr: fp_reg = CV_Regx64_RSP; break; - case CV_EncodedFramePtrReg_FramePtr: fp_reg = CV_Regx64_RBP; break; - case CV_EncodedFramePtrReg_BasePtr : fp_reg = CV_Regx64_R13; break; - default: InvalidPath; - } - } break; - default: NotImplemented; + case CV_Arch_8086: + { + switch (encoded_reg) + { + case CV_EncodedFramePtrReg_None : break; + case CV_EncodedFramePtrReg_StackPtr: AssertAlways(!"TODO: not tested, this is a guess"); + fp_reg = CV_Regx86_ESP; break; + case CV_EncodedFramePtrReg_FramePtr: fp_reg = CV_Regx86_EBP; break; + case CV_EncodedFramePtrReg_BasePtr : fp_reg = CV_Regx86_EBX; break; + default: InvalidPath; + } + } break; + case CV_Arch_X64: + { + switch (encoded_reg) + { + case CV_EncodedFramePtrReg_None : break; + case CV_EncodedFramePtrReg_StackPtr: fp_reg = CV_Regx64_RSP; break; + case CV_EncodedFramePtrReg_FramePtr: fp_reg = CV_Regx64_RBP; break; + case CV_EncodedFramePtrReg_BasePtr : fp_reg = CV_Regx64_R13; break; + default: InvalidPath; + } + } break; + default: NotImplemented; } return fp_reg; } @@ -144,22 +144,22 @@ cv_map_encoded_base_pointer(CV_Arch arch, U32 encoded_frame_reg) { U32 r = 0; switch (arch) { - case CV_Arch_8086: { - switch (encoded_frame_reg) { - case 0: r = 0; break; - case 1: r = CV_AllReg_VFRAME; break; - case 2: r = CV_Regx86_EBP; break; - case 3: r = CV_Regx86_EBX; break; - } - } break; - case CV_Arch_X64: { - switch (encoded_frame_reg) { - case 0: r = 0; break; - case 1: r = CV_Regx64_RSP; break; - case 2: r = CV_Regx64_RBP; break; - case 3: r = CV_Regx64_R13; break; - } - } break; + case CV_Arch_8086: { + switch (encoded_frame_reg) { + case 0: r = 0; break; + case 1: r = CV_AllReg_VFRAME; break; + case 2: r = CV_Regx86_EBP; break; + case 3: r = CV_Regx86_EBX; break; + } + } break; + case CV_Arch_X64: { + switch (encoded_frame_reg) { + case 0: r = 0; break; + case 1: r = CV_Regx64_RSP; break; + case 2: r = CV_Regx64_RBP; break; + case 3: r = CV_Regx64_R13; break; + } + } break; default: NotImplemented; } return r; diff --git a/src/codeview/codeview.h b/src/codeview/codeview.h index 4caebc98..e70a426d 100644 --- a/src/codeview/codeview.h +++ b/src/codeview/codeview.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef CODEVIEW_H @@ -43,249 +43,249 @@ read_only global CV_TypeId cv_type_id_variadic = 0xFFFFFFFF; // X(NAME, CODE, (RDI_RegCode_X86) NAME, BYTE_POS, BYTE_SIZE) #define CV_Reg_X86_XList(X) \ - X(NONE, 0, nil, 0, 0) \ - X(AL, 1, eax, 0, 1) \ - X(CL, 2, ecx, 0, 1) \ - X(DL, 3, edx, 0, 1) \ - X(BL, 4, ebx, 0, 1) \ - X(AH, 5, eax, 1, 1) \ - X(CH, 6, ecx, 1, 1) \ - X(DH, 7, edx, 1, 1) \ - X(BH, 8, ebx, 1, 1) \ - X(AX, 9, eax, 0, 2) \ - X(CX, 10, ecx, 0, 2) \ - X(DX, 11, edx, 0, 2) \ - X(BX, 12, ebx, 0, 2) \ - X(SP, 13, esp, 0, 2) \ - X(BP, 14, ebp, 0, 2) \ - X(SI, 15, esi, 0, 2) \ - X(DI, 16, edi, 0, 2) \ - X(EAX, 17, eax, 0, 4) \ - X(ECX, 18, ecx, 0, 4) \ - X(EDX, 19, edx, 0, 4) \ - X(EBX, 20, ebx, 0, 4) \ - X(ESP, 21, esp, 0, 4) \ - X(EBP, 22, ebp, 0, 4) \ - X(ESI, 23, esi, 0, 4) \ - X(EDI, 24, edi, 0, 4) \ - X(ES, 25, es, 0, 2) \ - X(CS, 26, cs, 0, 2) \ - X(SS, 27, ss, 0, 2) \ - X(DS, 28, ds, 0, 2) \ - X(FS, 29, fs, 0, 2) \ - X(GS, 30, gs, 0, 2) \ - X(IP, 31, eip, 0, 2) \ - X(FLAGS, 32, eflags, 0, 2) \ - X(EIP, 33, eip, 0, 4) \ - X(EFLAGS, 34, eflags, 0, 4) \ - X(MM0, 146, fpr0, 0, 8) \ - X(MM1, 147, fpr1, 0, 8) \ - X(MM2, 148, fpr2, 0, 8) \ - X(MM3, 149, fpr3, 0, 8) \ - X(MM4, 150, fpr4, 0, 8) \ - X(MM5, 151, fpr5, 0, 8) \ - X(MM6, 152, fpr6, 0, 8) \ - X(MM7, 153, fpr7, 0, 8) \ - X(XMM0, 154, ymm0, 0, 16) \ - X(XMM1, 155, ymm1, 0, 16) \ - X(XMM2, 156, ymm2, 0, 16) \ - X(XMM3, 157, ymm3, 0, 16) \ - X(XMM4, 158, ymm4, 0, 16) \ - X(XMM5, 159, ymm5, 0, 16) \ - X(XMM6, 160, ymm6, 0, 16) \ - X(XMM7, 161, ymm7, 0, 16) \ - X(XMM00, 162, ymm0, 0, 4) \ - X(XMM01, 163, ymm0, 4, 4) \ - X(XMM02, 164, ymm0, 8, 4) \ - X(XMM03, 165, ymm0, 12, 4) \ - X(XMM10, 166, ymm1, 0, 4) \ - X(XMM11, 167, ymm1, 4, 4) \ - X(XMM12, 168, ymm1, 8, 4) \ - X(XMM13, 169, ymm1, 12, 4) \ - X(XMM20, 170, ymm2, 0, 4) \ - X(XMM21, 171, ymm2, 4, 4) \ - X(XMM22, 172, ymm2, 8, 4) \ - X(XMM23, 173, ymm2, 12, 4) \ - X(XMM30, 174, ymm3, 0, 4) \ - X(XMM31, 175, ymm3, 4, 4) \ - X(XMM32, 176, ymm3, 8, 4) \ - X(XMM33, 177, ymm3, 12, 4) \ - X(XMM40, 178, ymm4, 0, 4) \ - X(XMM41, 179, ymm4, 4, 4) \ - X(XMM42, 180, ymm4, 8, 4) \ - X(XMM43, 181, ymm4, 12, 4) \ - X(XMM50, 182, ymm5, 0, 4) \ - X(XMM51, 183, ymm5, 4, 4) \ - X(XMM52, 184, ymm5, 8, 4) \ - X(XMM53, 185, ymm5, 12, 4) \ - X(XMM60, 186, ymm6, 0, 4) \ - X(XMM61, 187, ymm6, 4, 4) \ - X(XMM62, 188, ymm6, 8, 4) \ - X(XMM63, 189, ymm6, 12, 4) \ - X(XMM70, 190, ymm7, 0, 4) \ - X(XMM71, 191, ymm7, 4, 4) \ - X(XMM72, 192, ymm7, 8, 4) \ - X(XMM73, 193, ymm7, 12, 4) \ - X(XMM0L, 194, ymm0, 0, 8) \ - X(XMM1L, 195, ymm1, 0, 8) \ - X(XMM2L, 196, ymm2, 0, 8) \ - X(XMM3L, 197, ymm3, 0, 8) \ - X(XMM4L, 198, ymm4, 0, 8) \ - X(XMM5L, 199, ymm5, 0, 8) \ - X(XMM6L, 200, ymm6, 0, 8) \ - X(XMM7L, 201, ymm7, 0, 8) \ - X(XMM0H, 202, ymm0, 8, 8) \ - X(XMM1H, 203, ymm1, 8, 8) \ - X(XMM2H, 204, ymm2, 8, 8) \ - X(XMM3H, 205, ymm3, 8, 8) \ - X(XMM4H, 206, ymm4, 8, 8) \ - X(XMM5H, 207, ymm5, 8, 8) \ - X(XMM6H, 208, ymm6, 8, 8) \ - X(XMM7H, 209, ymm7, 8, 8) \ - X(YMM0, 252, ymm0, 0, 32) \ - X(YMM1, 253, ymm1, 0, 32) \ - X(YMM2, 254, ymm2, 0, 32) \ - X(YMM3, 255, ymm3, 0, 32) \ - X(YMM4, 256, ymm4, 0, 32) \ - X(YMM5, 257, ymm5, 0, 32) \ - X(YMM6, 258, ymm6, 0, 32) \ - X(YMM7, 259, ymm7, 0, 32) \ - X(YMM0H, 260, ymm0, 16, 16) \ - X(YMM1H, 261, ymm1, 16, 16) \ - X(YMM2H, 262, ymm2, 16, 16) \ - X(YMM3H, 263, ymm3, 16, 16) \ - X(YMM4H, 264, ymm4, 16, 16) \ - X(YMM5H, 265, ymm5, 16, 16) \ - X(YMM6H, 266, ymm6, 16, 16) \ - X(YMM7H, 267, ymm7, 16, 16) \ - X(YMM0I0, 268, ymm0, 0, 8) \ - X(YMM0I1, 269, ymm0, 8, 8) \ - X(YMM0I2, 270, ymm0, 16, 8) \ - X(YMM0I3, 271, ymm0, 24, 8) \ - X(YMM1I0, 272, ymm1, 0, 8) \ - X(YMM1I1, 273, ymm1, 8, 8) \ - X(YMM1I2, 274, ymm1, 16, 8) \ - X(YMM1I3, 275, ymm1, 24, 8) \ - X(YMM2I0, 276, ymm2, 0, 8) \ - X(YMM2I1, 277, ymm2, 8, 8) \ - X(YMM2I2, 278, ymm2, 16, 8) \ - X(YMM2I3, 279, ymm2, 24, 8) \ - X(YMM3I0, 280, ymm3, 0, 8) \ - X(YMM3I1, 281, ymm3, 8, 8) \ - X(YMM3I2, 282, ymm3, 16, 8) \ - X(YMM3I3, 283, ymm3, 24, 8) \ - X(YMM4I0, 284, ymm4, 0, 8) \ - X(YMM4I1, 285, ymm4, 8, 8) \ - X(YMM4I2, 286, ymm4, 16, 8) \ - X(YMM4I3, 287, ymm4, 24, 8) \ - X(YMM5I0, 288, ymm5, 0, 8) \ - X(YMM5I1, 289, ymm5, 8, 8) \ - X(YMM5I2, 290, ymm5, 16, 8) \ - X(YMM5I3, 291, ymm5, 24, 8) \ - X(YMM6I0, 292, ymm6, 0, 8) \ - X(YMM6I1, 293, ymm6, 8, 8) \ - X(YMM6I2, 294, ymm6, 16, 8) \ - X(YMM6I3, 295, ymm6, 24, 8) \ - X(YMM7I0, 296, ymm7, 0, 8) \ - X(YMM7I1, 297, ymm7, 8, 8) \ - X(YMM7I2, 298, ymm7, 16, 8) \ - X(YMM7I3, 299, ymm7, 24, 8) \ - X(YMM0F0, 300, ymm0, 0, 4) \ - X(YMM0F1, 301, ymm0, 4, 4) \ - X(YMM0F2, 302, ymm0, 8, 4) \ - X(YMM0F3, 303, ymm0, 12, 4) \ - X(YMM0F4, 304, ymm0, 16, 4) \ - X(YMM0F5, 305, ymm0, 20, 4) \ - X(YMM0F6, 306, ymm0, 24, 4) \ - X(YMM0F7, 307, ymm0, 28, 4) \ - X(YMM1F0, 308, ymm1, 0, 4) \ - X(YMM1F1, 309, ymm1, 4, 4) \ - X(YMM1F2, 310, ymm1, 8, 4) \ - X(YMM1F3, 311, ymm1, 12, 4) \ - X(YMM1F4, 312, ymm1, 16, 4) \ - X(YMM1F5, 313, ymm1, 20, 4) \ - X(YMM1F6, 314, ymm1, 24, 4) \ - X(YMM1F7, 315, ymm1, 28, 4) \ - X(YMM2F0, 316, ymm2, 0, 4) \ - X(YMM2F1, 317, ymm2, 4, 4) \ - X(YMM2F2, 318, ymm2, 8, 4) \ - X(YMM2F3, 319, ymm2, 12, 4) \ - X(YMM2F4, 320, ymm2, 16, 4) \ - X(YMM2F5, 321, ymm2, 20, 4) \ - X(YMM2F6, 322, ymm2, 24, 4) \ - X(YMM2F7, 323, ymm2, 28, 4) \ - X(YMM3F0, 324, ymm3, 0, 4) \ - X(YMM3F1, 325, ymm3, 4, 4) \ - X(YMM3F2, 326, ymm3, 8, 4) \ - X(YMM3F3, 327, ymm3, 12, 4) \ - X(YMM3F4, 328, ymm3, 16, 4) \ - X(YMM3F5, 329, ymm3, 20, 4) \ - X(YMM3F6, 330, ymm3, 24, 4) \ - X(YMM3F7, 331, ymm3, 28, 4) \ - X(YMM4F0, 332, ymm4, 0, 4) \ - X(YMM4F1, 333, ymm4, 4, 4) \ - X(YMM4F2, 334, ymm4, 8, 4) \ - X(YMM4F3, 335, ymm4, 12, 4) \ - X(YMM4F4, 336, ymm4, 16, 4) \ - X(YMM4F5, 337, ymm4, 20, 4) \ - X(YMM4F6, 338, ymm4, 24, 4) \ - X(YMM4F7, 339, ymm4, 28, 4) \ - X(YMM5F0, 340, ymm5, 0, 4) \ - X(YMM5F1, 341, ymm5, 4, 4) \ - X(YMM5F2, 342, ymm5, 8, 4) \ - X(YMM5F3, 343, ymm5, 12, 4) \ - X(YMM5F4, 344, ymm5, 16, 4) \ - X(YMM5F5, 345, ymm5, 20, 4) \ - X(YMM5F6, 346, ymm5, 24, 4) \ - X(YMM5F7, 347, ymm5, 28, 4) \ - X(YMM6F0, 348, ymm6, 0, 4) \ - X(YMM6F1, 349, ymm6, 4, 4) \ - X(YMM6F2, 350, ymm6, 8, 4) \ - X(YMM6F3, 351, ymm6, 12, 4) \ - X(YMM6F4, 352, ymm6, 16, 4) \ - X(YMM6F5, 353, ymm6, 20, 4) \ - X(YMM6F6, 354, ymm6, 24, 4) \ - X(YMM6F7, 355, ymm6, 28, 4) \ - X(YMM7F0, 356, ymm7, 0, 4) \ - X(YMM7F1, 357, ymm7, 4, 4) \ - X(YMM7F2, 358, ymm7, 8, 4) \ - X(YMM7F3, 359, ymm7, 12, 4) \ - X(YMM7F4, 360, ymm7, 16, 4) \ - X(YMM7F5, 361, ymm7, 20, 4) \ - X(YMM7F6, 362, ymm7, 24, 4) \ - X(YMM7F7, 363, ymm7, 28, 4) \ - X(YMM0D0, 364, ymm0, 0, 8) \ - X(YMM0D1, 365, ymm0, 8, 8) \ - X(YMM0D2, 366, ymm0, 16, 8) \ - X(YMM0D3, 367, ymm0, 24, 8) \ - X(YMM1D0, 368, ymm1, 0, 8) \ - X(YMM1D1, 369, ymm1, 8, 8) \ - X(YMM1D2, 370, ymm1, 16, 8) \ - X(YMM1D3, 371, ymm1, 24, 8) \ - X(YMM2D0, 372, ymm2, 0, 8) \ - X(YMM2D1, 373, ymm2, 8, 8) \ - X(YMM2D2, 374, ymm2, 16, 8) \ - X(YMM2D3, 375, ymm2, 24, 8) \ - X(YMM3D0, 376, ymm3, 0, 8) \ - X(YMM3D1, 377, ymm3, 8, 8) \ - X(YMM3D2, 378, ymm3, 16, 8) \ - X(YMM3D3, 379, ymm3, 24, 8) \ - X(YMM4D0, 380, ymm4, 0, 8) \ - X(YMM4D1, 381, ymm4, 8, 8) \ - X(YMM4D2, 382, ymm4, 16, 8) \ - X(YMM4D3, 383, ymm4, 24, 8) \ - X(YMM5D0, 384, ymm5, 0, 8) \ - X(YMM5D1, 385, ymm5, 8, 8) \ - X(YMM5D2, 386, ymm5, 16, 8) \ - X(YMM5D3, 387, ymm5, 24, 8) \ - X(YMM6D0, 388, ymm6, 0, 8) \ - X(YMM6D1, 389, ymm6, 8, 8) \ - X(YMM6D2, 390, ymm6, 16, 8) \ - X(YMM6D3, 391, ymm6, 24, 8) \ - X(YMM7D0, 392, ymm7, 0, 8) \ - X(YMM7D1, 393, ymm7, 8, 8) \ - X(YMM7D2, 394, ymm7, 16, 8) \ - X(YMM7D3, 395, ymm7, 24, 8) +X(NONE, 0, nil, 0, 0) \ +X(AL, 1, eax, 0, 1) \ +X(CL, 2, ecx, 0, 1) \ +X(DL, 3, edx, 0, 1) \ +X(BL, 4, ebx, 0, 1) \ +X(AH, 5, eax, 1, 1) \ +X(CH, 6, ecx, 1, 1) \ +X(DH, 7, edx, 1, 1) \ +X(BH, 8, ebx, 1, 1) \ +X(AX, 9, eax, 0, 2) \ +X(CX, 10, ecx, 0, 2) \ +X(DX, 11, edx, 0, 2) \ +X(BX, 12, ebx, 0, 2) \ +X(SP, 13, esp, 0, 2) \ +X(BP, 14, ebp, 0, 2) \ +X(SI, 15, esi, 0, 2) \ +X(DI, 16, edi, 0, 2) \ +X(EAX, 17, eax, 0, 4) \ +X(ECX, 18, ecx, 0, 4) \ +X(EDX, 19, edx, 0, 4) \ +X(EBX, 20, ebx, 0, 4) \ +X(ESP, 21, esp, 0, 4) \ +X(EBP, 22, ebp, 0, 4) \ +X(ESI, 23, esi, 0, 4) \ +X(EDI, 24, edi, 0, 4) \ +X(ES, 25, es, 0, 2) \ +X(CS, 26, cs, 0, 2) \ +X(SS, 27, ss, 0, 2) \ +X(DS, 28, ds, 0, 2) \ +X(FS, 29, fs, 0, 2) \ +X(GS, 30, gs, 0, 2) \ +X(IP, 31, eip, 0, 2) \ +X(FLAGS, 32, eflags, 0, 2) \ +X(EIP, 33, eip, 0, 4) \ +X(EFLAGS, 34, eflags, 0, 4) \ +X(MM0, 146, fpr0, 0, 8) \ +X(MM1, 147, fpr1, 0, 8) \ +X(MM2, 148, fpr2, 0, 8) \ +X(MM3, 149, fpr3, 0, 8) \ +X(MM4, 150, fpr4, 0, 8) \ +X(MM5, 151, fpr5, 0, 8) \ +X(MM6, 152, fpr6, 0, 8) \ +X(MM7, 153, fpr7, 0, 8) \ +X(XMM0, 154, ymm0, 0, 16) \ +X(XMM1, 155, ymm1, 0, 16) \ +X(XMM2, 156, ymm2, 0, 16) \ +X(XMM3, 157, ymm3, 0, 16) \ +X(XMM4, 158, ymm4, 0, 16) \ +X(XMM5, 159, ymm5, 0, 16) \ +X(XMM6, 160, ymm6, 0, 16) \ +X(XMM7, 161, ymm7, 0, 16) \ +X(XMM00, 162, ymm0, 0, 4) \ +X(XMM01, 163, ymm0, 4, 4) \ +X(XMM02, 164, ymm0, 8, 4) \ +X(XMM03, 165, ymm0, 12, 4) \ +X(XMM10, 166, ymm1, 0, 4) \ +X(XMM11, 167, ymm1, 4, 4) \ +X(XMM12, 168, ymm1, 8, 4) \ +X(XMM13, 169, ymm1, 12, 4) \ +X(XMM20, 170, ymm2, 0, 4) \ +X(XMM21, 171, ymm2, 4, 4) \ +X(XMM22, 172, ymm2, 8, 4) \ +X(XMM23, 173, ymm2, 12, 4) \ +X(XMM30, 174, ymm3, 0, 4) \ +X(XMM31, 175, ymm3, 4, 4) \ +X(XMM32, 176, ymm3, 8, 4) \ +X(XMM33, 177, ymm3, 12, 4) \ +X(XMM40, 178, ymm4, 0, 4) \ +X(XMM41, 179, ymm4, 4, 4) \ +X(XMM42, 180, ymm4, 8, 4) \ +X(XMM43, 181, ymm4, 12, 4) \ +X(XMM50, 182, ymm5, 0, 4) \ +X(XMM51, 183, ymm5, 4, 4) \ +X(XMM52, 184, ymm5, 8, 4) \ +X(XMM53, 185, ymm5, 12, 4) \ +X(XMM60, 186, ymm6, 0, 4) \ +X(XMM61, 187, ymm6, 4, 4) \ +X(XMM62, 188, ymm6, 8, 4) \ +X(XMM63, 189, ymm6, 12, 4) \ +X(XMM70, 190, ymm7, 0, 4) \ +X(XMM71, 191, ymm7, 4, 4) \ +X(XMM72, 192, ymm7, 8, 4) \ +X(XMM73, 193, ymm7, 12, 4) \ +X(XMM0L, 194, ymm0, 0, 8) \ +X(XMM1L, 195, ymm1, 0, 8) \ +X(XMM2L, 196, ymm2, 0, 8) \ +X(XMM3L, 197, ymm3, 0, 8) \ +X(XMM4L, 198, ymm4, 0, 8) \ +X(XMM5L, 199, ymm5, 0, 8) \ +X(XMM6L, 200, ymm6, 0, 8) \ +X(XMM7L, 201, ymm7, 0, 8) \ +X(XMM0H, 202, ymm0, 8, 8) \ +X(XMM1H, 203, ymm1, 8, 8) \ +X(XMM2H, 204, ymm2, 8, 8) \ +X(XMM3H, 205, ymm3, 8, 8) \ +X(XMM4H, 206, ymm4, 8, 8) \ +X(XMM5H, 207, ymm5, 8, 8) \ +X(XMM6H, 208, ymm6, 8, 8) \ +X(XMM7H, 209, ymm7, 8, 8) \ +X(YMM0, 252, ymm0, 0, 32) \ +X(YMM1, 253, ymm1, 0, 32) \ +X(YMM2, 254, ymm2, 0, 32) \ +X(YMM3, 255, ymm3, 0, 32) \ +X(YMM4, 256, ymm4, 0, 32) \ +X(YMM5, 257, ymm5, 0, 32) \ +X(YMM6, 258, ymm6, 0, 32) \ +X(YMM7, 259, ymm7, 0, 32) \ +X(YMM0H, 260, ymm0, 16, 16) \ +X(YMM1H, 261, ymm1, 16, 16) \ +X(YMM2H, 262, ymm2, 16, 16) \ +X(YMM3H, 263, ymm3, 16, 16) \ +X(YMM4H, 264, ymm4, 16, 16) \ +X(YMM5H, 265, ymm5, 16, 16) \ +X(YMM6H, 266, ymm6, 16, 16) \ +X(YMM7H, 267, ymm7, 16, 16) \ +X(YMM0I0, 268, ymm0, 0, 8) \ +X(YMM0I1, 269, ymm0, 8, 8) \ +X(YMM0I2, 270, ymm0, 16, 8) \ +X(YMM0I3, 271, ymm0, 24, 8) \ +X(YMM1I0, 272, ymm1, 0, 8) \ +X(YMM1I1, 273, ymm1, 8, 8) \ +X(YMM1I2, 274, ymm1, 16, 8) \ +X(YMM1I3, 275, ymm1, 24, 8) \ +X(YMM2I0, 276, ymm2, 0, 8) \ +X(YMM2I1, 277, ymm2, 8, 8) \ +X(YMM2I2, 278, ymm2, 16, 8) \ +X(YMM2I3, 279, ymm2, 24, 8) \ +X(YMM3I0, 280, ymm3, 0, 8) \ +X(YMM3I1, 281, ymm3, 8, 8) \ +X(YMM3I2, 282, ymm3, 16, 8) \ +X(YMM3I3, 283, ymm3, 24, 8) \ +X(YMM4I0, 284, ymm4, 0, 8) \ +X(YMM4I1, 285, ymm4, 8, 8) \ +X(YMM4I2, 286, ymm4, 16, 8) \ +X(YMM4I3, 287, ymm4, 24, 8) \ +X(YMM5I0, 288, ymm5, 0, 8) \ +X(YMM5I1, 289, ymm5, 8, 8) \ +X(YMM5I2, 290, ymm5, 16, 8) \ +X(YMM5I3, 291, ymm5, 24, 8) \ +X(YMM6I0, 292, ymm6, 0, 8) \ +X(YMM6I1, 293, ymm6, 8, 8) \ +X(YMM6I2, 294, ymm6, 16, 8) \ +X(YMM6I3, 295, ymm6, 24, 8) \ +X(YMM7I0, 296, ymm7, 0, 8) \ +X(YMM7I1, 297, ymm7, 8, 8) \ +X(YMM7I2, 298, ymm7, 16, 8) \ +X(YMM7I3, 299, ymm7, 24, 8) \ +X(YMM0F0, 300, ymm0, 0, 4) \ +X(YMM0F1, 301, ymm0, 4, 4) \ +X(YMM0F2, 302, ymm0, 8, 4) \ +X(YMM0F3, 303, ymm0, 12, 4) \ +X(YMM0F4, 304, ymm0, 16, 4) \ +X(YMM0F5, 305, ymm0, 20, 4) \ +X(YMM0F6, 306, ymm0, 24, 4) \ +X(YMM0F7, 307, ymm0, 28, 4) \ +X(YMM1F0, 308, ymm1, 0, 4) \ +X(YMM1F1, 309, ymm1, 4, 4) \ +X(YMM1F2, 310, ymm1, 8, 4) \ +X(YMM1F3, 311, ymm1, 12, 4) \ +X(YMM1F4, 312, ymm1, 16, 4) \ +X(YMM1F5, 313, ymm1, 20, 4) \ +X(YMM1F6, 314, ymm1, 24, 4) \ +X(YMM1F7, 315, ymm1, 28, 4) \ +X(YMM2F0, 316, ymm2, 0, 4) \ +X(YMM2F1, 317, ymm2, 4, 4) \ +X(YMM2F2, 318, ymm2, 8, 4) \ +X(YMM2F3, 319, ymm2, 12, 4) \ +X(YMM2F4, 320, ymm2, 16, 4) \ +X(YMM2F5, 321, ymm2, 20, 4) \ +X(YMM2F6, 322, ymm2, 24, 4) \ +X(YMM2F7, 323, ymm2, 28, 4) \ +X(YMM3F0, 324, ymm3, 0, 4) \ +X(YMM3F1, 325, ymm3, 4, 4) \ +X(YMM3F2, 326, ymm3, 8, 4) \ +X(YMM3F3, 327, ymm3, 12, 4) \ +X(YMM3F4, 328, ymm3, 16, 4) \ +X(YMM3F5, 329, ymm3, 20, 4) \ +X(YMM3F6, 330, ymm3, 24, 4) \ +X(YMM3F7, 331, ymm3, 28, 4) \ +X(YMM4F0, 332, ymm4, 0, 4) \ +X(YMM4F1, 333, ymm4, 4, 4) \ +X(YMM4F2, 334, ymm4, 8, 4) \ +X(YMM4F3, 335, ymm4, 12, 4) \ +X(YMM4F4, 336, ymm4, 16, 4) \ +X(YMM4F5, 337, ymm4, 20, 4) \ +X(YMM4F6, 338, ymm4, 24, 4) \ +X(YMM4F7, 339, ymm4, 28, 4) \ +X(YMM5F0, 340, ymm5, 0, 4) \ +X(YMM5F1, 341, ymm5, 4, 4) \ +X(YMM5F2, 342, ymm5, 8, 4) \ +X(YMM5F3, 343, ymm5, 12, 4) \ +X(YMM5F4, 344, ymm5, 16, 4) \ +X(YMM5F5, 345, ymm5, 20, 4) \ +X(YMM5F6, 346, ymm5, 24, 4) \ +X(YMM5F7, 347, ymm5, 28, 4) \ +X(YMM6F0, 348, ymm6, 0, 4) \ +X(YMM6F1, 349, ymm6, 4, 4) \ +X(YMM6F2, 350, ymm6, 8, 4) \ +X(YMM6F3, 351, ymm6, 12, 4) \ +X(YMM6F4, 352, ymm6, 16, 4) \ +X(YMM6F5, 353, ymm6, 20, 4) \ +X(YMM6F6, 354, ymm6, 24, 4) \ +X(YMM6F7, 355, ymm6, 28, 4) \ +X(YMM7F0, 356, ymm7, 0, 4) \ +X(YMM7F1, 357, ymm7, 4, 4) \ +X(YMM7F2, 358, ymm7, 8, 4) \ +X(YMM7F3, 359, ymm7, 12, 4) \ +X(YMM7F4, 360, ymm7, 16, 4) \ +X(YMM7F5, 361, ymm7, 20, 4) \ +X(YMM7F6, 362, ymm7, 24, 4) \ +X(YMM7F7, 363, ymm7, 28, 4) \ +X(YMM0D0, 364, ymm0, 0, 8) \ +X(YMM0D1, 365, ymm0, 8, 8) \ +X(YMM0D2, 366, ymm0, 16, 8) \ +X(YMM0D3, 367, ymm0, 24, 8) \ +X(YMM1D0, 368, ymm1, 0, 8) \ +X(YMM1D1, 369, ymm1, 8, 8) \ +X(YMM1D2, 370, ymm1, 16, 8) \ +X(YMM1D3, 371, ymm1, 24, 8) \ +X(YMM2D0, 372, ymm2, 0, 8) \ +X(YMM2D1, 373, ymm2, 8, 8) \ +X(YMM2D2, 374, ymm2, 16, 8) \ +X(YMM2D3, 375, ymm2, 24, 8) \ +X(YMM3D0, 376, ymm3, 0, 8) \ +X(YMM3D1, 377, ymm3, 8, 8) \ +X(YMM3D2, 378, ymm3, 16, 8) \ +X(YMM3D3, 379, ymm3, 24, 8) \ +X(YMM4D0, 380, ymm4, 0, 8) \ +X(YMM4D1, 381, ymm4, 8, 8) \ +X(YMM4D2, 382, ymm4, 16, 8) \ +X(YMM4D3, 383, ymm4, 24, 8) \ +X(YMM5D0, 384, ymm5, 0, 8) \ +X(YMM5D1, 385, ymm5, 8, 8) \ +X(YMM5D2, 386, ymm5, 16, 8) \ +X(YMM5D3, 387, ymm5, 24, 8) \ +X(YMM6D0, 388, ymm6, 0, 8) \ +X(YMM6D1, 389, ymm6, 8, 8) \ +X(YMM6D2, 390, ymm6, 16, 8) \ +X(YMM6D3, 391, ymm6, 24, 8) \ +X(YMM7D0, 392, ymm7, 0, 8) \ +X(YMM7D1, 393, ymm7, 8, 8) \ +X(YMM7D2, 394, ymm7, 16, 8) \ +X(YMM7D3, 395, ymm7, 24, 8) typedef U16 CV_Regx86; typedef enum CV_Regx86Enum @@ -298,711 +298,711 @@ CV_Regx86Enum; // X(NAME, CODE, (RDI_RegisterCode_X64) NAME, BYTE_POS, BYTE_SIZE) #define CV_Reg_X64_XList(X) \ - X(NONE, 0, nil, 0, 0) \ - X(AL, 1, rax, 0, 1) \ - X(CL, 2, rcx, 0, 1) \ - X(DL, 3, rdx, 0, 1) \ - X(BL, 4, rbx, 0, 1) \ - X(AH, 5, rax, 1, 1) \ - X(CH, 6, rcx, 1, 1) \ - X(DH, 7, rdx, 1, 1) \ - X(BH, 8, rbx, 1, 1) \ - X(AX, 9, rax, 0, 2) \ - X(CX, 10, rcx, 0, 2) \ - X(DX, 11, rdx, 0, 2) \ - X(BX, 12, rbx, 0, 2) \ - X(SP, 13, rsp, 0, 2) \ - X(BP, 14, rbp, 0, 2) \ - X(SI, 15, rsi, 0, 2) \ - X(DI, 16, rdi, 0, 2) \ - X(EAX, 17, rax, 0, 4) \ - X(ECX, 18, rcx, 0, 4) \ - X(EDX, 19, rdx, 0, 4) \ - X(EBX, 20, rbx, 0, 4) \ - X(ESP, 21, rsp, 0, 4) \ - X(EBP, 22, rbp, 0, 4) \ - X(ESI, 23, rsi, 0, 4) \ - X(EDI, 24, rdi, 0, 4) \ - X(ES, 25, es, 0, 2) \ - X(CS, 26, cs, 0, 2) \ - X(SS, 27, ss, 0, 2) \ - X(DS, 28, ds, 0, 2) \ - X(FS, 29, fs, 0, 2) \ - X(GS, 30, gs, 0, 2) \ - X(FLAGS, 32, rflags, 0, 2) \ - X(RIP, 33, rip, 0, 8) \ - X(EFLAGS, 34, rflags, 0, 4) \ - /* TODO: possibly missing control registers in x64 definitions? */ \ - X(CR0, 80, nil, 0, 0) \ - X(CR1, 81, nil, 0, 0) \ - X(CR2, 82, nil, 0, 0) \ - X(CR3, 83, nil, 0, 0) \ - X(CR4, 84, nil, 0, 0) \ - X(CR8, 88, nil, 0, 0) \ - X(DR0, 90, dr0, 0, 4) \ - X(DR1, 91, dr1, 0, 4) \ - X(DR2, 92, dr2, 0, 4) \ - X(DR3, 93, dr3, 0, 4) \ - X(DR4, 94, dr4, 0, 4) \ - X(DR5, 95, dr5, 0, 4) \ - X(DR6, 96, dr6, 0, 4) \ - X(DR7, 97, dr7, 0, 4) \ - /* TODO: possibly missing debug registers 8-15 in x64 definitions? */ \ - X(DR8, 98, nil, 0, 0) \ - X(DR9, 99, nil, 0, 0) \ - X(DR10, 100, nil, 0, 0) \ - X(DR11, 101, nil, 0, 0) \ - X(DR12, 102, nil, 0, 0) \ - X(DR13, 103, nil, 0, 0) \ - X(DR14, 104, nil, 0, 0) \ - X(DR15, 105, nil, 0, 0) \ - /* TODO: possibly missing ~whatever these are~ in x64 definitions? */ \ - X(GDTR, 110, nil, 0, 0) \ - X(GDTL, 111, nil, 0, 0) \ - X(IDTR, 112, nil, 0, 0) \ - X(IDTL, 113, nil, 0, 0) \ - X(LDTR, 114, nil, 0, 0) \ - X(TR, 115, nil, 0, 0) \ - X(ST0, 128, st0, 0, 10) \ - X(ST1, 129, st1, 0, 10) \ - X(ST2, 130, st2, 0, 10) \ - X(ST3, 131, st3, 0, 10) \ - X(ST4, 132, st4, 0, 10) \ - X(ST5, 133, st5, 0, 10) \ - X(ST6, 134, st6, 0, 10) \ - X(ST7, 135, st7, 0, 10) \ - /* TODO: possibly missing these, or not sure how they map to our x64 definitions? */ \ - X(CTRL, 136, nil, 0, 0) \ - X(STAT, 137, nil, 0, 0) \ - X(TAG, 138, nil, 0, 0) \ - X(FPIP, 139, nil, 0, 0) \ - X(FPCS, 140, nil, 0, 0) \ - X(FPDO, 141, nil, 0, 0) \ - X(FPDS, 142, nil, 0, 0) \ - X(ISEM, 143, nil, 0, 0) \ - X(FPEIP, 144, nil, 0, 0) \ - X(FPEDO, 145, nil, 0, 0) \ - X(MM0, 146, fpr0, 0, 8) \ - X(MM1, 147, fpr1, 0, 8) \ - X(MM2, 148, fpr2, 0, 8) \ - X(MM3, 149, fpr3, 0, 8) \ - X(MM4, 150, fpr4, 0, 8) \ - X(MM5, 151, fpr5, 0, 8) \ - X(MM6, 152, fpr6, 0, 8) \ - X(MM7, 153, fpr7, 0, 8) \ - X(XMM0, 154, zmm0, 0, 16) \ - X(XMM1, 155, zmm1, 0, 16) \ - X(XMM2, 156, zmm2, 0, 16) \ - X(XMM3, 157, zmm3, 0, 16) \ - X(XMM4, 158, zmm4, 0, 16) \ - X(XMM5, 159, zmm5, 0, 16) \ - X(XMM6, 160, zmm6, 0, 16) \ - X(XMM7, 161, zmm7, 0, 16) \ - X(XMM0_0, 162, zmm0, 0, 4) \ - X(XMM0_1, 163, zmm0, 4, 4) \ - X(XMM0_2, 164, zmm0, 8, 4) \ - X(XMM0_3, 165, zmm0, 12, 4) \ - X(XMM1_0, 166, zmm1, 0, 4) \ - X(XMM1_1, 167, zmm1, 4, 4) \ - X(XMM1_2, 168, zmm1, 8, 4) \ - X(XMM1_3, 169, zmm1, 12, 4) \ - X(XMM2_0, 170, zmm2, 0, 4) \ - X(XMM2_1, 171, zmm2, 4, 4) \ - X(XMM2_2, 172, zmm2, 8, 4) \ - X(XMM2_3, 173, zmm2, 12, 4) \ - X(XMM3_0, 174, zmm3, 0, 4) \ - X(XMM3_1, 175, zmm3, 4, 4) \ - X(XMM3_2, 176, zmm3, 8, 4) \ - X(XMM3_3, 177, zmm3, 12, 4) \ - X(XMM4_0, 178, zmm4, 0, 4) \ - X(XMM4_1, 179, zmm4, 4, 4) \ - X(XMM4_2, 180, zmm4, 8, 4) \ - X(XMM4_3, 181, zmm4, 12, 4) \ - X(XMM5_0, 182, zmm5, 0, 4) \ - X(XMM5_1, 183, zmm5, 4, 4) \ - X(XMM5_2, 184, zmm5, 8, 4) \ - X(XMM5_3, 185, zmm5, 12, 4) \ - X(XMM6_0, 186, zmm6, 0, 4) \ - X(XMM6_1, 187, zmm6, 4, 4) \ - X(XMM6_2, 188, zmm6, 8, 4) \ - X(XMM6_3, 189, zmm6, 12, 4) \ - X(XMM7_0, 190, zmm7, 0, 4) \ - X(XMM7_1, 191, zmm7, 4, 4) \ - X(XMM7_2, 192, zmm7, 8, 4) \ - X(XMM7_3, 193, zmm7, 12, 4) \ - X(XMM0L, 194, zmm0, 0, 8) \ - X(XMM1L, 195, zmm1, 0, 8) \ - X(XMM2L, 196, zmm2, 0, 8) \ - X(XMM3L, 197, zmm3, 0, 8) \ - X(XMM4L, 198, zmm4, 0, 8) \ - X(XMM5L, 199, zmm5, 0, 8) \ - X(XMM6L, 200, zmm6, 0, 8) \ - X(XMM7L, 201, zmm7, 0, 8) \ - X(XMM0H, 202, zmm0, 8, 8) \ - X(XMM1H, 203, zmm1, 8, 8) \ - X(XMM2H, 204, zmm2, 8, 8) \ - X(XMM3H, 205, zmm3, 8, 8) \ - X(XMM4H, 206, zmm4, 8, 8) \ - X(XMM5H, 207, zmm5, 8, 8) \ - X(XMM6H, 208, zmm6, 8, 8) \ - X(XMM7H, 209, zmm7, 8, 8) \ - X(MXCSR, 211, mxcsr, 0, 4) \ - X(EMM0L, 220, zmm0, 0, 8) \ - X(EMM1L, 221, zmm1, 0, 8) \ - X(EMM2L, 222, zmm2, 0, 8) \ - X(EMM3L, 223, zmm3, 0, 8) \ - X(EMM4L, 224, zmm4, 0, 8) \ - X(EMM5L, 225, zmm5, 0, 8) \ - X(EMM6L, 226, zmm6, 0, 8) \ - X(EMM7L, 227, zmm7, 0, 8) \ - X(EMM0H, 228, zmm0, 8, 8) \ - X(EMM1H, 229, zmm1, 8, 8) \ - X(EMM2H, 230, zmm2, 8, 8) \ - X(EMM3H, 231, zmm3, 8, 8) \ - X(EMM4H, 232, zmm4, 8, 8) \ - X(EMM5H, 233, zmm5, 8, 8) \ - X(EMM6H, 234, zmm6, 8, 8) \ - X(EMM7H, 235, zmm7, 8, 8) \ - X(MM00, 236, fpr0, 0, 4) \ - X(MM01, 237, fpr0, 4, 4) \ - X(MM10, 238, fpr1, 0, 4) \ - X(MM11, 239, fpr1, 4, 4) \ - X(MM20, 240, fpr2, 0, 4) \ - X(MM21, 241, fpr2, 4, 4) \ - X(MM30, 242, fpr3, 0, 4) \ - X(MM31, 243, fpr3, 4, 4) \ - X(MM40, 244, fpr4, 0, 4) \ - X(MM41, 245, fpr4, 4, 4) \ - X(MM50, 246, fpr5, 0, 4) \ - X(MM51, 247, fpr5, 4, 4) \ - X(MM60, 248, fpr6, 0, 4) \ - X(MM61, 249, fpr6, 4, 4) \ - X(MM70, 250, fpr7, 0, 4) \ - X(MM71, 251, fpr7, 4, 4) \ - X(XMM8, 252, zmm8, 0, 16) \ - X(XMM9, 253, zmm9, 0, 16) \ - X(XMM10, 254, zmm10, 0, 16) \ - X(XMM11, 255, zmm11, 0, 16) \ - X(XMM12, 256, zmm12, 0, 16) \ - X(XMM13, 257, zmm13, 0, 16) \ - X(XMM14, 258, zmm14, 0, 16) \ - X(XMM15, 259, zmm15, 0, 16) \ - X(XMM8_0, 260, zmm8, 0, 16) \ - X(XMM8_1, 261, zmm8, 4, 16) \ - X(XMM8_2, 262, zmm8, 8, 16) \ - X(XMM8_3, 263, zmm8, 12, 16) \ - X(XMM9_0, 264, zmm9, 0, 4) \ - X(XMM9_1, 265, zmm9, 4, 4) \ - X(XMM9_2, 266, zmm9, 8, 4) \ - X(XMM9_3, 267, zmm9, 12, 4) \ - X(XMM10_0, 268, zmm10, 0, 4) \ - X(XMM10_1, 269, zmm10, 4, 4) \ - X(XMM10_2, 270, zmm10, 8, 4) \ - X(XMM10_3, 271, zmm10, 12, 4) \ - X(XMM11_0, 272, zmm11, 0, 4) \ - X(XMM11_1, 273, zmm11, 4, 4) \ - X(XMM11_2, 274, zmm11, 8, 4) \ - X(XMM11_3, 275, zmm11, 12, 4) \ - X(XMM12_0, 276, zmm12, 0, 4) \ - X(XMM12_1, 277, zmm12, 4, 4) \ - X(XMM12_2, 278, zmm12, 8, 4) \ - X(XMM12_3, 279, zmm12, 12, 4) \ - X(XMM13_0, 280, zmm13, 0, 4) \ - X(XMM13_1, 281, zmm13, 4, 4) \ - X(XMM13_2, 282, zmm13, 8, 4) \ - X(XMM13_3, 283, zmm13, 12, 4) \ - X(XMM14_0, 284, zmm14, 0, 4) \ - X(XMM14_1, 285, zmm14, 4, 4) \ - X(XMM14_2, 286, zmm14, 8, 4) \ - X(XMM14_3, 287, zmm14, 12, 4) \ - X(XMM15_0, 288, zmm15, 0, 4) \ - X(XMM15_1, 289, zmm15, 4, 4) \ - X(XMM15_2, 290, zmm15, 8, 4) \ - X(XMM15_3, 291, zmm15, 12, 4) \ - X(XMM8L, 292, zmm8, 0, 8) \ - X(XMM9L, 293, zmm9, 0, 8) \ - X(XMM10L, 294, zmm10, 0, 8) \ - X(XMM11L, 295, zmm11, 0, 8) \ - X(XMM12L, 296, zmm12, 0, 8) \ - X(XMM13L, 297, zmm13, 0, 8) \ - X(XMM14L, 298, zmm14, 0, 8) \ - X(XMM15L, 299, zmm15, 0, 8) \ - X(XMM8H, 300, zmm8, 8, 8) \ - X(XMM9H, 301, zmm9, 8, 8) \ - X(XMM10H, 302, zmm10, 8, 8) \ - X(XMM11H, 303, zmm11, 8, 8) \ - X(XMM12H, 304, zmm12, 8, 8) \ - X(XMM13H, 305, zmm13, 8, 8) \ - X(XMM14H, 306, zmm14, 8, 8) \ - X(XMM15H, 307, zmm15, 8, 8) \ - X(EMM8L, 308, zmm8, 0, 8) \ - X(EMM9L, 309, zmm9, 0, 8) \ - X(EMM10L, 310, zmm10, 0, 8) \ - X(EMM11L, 311, zmm11, 0, 8) \ - X(EMM12L, 312, zmm12, 0, 8) \ - X(EMM13L, 313, zmm13, 0, 8) \ - X(EMM14L, 314, zmm14, 0, 8) \ - X(EMM15L, 315, zmm15, 0, 8) \ - X(EMM8H, 316, zmm8, 8, 8) \ - X(EMM9H, 317, zmm9, 8, 8) \ - X(EMM10H, 318, zmm10, 8, 8) \ - X(EMM11H, 319, zmm11, 8, 8) \ - X(EMM12H, 320, zmm12, 8, 8) \ - X(EMM13H, 321, zmm13, 8, 8) \ - X(EMM14H, 322, zmm14, 8, 8) \ - X(EMM15H, 323, zmm15, 8, 8) \ - X(SIL, 324, rsi, 0, 1) \ - X(DIL, 325, rdi, 0, 1) \ - X(BPL, 326, rbp, 0, 1) \ - X(SPL, 327, rsp, 0, 1) \ - X(RAX, 328, rax, 0, 8) \ - X(RBX, 329, rbx, 0, 8) \ - X(RCX, 330, rcx, 0, 8) \ - X(RDX, 331, rdx, 0, 8) \ - X(RSI, 332, rsi, 0, 8) \ - X(RDI, 333, rdi, 0, 8) \ - X(RBP, 334, rbp, 0, 8) \ - X(RSP, 335, rsp, 0, 8) \ - X(R8, 336, r8, 0, 8) \ - X(R9, 337, r9, 0, 8) \ - X(R10, 338, r10, 0, 8) \ - X(R11, 339, r11, 0, 8) \ - X(R12, 340, r12, 0, 8) \ - X(R13, 341, r13, 0, 8) \ - X(R14, 342, r14, 0, 8) \ - X(R15, 343, r15, 0, 8) \ - X(R8B, 344, r8, 0, 1) \ - X(R9B, 345, r9, 0, 1) \ - X(R10B, 346, r10, 0, 1) \ - X(R11B, 347, r11, 0, 1) \ - X(R12B, 348, r12, 0, 1) \ - X(R13B, 349, r13, 0, 1) \ - X(R14B, 350, r14, 0, 1) \ - X(R15B, 351, r15, 0, 1) \ - X(R8W, 352, r8, 0, 2) \ - X(R9W, 353, r9, 0, 2) \ - X(R10W, 354, r10, 0, 2) \ - X(R11W, 355, r11, 0, 2) \ - X(R12W, 356, r12, 0, 2) \ - X(R13W, 357, r13, 0, 2) \ - X(R14W, 358, r14, 0, 2) \ - X(R15W, 359, r15, 0, 2) \ - X(R8D, 360, r8, 0, 4) \ - X(R9D, 361, r9, 0, 4) \ - X(R10D, 362, r10, 0, 4) \ - X(R11D, 363, r11, 0, 4) \ - X(R12D, 364, r12, 0, 4) \ - X(R13D, 365, r13, 0, 4) \ - X(R14D, 366, r14, 0, 4) \ - X(R15D, 367, r15, 0, 4) \ - X(YMM0, 368, zmm0, 0, 32) \ - X(YMM1, 369, zmm1, 0, 32) \ - X(YMM2, 370, zmm2, 0, 32) \ - X(YMM3, 371, zmm3, 0, 32) \ - X(YMM4, 372, zmm4, 0, 32) \ - X(YMM5, 373, zmm5, 0, 32) \ - X(YMM6, 374, zmm6, 0, 32) \ - X(YMM7, 375, zmm7, 0, 32) \ - X(YMM8, 376, zmm8, 0, 32) \ - X(YMM9, 377, zmm9, 0, 32) \ - X(YMM10, 378, zmm10, 0, 32) \ - X(YMM11, 379, zmm11, 0, 32) \ - X(YMM12, 380, zmm12, 0, 32) \ - X(YMM13, 381, zmm13, 0, 32) \ - X(YMM14, 382, zmm14, 0, 32) \ - X(YMM15, 383, zmm15, 0, 32) \ - X(YMM0H, 384, zmm0, 16, 32) \ - X(YMM1H, 385, zmm1, 16, 32) \ - X(YMM2H, 386, zmm2, 16, 32) \ - X(YMM3H, 387, zmm3, 16, 32) \ - X(YMM4H, 388, zmm4, 16, 32) \ - X(YMM5H, 389, zmm5, 16, 32) \ - X(YMM6H, 390, zmm6, 16, 32) \ - X(YMM7H, 391, zmm7, 16, 32) \ - X(YMM8H, 392, zmm8, 16, 32) \ - X(YMM9H, 393, zmm9, 16, 32) \ - X(YMM10H, 394, zmm10, 16, 32) \ - X(YMM11H, 395, zmm11, 16, 32) \ - X(YMM12H, 396, zmm12, 16, 32) \ - X(YMM13H, 397, zmm13, 16, 32) \ - X(YMM14H, 398, zmm14, 16, 32) \ - X(YMM15H, 399, zmm15, 16, 32) \ - X(XMM0IL, 400, zmm0, 0, 8) \ - X(XMM1IL, 401, zmm1, 0, 8) \ - X(XMM2IL, 402, zmm2, 0, 8) \ - X(XMM3IL, 403, zmm3, 0, 8) \ - X(XMM4IL, 404, zmm4, 0, 8) \ - X(XMM5IL, 405, zmm5, 0, 8) \ - X(XMM6IL, 406, zmm6, 0, 8) \ - X(XMM7IL, 407, zmm7, 0, 8) \ - X(XMM8IL, 408, zmm8, 0, 8) \ - X(XMM9IL, 409, zmm9, 0, 8) \ - X(XMM10IL, 410, zmm10, 0, 8) \ - X(XMM11IL, 411, zmm11, 0, 8) \ - X(XMM12IL, 412, zmm12, 0, 8) \ - X(XMM13IL, 413, zmm13, 0, 8) \ - X(XMM14IL, 414, zmm14, 0, 8) \ - X(XMM15IL, 415, zmm15, 0, 8) \ - X(XMM0IH, 416, zmm0, 8, 8) \ - X(XMM1IH, 417, zmm1, 8, 8) \ - X(XMM2IH, 418, zmm2, 8, 8) \ - X(XMM3IH, 419, zmm3, 8, 8) \ - X(XMM4IH, 420, zmm4, 8, 8) \ - X(XMM5IH, 421, zmm5, 8, 8) \ - X(XMM6IH, 422, zmm6, 8, 8) \ - X(XMM7IH, 423, zmm7, 8, 8) \ - X(XMM8IH, 424, zmm8, 8, 8) \ - X(XMM9IH, 425, zmm9, 8, 8) \ - X(XMM10IH, 426, zmm10, 8, 8) \ - X(XMM11IH, 427, zmm11, 8, 8) \ - X(XMM12IH, 428, zmm12, 8, 8) \ - X(XMM13IH, 429, zmm13, 8, 8) \ - X(XMM14IH, 430, zmm14, 8, 8) \ - X(XMM15IH, 431, zmm15, 8, 8) \ - X(YMM0I0, 432, zmm0, 0, 8) \ - X(YMM0I1, 433, zmm0, 8, 8) \ - X(YMM0I2, 434, zmm0, 16, 8) \ - X(YMM0I3, 435, zmm0, 24, 8) \ - X(YMM1I0, 436, zmm1, 0, 8) \ - X(YMM1I1, 437, zmm1, 8, 8) \ - X(YMM1I2, 438, zmm1, 16, 8) \ - X(YMM1I3, 439, zmm1, 24, 8) \ - X(YMM2I0, 440, zmm2, 0, 8) \ - X(YMM2I1, 441, zmm2, 8, 8) \ - X(YMM2I2, 442, zmm2, 16, 8) \ - X(YMM2I3, 443, zmm2, 24, 8) \ - X(YMM3I0, 444, zmm3, 0, 8) \ - X(YMM3I1, 445, zmm3, 8, 8) \ - X(YMM3I2, 446, zmm3, 16, 8) \ - X(YMM3I3, 447, zmm3, 24, 8) \ - X(YMM4I0, 448, zmm4, 0, 8) \ - X(YMM4I1, 449, zmm4, 8, 8) \ - X(YMM4I2, 450, zmm4, 16, 8) \ - X(YMM4I3, 451, zmm4, 24, 8) \ - X(YMM5I0, 452, zmm5, 0, 8) \ - X(YMM5I1, 453, zmm5, 8, 8) \ - X(YMM5I2, 454, zmm5, 16, 8) \ - X(YMM5I3, 455, zmm5, 24, 8) \ - X(YMM6I0, 456, zmm6, 0, 8) \ - X(YMM6I1, 457, zmm6, 8, 8) \ - X(YMM6I2, 458, zmm6, 16, 8) \ - X(YMM6I3, 459, zmm6, 24, 8) \ - X(YMM7I0, 460, zmm7, 0, 8) \ - X(YMM7I1, 461, zmm7, 8, 8) \ - X(YMM7I2, 462, zmm7, 16, 8) \ - X(YMM7I3, 463, zmm7, 24, 8) \ - X(YMM8I0, 464, zmm8, 0, 8) \ - X(YMM8I1, 465, zmm8, 8, 8) \ - X(YMM8I2, 466, zmm8, 16, 8) \ - X(YMM8I3, 467, zmm8, 24, 8) \ - X(YMM9I0, 468, zmm9, 0, 8) \ - X(YMM9I1, 469, zmm9, 8, 8) \ - X(YMM9I2, 470, zmm9, 16, 8) \ - X(YMM9I3, 471, zmm9, 24, 8) \ - X(YMM10I0, 472, zmm10, 0, 8) \ - X(YMM10I1, 473, zmm10, 8, 8) \ - X(YMM10I2, 474, zmm10, 16, 8) \ - X(YMM10I3, 475, zmm10, 24, 8) \ - X(YMM11I0, 476, zmm11, 0, 8) \ - X(YMM11I1, 477, zmm11, 8, 8) \ - X(YMM11I2, 478, zmm11, 16, 8) \ - X(YMM11I3, 479, zmm11, 24, 8) \ - X(YMM12I0, 480, zmm12, 0, 8) \ - X(YMM12I1, 481, zmm12, 8, 8) \ - X(YMM12I2, 482, zmm12, 16, 8) \ - X(YMM12I3, 483, zmm12, 24, 8) \ - X(YMM13I0, 484, zmm13, 0, 8) \ - X(YMM13I1, 485, zmm13, 8, 8) \ - X(YMM13I2, 486, zmm13, 16, 8) \ - X(YMM13I3, 487, zmm13, 24, 8) \ - X(YMM14I0, 488, zmm14, 0, 8) \ - X(YMM14I1, 489, zmm14, 8, 8) \ - X(YMM14I2, 490, zmm14, 16, 8) \ - X(YMM14I3, 491, zmm14, 24, 8) \ - X(YMM15I0, 492, zmm15, 0, 8) \ - X(YMM15I1, 493, zmm15, 8, 8) \ - X(YMM15I2, 494, zmm15, 16, 8) \ - X(YMM15I3, 495, zmm15, 24, 8) \ - X(YMM0F0, 496, zmm0, 0, 4) \ - X(YMM0F1, 497, zmm0, 4, 4) \ - X(YMM0F2, 498, zmm0, 8, 4) \ - X(YMM0F3, 499, zmm0, 12, 4) \ - X(YMM0F4, 500, zmm0, 16, 4) \ - X(YMM0F5, 501, zmm0, 20, 4) \ - X(YMM0F6, 502, zmm0, 24, 4) \ - X(YMM0F7, 503, zmm0, 28, 4) \ - X(YMM1F0, 504, zmm1, 0, 4) \ - X(YMM1F1, 505, zmm1, 4, 4) \ - X(YMM1F2, 506, zmm1, 8, 4) \ - X(YMM1F3, 507, zmm1, 12, 4) \ - X(YMM1F4, 508, zmm1, 16, 4) \ - X(YMM1F5, 509, zmm1, 20, 4) \ - X(YMM1F6, 510, zmm1, 24, 4) \ - X(YMM1F7, 511, zmm1, 28, 4) \ - X(YMM2F0, 512, zmm2, 0, 4) \ - X(YMM2F1, 513, zmm2, 4, 4) \ - X(YMM2F2, 514, zmm2, 8, 4) \ - X(YMM2F3, 515, zmm2, 12, 4) \ - X(YMM2F4, 516, zmm2, 16, 4) \ - X(YMM2F5, 517, zmm2, 20, 4) \ - X(YMM2F6, 518, zmm2, 24, 4) \ - X(YMM2F7, 519, zmm2, 28, 4) \ - X(YMM3F0, 520, zmm3, 0, 4) \ - X(YMM3F1, 521, zmm3, 4, 4) \ - X(YMM3F2, 522, zmm3, 8, 4) \ - X(YMM3F3, 523, zmm3, 12, 4) \ - X(YMM3F4, 524, zmm3, 16, 4) \ - X(YMM3F5, 525, zmm3, 20, 4) \ - X(YMM3F6, 526, zmm3, 24, 4) \ - X(YMM3F7, 527, zmm3, 28, 4) \ - X(YMM4F0, 528, zmm4, 0, 4) \ - X(YMM4F1, 529, zmm4, 4, 4) \ - X(YMM4F2, 530, zmm4, 8, 4) \ - X(YMM4F3, 531, zmm4, 12, 4) \ - X(YMM4F4, 532, zmm4, 16, 4) \ - X(YMM4F5, 533, zmm4, 20, 4) \ - X(YMM4F6, 534, zmm4, 24, 4) \ - X(YMM4F7, 535, zmm4, 28, 4) \ - X(YMM5F0, 536, zmm5, 0, 4) \ - X(YMM5F1, 537, zmm5, 4, 4) \ - X(YMM5F2, 538, zmm5, 8, 4) \ - X(YMM5F3, 539, zmm5, 12, 4) \ - X(YMM5F4, 540, zmm5, 16, 4) \ - X(YMM5F5, 541, zmm5, 20, 4) \ - X(YMM5F6, 542, zmm5, 24, 4) \ - X(YMM5F7, 543, zmm5, 28, 4) \ - X(YMM6F0, 544, zmm6, 0, 4) \ - X(YMM6F1, 545, zmm6, 4, 4) \ - X(YMM6F2, 546, zmm6, 8, 4) \ - X(YMM6F3, 547, zmm6, 12, 4) \ - X(YMM6F4, 548, zmm6, 16, 4) \ - X(YMM6F5, 549, zmm6, 20, 4) \ - X(YMM6F6, 550, zmm6, 24, 4) \ - X(YMM6F7, 551, zmm6, 28, 4) \ - X(YMM7F0, 552, zmm7, 0, 4) \ - X(YMM7F1, 553, zmm7, 4, 4) \ - X(YMM7F2, 554, zmm7, 8, 4) \ - X(YMM7F3, 555, zmm7, 12, 4) \ - X(YMM7F4, 556, zmm7, 16, 4) \ - X(YMM7F5, 557, zmm7, 20, 4) \ - X(YMM7F6, 558, zmm7, 24, 4) \ - X(YMM7F7, 559, zmm7, 28, 4) \ - X(YMM8F0, 560, zmm8, 0, 4) \ - X(YMM8F1, 561, zmm8, 4, 4) \ - X(YMM8F2, 562, zmm8, 8, 4) \ - X(YMM8F3, 563, zmm8, 12, 4) \ - X(YMM8F4, 564, zmm8, 16, 4) \ - X(YMM8F5, 565, zmm8, 20, 4) \ - X(YMM8F6, 566, zmm8, 24, 4) \ - X(YMM8F7, 567, zmm8, 28, 4) \ - X(YMM9F0, 568, zmm9, 0, 4) \ - X(YMM9F1, 569, zmm9, 4, 4) \ - X(YMM9F2, 570, zmm9, 8, 4) \ - X(YMM9F3, 571, zmm9, 12, 4) \ - X(YMM9F4, 572, zmm9, 16, 4) \ - X(YMM9F5, 573, zmm9, 20, 4) \ - X(YMM9F6, 574, zmm9, 24, 4) \ - X(YMM9F7, 575, zmm9, 28, 4) \ - X(YMM10F0, 576, zmm10, 0, 4) \ - X(YMM10F1, 577, zmm10, 4, 4) \ - X(YMM10F2, 578, zmm10, 8, 4) \ - X(YMM10F3, 579, zmm10, 12, 4) \ - X(YMM10F4, 580, zmm10, 16, 4) \ - X(YMM10F5, 581, zmm10, 20, 4) \ - X(YMM10F6, 582, zmm10, 24, 4) \ - X(YMM10F7, 583, zmm10, 28, 4) \ - X(YMM11F0, 584, zmm11, 0, 4) \ - X(YMM11F1, 585, zmm11, 4, 4) \ - X(YMM11F2, 586, zmm11, 8, 4) \ - X(YMM11F3, 587, zmm11, 12, 4) \ - X(YMM11F4, 588, zmm11, 16, 4) \ - X(YMM11F5, 589, zmm11, 20, 4) \ - X(YMM11F6, 590, zmm11, 24, 4) \ - X(YMM11F7, 591, zmm11, 28, 4) \ - X(YMM12F0, 592, zmm12, 0, 4) \ - X(YMM12F1, 593, zmm12, 4, 4) \ - X(YMM12F2, 594, zmm12, 8, 4) \ - X(YMM12F3, 595, zmm12, 12, 4) \ - X(YMM12F4, 596, zmm12, 16, 4) \ - X(YMM12F5, 597, zmm12, 20, 4) \ - X(YMM12F6, 598, zmm12, 24, 4) \ - X(YMM12F7, 599, zmm12, 28, 4) \ - X(YMM13F0, 600, zmm13, 0, 4) \ - X(YMM13F1, 601, zmm13, 4, 4) \ - X(YMM13F2, 602, zmm13, 8, 4) \ - X(YMM13F3, 603, zmm13, 12, 4) \ - X(YMM13F4, 604, zmm13, 16, 4) \ - X(YMM13F5, 605, zmm13, 20, 4) \ - X(YMM13F6, 606, zmm13, 24, 4) \ - X(YMM13F7, 607, zmm13, 28, 4) \ - X(YMM14F0, 608, zmm14, 0, 4) \ - X(YMM14F1, 609, zmm14, 4, 4) \ - X(YMM14F2, 610, zmm14, 8, 4) \ - X(YMM14F3, 611, zmm14, 12, 4) \ - X(YMM14F4, 612, zmm14, 16, 4) \ - X(YMM14F5, 613, zmm14, 20, 4) \ - X(YMM14F6, 614, zmm14, 24, 4) \ - X(YMM14F7, 615, zmm14, 28, 4) \ - X(YMM15F0, 616, zmm15, 0, 4) \ - X(YMM15F1, 617, zmm15, 4, 4) \ - X(YMM15F2, 618, zmm15, 8, 4) \ - X(YMM15F3, 619, zmm15, 12, 4) \ - X(YMM15F4, 620, zmm15, 16, 4) \ - X(YMM15F5, 621, zmm15, 20, 4) \ - X(YMM15F6, 622, zmm15, 24, 4) \ - X(YMM15F7, 623, zmm15, 28, 4) \ - X(YMM0D0, 624, zmm0, 0, 8) \ - X(YMM0D1, 625, zmm0, 8, 8) \ - X(YMM0D2, 626, zmm0, 16, 8) \ - X(YMM0D3, 627, zmm0, 24, 8) \ - X(YMM1D0, 628, zmm1, 0, 8) \ - X(YMM1D1, 629, zmm1, 8, 8) \ - X(YMM1D2, 630, zmm1, 16, 8) \ - X(YMM1D3, 631, zmm1, 24, 8) \ - X(YMM2D0, 632, zmm2, 0, 8) \ - X(YMM2D1, 633, zmm2, 8, 8) \ - X(YMM2D2, 634, zmm2, 16, 8) \ - X(YMM2D3, 635, zmm2, 24, 8) \ - X(YMM3D0, 636, zmm3, 0, 8) \ - X(YMM3D1, 637, zmm3, 8, 8) \ - X(YMM3D2, 638, zmm3, 16, 8) \ - X(YMM3D3, 639, zmm3, 24, 8) \ - X(YMM4D0, 640, zmm4, 0, 8) \ - X(YMM4D1, 641, zmm4, 8, 8) \ - X(YMM4D2, 642, zmm4, 16, 8) \ - X(YMM4D3, 643, zmm4, 24, 8) \ - X(YMM5D0, 644, zmm5, 0, 8) \ - X(YMM5D1, 645, zmm5, 8, 8) \ - X(YMM5D2, 646, zmm5, 16, 8) \ - X(YMM5D3, 647, zmm5, 24, 8) \ - X(YMM6D0, 648, zmm6, 0, 8) \ - X(YMM6D1, 649, zmm6, 8, 8) \ - X(YMM6D2, 650, zmm6, 16, 8) \ - X(YMM6D3, 651, zmm6, 24, 8) \ - X(YMM7D0, 652, zmm7, 0, 8) \ - X(YMM7D1, 653, zmm7, 8, 8) \ - X(YMM7D2, 654, zmm7, 16, 8) \ - X(YMM7D3, 655, zmm7, 24, 8) \ - X(YMM8D0, 656, zmm8, 0, 8) \ - X(YMM8D1, 657, zmm8, 8, 8) \ - X(YMM8D2, 658, zmm8, 16, 8) \ - X(YMM8D3, 659, zmm8, 24, 8) \ - X(YMM9D0, 660, zmm9, 0, 8) \ - X(YMM9D1, 661, zmm9, 8, 8) \ - X(YMM9D2, 662, zmm9, 16, 8) \ - X(YMM9D3, 663, zmm9, 24, 8) \ - X(YMM10D0, 664, zmm10, 0, 8) \ - X(YMM10D1, 665, zmm10, 8, 8) \ - X(YMM10D2, 666, zmm10, 16, 8) \ - X(YMM10D3, 667, zmm10, 24, 8) \ - X(YMM11D0, 668, zmm11, 0, 8) \ - X(YMM11D1, 669, zmm11, 8, 8) \ - X(YMM11D2, 670, zmm11, 16, 8) \ - X(YMM11D3, 671, zmm11, 24, 8) \ - X(YMM12D0, 672, zmm12, 0, 8) \ - X(YMM12D1, 673, zmm12, 8, 8) \ - X(YMM12D2, 674, zmm12, 16, 8) \ - X(YMM12D3, 675, zmm12, 24, 8) \ - X(YMM13D0, 676, zmm13, 0, 8) \ - X(YMM13D1, 677, zmm13, 8, 8) \ - X(YMM13D2, 678, zmm13, 16, 8) \ - X(YMM13D3, 679, zmm13, 24, 8) \ - X(YMM14D0, 680, zmm14, 0, 8) \ - X(YMM14D1, 681, zmm14, 8, 8) \ - X(YMM14D2, 682, zmm14, 16, 8) \ - X(YMM14D3, 683, zmm14, 24, 8) \ - X(YMM15D0, 684, zmm15, 0, 8) \ - X(YMM15D1, 685, zmm15, 8, 8) \ - X(YMM15D2, 686, zmm15, 16, 8) \ - X(YMM15D3, 687, zmm15, 24, 8) \ - X(XMM16, 694, zmm16, 0, 16) \ - X(XMM17, 695, zmm17, 0, 16) \ - X(XMM18, 696, zmm18, 0, 16) \ - X(XMM19, 697, zmm19, 0, 16) \ - X(XMM20, 698, zmm20, 0, 16) \ - X(XMM21, 699, zmm21, 0, 16) \ - X(XMM22, 700, zmm22, 0, 16) \ - X(XMM23, 701, zmm23, 0, 16) \ - X(XMM24, 702, zmm24, 0, 16) \ - X(XMM25, 703, zmm25, 0, 16) \ - X(XMM26, 704, zmm26, 0, 16) \ - X(XMM27, 705, zmm27, 0, 16) \ - X(XMM28, 706, zmm28, 0, 16) \ - X(XMM29, 707, zmm29, 0, 16) \ - X(XMM30, 708, zmm30, 0, 16) \ - X(XMM31, 709, zmm31, 0, 16) \ - X(YMM16, 710, zmm16, 0, 32) \ - X(YMM17, 711, zmm17, 0, 32) \ - X(YMM18, 712, zmm18, 0, 32) \ - X(YMM19, 713, zmm19, 0, 32) \ - X(YMM20, 714, zmm20, 0, 32) \ - X(YMM21, 715, zmm21, 0, 32) \ - X(YMM22, 716, zmm22, 0, 32) \ - X(YMM23, 717, zmm23, 0, 32) \ - X(YMM24, 718, zmm24, 0, 32) \ - X(YMM25, 719, zmm25, 0, 32) \ - X(YMM26, 720, zmm26, 0, 32) \ - X(YMM27, 721, zmm27, 0, 32) \ - X(YMM28, 722, zmm28, 0, 32) \ - X(YMM29, 723, zmm29, 0, 32) \ - X(YMM30, 724, zmm30, 0, 32) \ - X(YMM31, 725, zmm31, 0, 32) \ - X(ZMM0, 726, zmm0, 0, 64) \ - X(ZMM1, 727, zmm1, 0, 64) \ - X(ZMM2, 728, zmm2, 0, 64) \ - X(ZMM3, 729, zmm3, 0, 64) \ - X(ZMM4, 730, zmm4, 0, 64) \ - X(ZMM5, 731, zmm5, 0, 64) \ - X(ZMM6, 732, zmm6, 0, 64) \ - X(ZMM7, 733, zmm7, 0, 64) \ - X(ZMM8, 734, zmm8, 0, 64) \ - X(ZMM9, 735, zmm9, 0, 64) \ - X(ZMM10, 736, zmm10, 0, 64) \ - X(ZMM11, 737, zmm11, 0, 64) \ - X(ZMM12, 738, zmm12, 0, 64) \ - X(ZMM13, 739, zmm13, 0, 64) \ - X(ZMM14, 740, zmm14, 0, 64) \ - X(ZMM15, 741, zmm15, 0, 64) \ - X(ZMM16, 742, zmm16, 0, 64) \ - X(ZMM17, 743, zmm17, 0, 64) \ - X(ZMM18, 744, zmm18, 0, 64) \ - X(ZMM19, 745, zmm19, 0, 64) \ - X(ZMM20, 746, zmm20, 0, 64) \ - X(ZMM21, 747, zmm21, 0, 64) \ - X(ZMM22, 748, zmm22, 0, 64) \ - X(ZMM23, 749, zmm23, 0, 64) \ - X(ZMM24, 750, zmm24, 0, 64) \ - X(ZMM25, 751, zmm25, 0, 64) \ - X(ZMM26, 752, zmm26, 0, 64) \ - X(ZMM27, 753, zmm27, 0, 64) \ - X(ZMM28, 754, zmm28, 0, 64) \ - X(ZMM29, 755, zmm29, 0, 64) \ - X(ZMM30, 756, zmm30, 0, 64) \ - X(ZMM31, 757, zmm31, 0, 64) \ - X(K0, 758, k0, 0, 8) \ - X(K1, 759, k1, 0, 8) \ - X(K2, 760, k2, 0, 8) \ - X(K3, 761, k3, 0, 8) \ - X(K4, 762, k4, 0, 8) \ - X(K5, 763, k5, 0, 8) \ - X(K6, 764, k6, 0, 8) \ - X(K7, 765, k7, 0, 8) \ - X(ZMM0H, 766, zmm0, 32, 32) \ - X(ZMM1H, 767, zmm1, 32, 32) \ - X(ZMM2H, 768, zmm2, 32, 32) \ - X(ZMM3H, 769, zmm3, 32, 32) \ - X(ZMM4H, 770, zmm4, 32, 32) \ - X(ZMM5H, 771, zmm5, 32, 32) \ - X(ZMM6H, 772, zmm6, 32, 32) \ - X(ZMM7H, 773, zmm7, 32, 32) \ - X(ZMM8H, 774, zmm8, 32, 32) \ - X(ZMM9H, 775, zmm9, 32, 32) \ - X(ZMM10H, 776, zmm10, 32, 32) \ - X(ZMM11H, 777, zmm11, 32, 32) \ - X(ZMM12H, 778, zmm12, 32, 32) \ - X(ZMM13H, 779, zmm13, 32, 32) \ - X(ZMM14H, 780, zmm14, 32, 32) \ - X(ZMM15H, 781, zmm15, 32, 32) +X(NONE, 0, nil, 0, 0) \ +X(AL, 1, rax, 0, 1) \ +X(CL, 2, rcx, 0, 1) \ +X(DL, 3, rdx, 0, 1) \ +X(BL, 4, rbx, 0, 1) \ +X(AH, 5, rax, 1, 1) \ +X(CH, 6, rcx, 1, 1) \ +X(DH, 7, rdx, 1, 1) \ +X(BH, 8, rbx, 1, 1) \ +X(AX, 9, rax, 0, 2) \ +X(CX, 10, rcx, 0, 2) \ +X(DX, 11, rdx, 0, 2) \ +X(BX, 12, rbx, 0, 2) \ +X(SP, 13, rsp, 0, 2) \ +X(BP, 14, rbp, 0, 2) \ +X(SI, 15, rsi, 0, 2) \ +X(DI, 16, rdi, 0, 2) \ +X(EAX, 17, rax, 0, 4) \ +X(ECX, 18, rcx, 0, 4) \ +X(EDX, 19, rdx, 0, 4) \ +X(EBX, 20, rbx, 0, 4) \ +X(ESP, 21, rsp, 0, 4) \ +X(EBP, 22, rbp, 0, 4) \ +X(ESI, 23, rsi, 0, 4) \ +X(EDI, 24, rdi, 0, 4) \ +X(ES, 25, es, 0, 2) \ +X(CS, 26, cs, 0, 2) \ +X(SS, 27, ss, 0, 2) \ +X(DS, 28, ds, 0, 2) \ +X(FS, 29, fs, 0, 2) \ +X(GS, 30, gs, 0, 2) \ +X(FLAGS, 32, rflags, 0, 2) \ +X(RIP, 33, rip, 0, 8) \ +X(EFLAGS, 34, rflags, 0, 4) \ +/* TODO: possibly missing control registers in x64 definitions? */ \ +X(CR0, 80, nil, 0, 0) \ +X(CR1, 81, nil, 0, 0) \ +X(CR2, 82, nil, 0, 0) \ +X(CR3, 83, nil, 0, 0) \ +X(CR4, 84, nil, 0, 0) \ +X(CR8, 88, nil, 0, 0) \ +X(DR0, 90, dr0, 0, 4) \ +X(DR1, 91, dr1, 0, 4) \ +X(DR2, 92, dr2, 0, 4) \ +X(DR3, 93, dr3, 0, 4) \ +X(DR4, 94, dr4, 0, 4) \ +X(DR5, 95, dr5, 0, 4) \ +X(DR6, 96, dr6, 0, 4) \ +X(DR7, 97, dr7, 0, 4) \ +/* TODO: possibly missing debug registers 8-15 in x64 definitions? */ \ +X(DR8, 98, nil, 0, 0) \ +X(DR9, 99, nil, 0, 0) \ +X(DR10, 100, nil, 0, 0) \ +X(DR11, 101, nil, 0, 0) \ +X(DR12, 102, nil, 0, 0) \ +X(DR13, 103, nil, 0, 0) \ +X(DR14, 104, nil, 0, 0) \ +X(DR15, 105, nil, 0, 0) \ +/* TODO: possibly missing ~whatever these are~ in x64 definitions? */ \ +X(GDTR, 110, nil, 0, 0) \ +X(GDTL, 111, nil, 0, 0) \ +X(IDTR, 112, nil, 0, 0) \ +X(IDTL, 113, nil, 0, 0) \ +X(LDTR, 114, nil, 0, 0) \ +X(TR, 115, nil, 0, 0) \ +X(ST0, 128, st0, 0, 10) \ +X(ST1, 129, st1, 0, 10) \ +X(ST2, 130, st2, 0, 10) \ +X(ST3, 131, st3, 0, 10) \ +X(ST4, 132, st4, 0, 10) \ +X(ST5, 133, st5, 0, 10) \ +X(ST6, 134, st6, 0, 10) \ +X(ST7, 135, st7, 0, 10) \ +/* TODO: possibly missing these, or not sure how they map to our x64 definitions? */ \ +X(CTRL, 136, nil, 0, 0) \ +X(STAT, 137, nil, 0, 0) \ +X(TAG, 138, nil, 0, 0) \ +X(FPIP, 139, nil, 0, 0) \ +X(FPCS, 140, nil, 0, 0) \ +X(FPDO, 141, nil, 0, 0) \ +X(FPDS, 142, nil, 0, 0) \ +X(ISEM, 143, nil, 0, 0) \ +X(FPEIP, 144, nil, 0, 0) \ +X(FPEDO, 145, nil, 0, 0) \ +X(MM0, 146, fpr0, 0, 8) \ +X(MM1, 147, fpr1, 0, 8) \ +X(MM2, 148, fpr2, 0, 8) \ +X(MM3, 149, fpr3, 0, 8) \ +X(MM4, 150, fpr4, 0, 8) \ +X(MM5, 151, fpr5, 0, 8) \ +X(MM6, 152, fpr6, 0, 8) \ +X(MM7, 153, fpr7, 0, 8) \ +X(XMM0, 154, zmm0, 0, 16) \ +X(XMM1, 155, zmm1, 0, 16) \ +X(XMM2, 156, zmm2, 0, 16) \ +X(XMM3, 157, zmm3, 0, 16) \ +X(XMM4, 158, zmm4, 0, 16) \ +X(XMM5, 159, zmm5, 0, 16) \ +X(XMM6, 160, zmm6, 0, 16) \ +X(XMM7, 161, zmm7, 0, 16) \ +X(XMM0_0, 162, zmm0, 0, 4) \ +X(XMM0_1, 163, zmm0, 4, 4) \ +X(XMM0_2, 164, zmm0, 8, 4) \ +X(XMM0_3, 165, zmm0, 12, 4) \ +X(XMM1_0, 166, zmm1, 0, 4) \ +X(XMM1_1, 167, zmm1, 4, 4) \ +X(XMM1_2, 168, zmm1, 8, 4) \ +X(XMM1_3, 169, zmm1, 12, 4) \ +X(XMM2_0, 170, zmm2, 0, 4) \ +X(XMM2_1, 171, zmm2, 4, 4) \ +X(XMM2_2, 172, zmm2, 8, 4) \ +X(XMM2_3, 173, zmm2, 12, 4) \ +X(XMM3_0, 174, zmm3, 0, 4) \ +X(XMM3_1, 175, zmm3, 4, 4) \ +X(XMM3_2, 176, zmm3, 8, 4) \ +X(XMM3_3, 177, zmm3, 12, 4) \ +X(XMM4_0, 178, zmm4, 0, 4) \ +X(XMM4_1, 179, zmm4, 4, 4) \ +X(XMM4_2, 180, zmm4, 8, 4) \ +X(XMM4_3, 181, zmm4, 12, 4) \ +X(XMM5_0, 182, zmm5, 0, 4) \ +X(XMM5_1, 183, zmm5, 4, 4) \ +X(XMM5_2, 184, zmm5, 8, 4) \ +X(XMM5_3, 185, zmm5, 12, 4) \ +X(XMM6_0, 186, zmm6, 0, 4) \ +X(XMM6_1, 187, zmm6, 4, 4) \ +X(XMM6_2, 188, zmm6, 8, 4) \ +X(XMM6_3, 189, zmm6, 12, 4) \ +X(XMM7_0, 190, zmm7, 0, 4) \ +X(XMM7_1, 191, zmm7, 4, 4) \ +X(XMM7_2, 192, zmm7, 8, 4) \ +X(XMM7_3, 193, zmm7, 12, 4) \ +X(XMM0L, 194, zmm0, 0, 8) \ +X(XMM1L, 195, zmm1, 0, 8) \ +X(XMM2L, 196, zmm2, 0, 8) \ +X(XMM3L, 197, zmm3, 0, 8) \ +X(XMM4L, 198, zmm4, 0, 8) \ +X(XMM5L, 199, zmm5, 0, 8) \ +X(XMM6L, 200, zmm6, 0, 8) \ +X(XMM7L, 201, zmm7, 0, 8) \ +X(XMM0H, 202, zmm0, 8, 8) \ +X(XMM1H, 203, zmm1, 8, 8) \ +X(XMM2H, 204, zmm2, 8, 8) \ +X(XMM3H, 205, zmm3, 8, 8) \ +X(XMM4H, 206, zmm4, 8, 8) \ +X(XMM5H, 207, zmm5, 8, 8) \ +X(XMM6H, 208, zmm6, 8, 8) \ +X(XMM7H, 209, zmm7, 8, 8) \ +X(MXCSR, 211, mxcsr, 0, 4) \ +X(EMM0L, 220, zmm0, 0, 8) \ +X(EMM1L, 221, zmm1, 0, 8) \ +X(EMM2L, 222, zmm2, 0, 8) \ +X(EMM3L, 223, zmm3, 0, 8) \ +X(EMM4L, 224, zmm4, 0, 8) \ +X(EMM5L, 225, zmm5, 0, 8) \ +X(EMM6L, 226, zmm6, 0, 8) \ +X(EMM7L, 227, zmm7, 0, 8) \ +X(EMM0H, 228, zmm0, 8, 8) \ +X(EMM1H, 229, zmm1, 8, 8) \ +X(EMM2H, 230, zmm2, 8, 8) \ +X(EMM3H, 231, zmm3, 8, 8) \ +X(EMM4H, 232, zmm4, 8, 8) \ +X(EMM5H, 233, zmm5, 8, 8) \ +X(EMM6H, 234, zmm6, 8, 8) \ +X(EMM7H, 235, zmm7, 8, 8) \ +X(MM00, 236, fpr0, 0, 4) \ +X(MM01, 237, fpr0, 4, 4) \ +X(MM10, 238, fpr1, 0, 4) \ +X(MM11, 239, fpr1, 4, 4) \ +X(MM20, 240, fpr2, 0, 4) \ +X(MM21, 241, fpr2, 4, 4) \ +X(MM30, 242, fpr3, 0, 4) \ +X(MM31, 243, fpr3, 4, 4) \ +X(MM40, 244, fpr4, 0, 4) \ +X(MM41, 245, fpr4, 4, 4) \ +X(MM50, 246, fpr5, 0, 4) \ +X(MM51, 247, fpr5, 4, 4) \ +X(MM60, 248, fpr6, 0, 4) \ +X(MM61, 249, fpr6, 4, 4) \ +X(MM70, 250, fpr7, 0, 4) \ +X(MM71, 251, fpr7, 4, 4) \ +X(XMM8, 252, zmm8, 0, 16) \ +X(XMM9, 253, zmm9, 0, 16) \ +X(XMM10, 254, zmm10, 0, 16) \ +X(XMM11, 255, zmm11, 0, 16) \ +X(XMM12, 256, zmm12, 0, 16) \ +X(XMM13, 257, zmm13, 0, 16) \ +X(XMM14, 258, zmm14, 0, 16) \ +X(XMM15, 259, zmm15, 0, 16) \ +X(XMM8_0, 260, zmm8, 0, 16) \ +X(XMM8_1, 261, zmm8, 4, 16) \ +X(XMM8_2, 262, zmm8, 8, 16) \ +X(XMM8_3, 263, zmm8, 12, 16) \ +X(XMM9_0, 264, zmm9, 0, 4) \ +X(XMM9_1, 265, zmm9, 4, 4) \ +X(XMM9_2, 266, zmm9, 8, 4) \ +X(XMM9_3, 267, zmm9, 12, 4) \ +X(XMM10_0, 268, zmm10, 0, 4) \ +X(XMM10_1, 269, zmm10, 4, 4) \ +X(XMM10_2, 270, zmm10, 8, 4) \ +X(XMM10_3, 271, zmm10, 12, 4) \ +X(XMM11_0, 272, zmm11, 0, 4) \ +X(XMM11_1, 273, zmm11, 4, 4) \ +X(XMM11_2, 274, zmm11, 8, 4) \ +X(XMM11_3, 275, zmm11, 12, 4) \ +X(XMM12_0, 276, zmm12, 0, 4) \ +X(XMM12_1, 277, zmm12, 4, 4) \ +X(XMM12_2, 278, zmm12, 8, 4) \ +X(XMM12_3, 279, zmm12, 12, 4) \ +X(XMM13_0, 280, zmm13, 0, 4) \ +X(XMM13_1, 281, zmm13, 4, 4) \ +X(XMM13_2, 282, zmm13, 8, 4) \ +X(XMM13_3, 283, zmm13, 12, 4) \ +X(XMM14_0, 284, zmm14, 0, 4) \ +X(XMM14_1, 285, zmm14, 4, 4) \ +X(XMM14_2, 286, zmm14, 8, 4) \ +X(XMM14_3, 287, zmm14, 12, 4) \ +X(XMM15_0, 288, zmm15, 0, 4) \ +X(XMM15_1, 289, zmm15, 4, 4) \ +X(XMM15_2, 290, zmm15, 8, 4) \ +X(XMM15_3, 291, zmm15, 12, 4) \ +X(XMM8L, 292, zmm8, 0, 8) \ +X(XMM9L, 293, zmm9, 0, 8) \ +X(XMM10L, 294, zmm10, 0, 8) \ +X(XMM11L, 295, zmm11, 0, 8) \ +X(XMM12L, 296, zmm12, 0, 8) \ +X(XMM13L, 297, zmm13, 0, 8) \ +X(XMM14L, 298, zmm14, 0, 8) \ +X(XMM15L, 299, zmm15, 0, 8) \ +X(XMM8H, 300, zmm8, 8, 8) \ +X(XMM9H, 301, zmm9, 8, 8) \ +X(XMM10H, 302, zmm10, 8, 8) \ +X(XMM11H, 303, zmm11, 8, 8) \ +X(XMM12H, 304, zmm12, 8, 8) \ +X(XMM13H, 305, zmm13, 8, 8) \ +X(XMM14H, 306, zmm14, 8, 8) \ +X(XMM15H, 307, zmm15, 8, 8) \ +X(EMM8L, 308, zmm8, 0, 8) \ +X(EMM9L, 309, zmm9, 0, 8) \ +X(EMM10L, 310, zmm10, 0, 8) \ +X(EMM11L, 311, zmm11, 0, 8) \ +X(EMM12L, 312, zmm12, 0, 8) \ +X(EMM13L, 313, zmm13, 0, 8) \ +X(EMM14L, 314, zmm14, 0, 8) \ +X(EMM15L, 315, zmm15, 0, 8) \ +X(EMM8H, 316, zmm8, 8, 8) \ +X(EMM9H, 317, zmm9, 8, 8) \ +X(EMM10H, 318, zmm10, 8, 8) \ +X(EMM11H, 319, zmm11, 8, 8) \ +X(EMM12H, 320, zmm12, 8, 8) \ +X(EMM13H, 321, zmm13, 8, 8) \ +X(EMM14H, 322, zmm14, 8, 8) \ +X(EMM15H, 323, zmm15, 8, 8) \ +X(SIL, 324, rsi, 0, 1) \ +X(DIL, 325, rdi, 0, 1) \ +X(BPL, 326, rbp, 0, 1) \ +X(SPL, 327, rsp, 0, 1) \ +X(RAX, 328, rax, 0, 8) \ +X(RBX, 329, rbx, 0, 8) \ +X(RCX, 330, rcx, 0, 8) \ +X(RDX, 331, rdx, 0, 8) \ +X(RSI, 332, rsi, 0, 8) \ +X(RDI, 333, rdi, 0, 8) \ +X(RBP, 334, rbp, 0, 8) \ +X(RSP, 335, rsp, 0, 8) \ +X(R8, 336, r8, 0, 8) \ +X(R9, 337, r9, 0, 8) \ +X(R10, 338, r10, 0, 8) \ +X(R11, 339, r11, 0, 8) \ +X(R12, 340, r12, 0, 8) \ +X(R13, 341, r13, 0, 8) \ +X(R14, 342, r14, 0, 8) \ +X(R15, 343, r15, 0, 8) \ +X(R8B, 344, r8, 0, 1) \ +X(R9B, 345, r9, 0, 1) \ +X(R10B, 346, r10, 0, 1) \ +X(R11B, 347, r11, 0, 1) \ +X(R12B, 348, r12, 0, 1) \ +X(R13B, 349, r13, 0, 1) \ +X(R14B, 350, r14, 0, 1) \ +X(R15B, 351, r15, 0, 1) \ +X(R8W, 352, r8, 0, 2) \ +X(R9W, 353, r9, 0, 2) \ +X(R10W, 354, r10, 0, 2) \ +X(R11W, 355, r11, 0, 2) \ +X(R12W, 356, r12, 0, 2) \ +X(R13W, 357, r13, 0, 2) \ +X(R14W, 358, r14, 0, 2) \ +X(R15W, 359, r15, 0, 2) \ +X(R8D, 360, r8, 0, 4) \ +X(R9D, 361, r9, 0, 4) \ +X(R10D, 362, r10, 0, 4) \ +X(R11D, 363, r11, 0, 4) \ +X(R12D, 364, r12, 0, 4) \ +X(R13D, 365, r13, 0, 4) \ +X(R14D, 366, r14, 0, 4) \ +X(R15D, 367, r15, 0, 4) \ +X(YMM0, 368, zmm0, 0, 32) \ +X(YMM1, 369, zmm1, 0, 32) \ +X(YMM2, 370, zmm2, 0, 32) \ +X(YMM3, 371, zmm3, 0, 32) \ +X(YMM4, 372, zmm4, 0, 32) \ +X(YMM5, 373, zmm5, 0, 32) \ +X(YMM6, 374, zmm6, 0, 32) \ +X(YMM7, 375, zmm7, 0, 32) \ +X(YMM8, 376, zmm8, 0, 32) \ +X(YMM9, 377, zmm9, 0, 32) \ +X(YMM10, 378, zmm10, 0, 32) \ +X(YMM11, 379, zmm11, 0, 32) \ +X(YMM12, 380, zmm12, 0, 32) \ +X(YMM13, 381, zmm13, 0, 32) \ +X(YMM14, 382, zmm14, 0, 32) \ +X(YMM15, 383, zmm15, 0, 32) \ +X(YMM0H, 384, zmm0, 16, 32) \ +X(YMM1H, 385, zmm1, 16, 32) \ +X(YMM2H, 386, zmm2, 16, 32) \ +X(YMM3H, 387, zmm3, 16, 32) \ +X(YMM4H, 388, zmm4, 16, 32) \ +X(YMM5H, 389, zmm5, 16, 32) \ +X(YMM6H, 390, zmm6, 16, 32) \ +X(YMM7H, 391, zmm7, 16, 32) \ +X(YMM8H, 392, zmm8, 16, 32) \ +X(YMM9H, 393, zmm9, 16, 32) \ +X(YMM10H, 394, zmm10, 16, 32) \ +X(YMM11H, 395, zmm11, 16, 32) \ +X(YMM12H, 396, zmm12, 16, 32) \ +X(YMM13H, 397, zmm13, 16, 32) \ +X(YMM14H, 398, zmm14, 16, 32) \ +X(YMM15H, 399, zmm15, 16, 32) \ +X(XMM0IL, 400, zmm0, 0, 8) \ +X(XMM1IL, 401, zmm1, 0, 8) \ +X(XMM2IL, 402, zmm2, 0, 8) \ +X(XMM3IL, 403, zmm3, 0, 8) \ +X(XMM4IL, 404, zmm4, 0, 8) \ +X(XMM5IL, 405, zmm5, 0, 8) \ +X(XMM6IL, 406, zmm6, 0, 8) \ +X(XMM7IL, 407, zmm7, 0, 8) \ +X(XMM8IL, 408, zmm8, 0, 8) \ +X(XMM9IL, 409, zmm9, 0, 8) \ +X(XMM10IL, 410, zmm10, 0, 8) \ +X(XMM11IL, 411, zmm11, 0, 8) \ +X(XMM12IL, 412, zmm12, 0, 8) \ +X(XMM13IL, 413, zmm13, 0, 8) \ +X(XMM14IL, 414, zmm14, 0, 8) \ +X(XMM15IL, 415, zmm15, 0, 8) \ +X(XMM0IH, 416, zmm0, 8, 8) \ +X(XMM1IH, 417, zmm1, 8, 8) \ +X(XMM2IH, 418, zmm2, 8, 8) \ +X(XMM3IH, 419, zmm3, 8, 8) \ +X(XMM4IH, 420, zmm4, 8, 8) \ +X(XMM5IH, 421, zmm5, 8, 8) \ +X(XMM6IH, 422, zmm6, 8, 8) \ +X(XMM7IH, 423, zmm7, 8, 8) \ +X(XMM8IH, 424, zmm8, 8, 8) \ +X(XMM9IH, 425, zmm9, 8, 8) \ +X(XMM10IH, 426, zmm10, 8, 8) \ +X(XMM11IH, 427, zmm11, 8, 8) \ +X(XMM12IH, 428, zmm12, 8, 8) \ +X(XMM13IH, 429, zmm13, 8, 8) \ +X(XMM14IH, 430, zmm14, 8, 8) \ +X(XMM15IH, 431, zmm15, 8, 8) \ +X(YMM0I0, 432, zmm0, 0, 8) \ +X(YMM0I1, 433, zmm0, 8, 8) \ +X(YMM0I2, 434, zmm0, 16, 8) \ +X(YMM0I3, 435, zmm0, 24, 8) \ +X(YMM1I0, 436, zmm1, 0, 8) \ +X(YMM1I1, 437, zmm1, 8, 8) \ +X(YMM1I2, 438, zmm1, 16, 8) \ +X(YMM1I3, 439, zmm1, 24, 8) \ +X(YMM2I0, 440, zmm2, 0, 8) \ +X(YMM2I1, 441, zmm2, 8, 8) \ +X(YMM2I2, 442, zmm2, 16, 8) \ +X(YMM2I3, 443, zmm2, 24, 8) \ +X(YMM3I0, 444, zmm3, 0, 8) \ +X(YMM3I1, 445, zmm3, 8, 8) \ +X(YMM3I2, 446, zmm3, 16, 8) \ +X(YMM3I3, 447, zmm3, 24, 8) \ +X(YMM4I0, 448, zmm4, 0, 8) \ +X(YMM4I1, 449, zmm4, 8, 8) \ +X(YMM4I2, 450, zmm4, 16, 8) \ +X(YMM4I3, 451, zmm4, 24, 8) \ +X(YMM5I0, 452, zmm5, 0, 8) \ +X(YMM5I1, 453, zmm5, 8, 8) \ +X(YMM5I2, 454, zmm5, 16, 8) \ +X(YMM5I3, 455, zmm5, 24, 8) \ +X(YMM6I0, 456, zmm6, 0, 8) \ +X(YMM6I1, 457, zmm6, 8, 8) \ +X(YMM6I2, 458, zmm6, 16, 8) \ +X(YMM6I3, 459, zmm6, 24, 8) \ +X(YMM7I0, 460, zmm7, 0, 8) \ +X(YMM7I1, 461, zmm7, 8, 8) \ +X(YMM7I2, 462, zmm7, 16, 8) \ +X(YMM7I3, 463, zmm7, 24, 8) \ +X(YMM8I0, 464, zmm8, 0, 8) \ +X(YMM8I1, 465, zmm8, 8, 8) \ +X(YMM8I2, 466, zmm8, 16, 8) \ +X(YMM8I3, 467, zmm8, 24, 8) \ +X(YMM9I0, 468, zmm9, 0, 8) \ +X(YMM9I1, 469, zmm9, 8, 8) \ +X(YMM9I2, 470, zmm9, 16, 8) \ +X(YMM9I3, 471, zmm9, 24, 8) \ +X(YMM10I0, 472, zmm10, 0, 8) \ +X(YMM10I1, 473, zmm10, 8, 8) \ +X(YMM10I2, 474, zmm10, 16, 8) \ +X(YMM10I3, 475, zmm10, 24, 8) \ +X(YMM11I0, 476, zmm11, 0, 8) \ +X(YMM11I1, 477, zmm11, 8, 8) \ +X(YMM11I2, 478, zmm11, 16, 8) \ +X(YMM11I3, 479, zmm11, 24, 8) \ +X(YMM12I0, 480, zmm12, 0, 8) \ +X(YMM12I1, 481, zmm12, 8, 8) \ +X(YMM12I2, 482, zmm12, 16, 8) \ +X(YMM12I3, 483, zmm12, 24, 8) \ +X(YMM13I0, 484, zmm13, 0, 8) \ +X(YMM13I1, 485, zmm13, 8, 8) \ +X(YMM13I2, 486, zmm13, 16, 8) \ +X(YMM13I3, 487, zmm13, 24, 8) \ +X(YMM14I0, 488, zmm14, 0, 8) \ +X(YMM14I1, 489, zmm14, 8, 8) \ +X(YMM14I2, 490, zmm14, 16, 8) \ +X(YMM14I3, 491, zmm14, 24, 8) \ +X(YMM15I0, 492, zmm15, 0, 8) \ +X(YMM15I1, 493, zmm15, 8, 8) \ +X(YMM15I2, 494, zmm15, 16, 8) \ +X(YMM15I3, 495, zmm15, 24, 8) \ +X(YMM0F0, 496, zmm0, 0, 4) \ +X(YMM0F1, 497, zmm0, 4, 4) \ +X(YMM0F2, 498, zmm0, 8, 4) \ +X(YMM0F3, 499, zmm0, 12, 4) \ +X(YMM0F4, 500, zmm0, 16, 4) \ +X(YMM0F5, 501, zmm0, 20, 4) \ +X(YMM0F6, 502, zmm0, 24, 4) \ +X(YMM0F7, 503, zmm0, 28, 4) \ +X(YMM1F0, 504, zmm1, 0, 4) \ +X(YMM1F1, 505, zmm1, 4, 4) \ +X(YMM1F2, 506, zmm1, 8, 4) \ +X(YMM1F3, 507, zmm1, 12, 4) \ +X(YMM1F4, 508, zmm1, 16, 4) \ +X(YMM1F5, 509, zmm1, 20, 4) \ +X(YMM1F6, 510, zmm1, 24, 4) \ +X(YMM1F7, 511, zmm1, 28, 4) \ +X(YMM2F0, 512, zmm2, 0, 4) \ +X(YMM2F1, 513, zmm2, 4, 4) \ +X(YMM2F2, 514, zmm2, 8, 4) \ +X(YMM2F3, 515, zmm2, 12, 4) \ +X(YMM2F4, 516, zmm2, 16, 4) \ +X(YMM2F5, 517, zmm2, 20, 4) \ +X(YMM2F6, 518, zmm2, 24, 4) \ +X(YMM2F7, 519, zmm2, 28, 4) \ +X(YMM3F0, 520, zmm3, 0, 4) \ +X(YMM3F1, 521, zmm3, 4, 4) \ +X(YMM3F2, 522, zmm3, 8, 4) \ +X(YMM3F3, 523, zmm3, 12, 4) \ +X(YMM3F4, 524, zmm3, 16, 4) \ +X(YMM3F5, 525, zmm3, 20, 4) \ +X(YMM3F6, 526, zmm3, 24, 4) \ +X(YMM3F7, 527, zmm3, 28, 4) \ +X(YMM4F0, 528, zmm4, 0, 4) \ +X(YMM4F1, 529, zmm4, 4, 4) \ +X(YMM4F2, 530, zmm4, 8, 4) \ +X(YMM4F3, 531, zmm4, 12, 4) \ +X(YMM4F4, 532, zmm4, 16, 4) \ +X(YMM4F5, 533, zmm4, 20, 4) \ +X(YMM4F6, 534, zmm4, 24, 4) \ +X(YMM4F7, 535, zmm4, 28, 4) \ +X(YMM5F0, 536, zmm5, 0, 4) \ +X(YMM5F1, 537, zmm5, 4, 4) \ +X(YMM5F2, 538, zmm5, 8, 4) \ +X(YMM5F3, 539, zmm5, 12, 4) \ +X(YMM5F4, 540, zmm5, 16, 4) \ +X(YMM5F5, 541, zmm5, 20, 4) \ +X(YMM5F6, 542, zmm5, 24, 4) \ +X(YMM5F7, 543, zmm5, 28, 4) \ +X(YMM6F0, 544, zmm6, 0, 4) \ +X(YMM6F1, 545, zmm6, 4, 4) \ +X(YMM6F2, 546, zmm6, 8, 4) \ +X(YMM6F3, 547, zmm6, 12, 4) \ +X(YMM6F4, 548, zmm6, 16, 4) \ +X(YMM6F5, 549, zmm6, 20, 4) \ +X(YMM6F6, 550, zmm6, 24, 4) \ +X(YMM6F7, 551, zmm6, 28, 4) \ +X(YMM7F0, 552, zmm7, 0, 4) \ +X(YMM7F1, 553, zmm7, 4, 4) \ +X(YMM7F2, 554, zmm7, 8, 4) \ +X(YMM7F3, 555, zmm7, 12, 4) \ +X(YMM7F4, 556, zmm7, 16, 4) \ +X(YMM7F5, 557, zmm7, 20, 4) \ +X(YMM7F6, 558, zmm7, 24, 4) \ +X(YMM7F7, 559, zmm7, 28, 4) \ +X(YMM8F0, 560, zmm8, 0, 4) \ +X(YMM8F1, 561, zmm8, 4, 4) \ +X(YMM8F2, 562, zmm8, 8, 4) \ +X(YMM8F3, 563, zmm8, 12, 4) \ +X(YMM8F4, 564, zmm8, 16, 4) \ +X(YMM8F5, 565, zmm8, 20, 4) \ +X(YMM8F6, 566, zmm8, 24, 4) \ +X(YMM8F7, 567, zmm8, 28, 4) \ +X(YMM9F0, 568, zmm9, 0, 4) \ +X(YMM9F1, 569, zmm9, 4, 4) \ +X(YMM9F2, 570, zmm9, 8, 4) \ +X(YMM9F3, 571, zmm9, 12, 4) \ +X(YMM9F4, 572, zmm9, 16, 4) \ +X(YMM9F5, 573, zmm9, 20, 4) \ +X(YMM9F6, 574, zmm9, 24, 4) \ +X(YMM9F7, 575, zmm9, 28, 4) \ +X(YMM10F0, 576, zmm10, 0, 4) \ +X(YMM10F1, 577, zmm10, 4, 4) \ +X(YMM10F2, 578, zmm10, 8, 4) \ +X(YMM10F3, 579, zmm10, 12, 4) \ +X(YMM10F4, 580, zmm10, 16, 4) \ +X(YMM10F5, 581, zmm10, 20, 4) \ +X(YMM10F6, 582, zmm10, 24, 4) \ +X(YMM10F7, 583, zmm10, 28, 4) \ +X(YMM11F0, 584, zmm11, 0, 4) \ +X(YMM11F1, 585, zmm11, 4, 4) \ +X(YMM11F2, 586, zmm11, 8, 4) \ +X(YMM11F3, 587, zmm11, 12, 4) \ +X(YMM11F4, 588, zmm11, 16, 4) \ +X(YMM11F5, 589, zmm11, 20, 4) \ +X(YMM11F6, 590, zmm11, 24, 4) \ +X(YMM11F7, 591, zmm11, 28, 4) \ +X(YMM12F0, 592, zmm12, 0, 4) \ +X(YMM12F1, 593, zmm12, 4, 4) \ +X(YMM12F2, 594, zmm12, 8, 4) \ +X(YMM12F3, 595, zmm12, 12, 4) \ +X(YMM12F4, 596, zmm12, 16, 4) \ +X(YMM12F5, 597, zmm12, 20, 4) \ +X(YMM12F6, 598, zmm12, 24, 4) \ +X(YMM12F7, 599, zmm12, 28, 4) \ +X(YMM13F0, 600, zmm13, 0, 4) \ +X(YMM13F1, 601, zmm13, 4, 4) \ +X(YMM13F2, 602, zmm13, 8, 4) \ +X(YMM13F3, 603, zmm13, 12, 4) \ +X(YMM13F4, 604, zmm13, 16, 4) \ +X(YMM13F5, 605, zmm13, 20, 4) \ +X(YMM13F6, 606, zmm13, 24, 4) \ +X(YMM13F7, 607, zmm13, 28, 4) \ +X(YMM14F0, 608, zmm14, 0, 4) \ +X(YMM14F1, 609, zmm14, 4, 4) \ +X(YMM14F2, 610, zmm14, 8, 4) \ +X(YMM14F3, 611, zmm14, 12, 4) \ +X(YMM14F4, 612, zmm14, 16, 4) \ +X(YMM14F5, 613, zmm14, 20, 4) \ +X(YMM14F6, 614, zmm14, 24, 4) \ +X(YMM14F7, 615, zmm14, 28, 4) \ +X(YMM15F0, 616, zmm15, 0, 4) \ +X(YMM15F1, 617, zmm15, 4, 4) \ +X(YMM15F2, 618, zmm15, 8, 4) \ +X(YMM15F3, 619, zmm15, 12, 4) \ +X(YMM15F4, 620, zmm15, 16, 4) \ +X(YMM15F5, 621, zmm15, 20, 4) \ +X(YMM15F6, 622, zmm15, 24, 4) \ +X(YMM15F7, 623, zmm15, 28, 4) \ +X(YMM0D0, 624, zmm0, 0, 8) \ +X(YMM0D1, 625, zmm0, 8, 8) \ +X(YMM0D2, 626, zmm0, 16, 8) \ +X(YMM0D3, 627, zmm0, 24, 8) \ +X(YMM1D0, 628, zmm1, 0, 8) \ +X(YMM1D1, 629, zmm1, 8, 8) \ +X(YMM1D2, 630, zmm1, 16, 8) \ +X(YMM1D3, 631, zmm1, 24, 8) \ +X(YMM2D0, 632, zmm2, 0, 8) \ +X(YMM2D1, 633, zmm2, 8, 8) \ +X(YMM2D2, 634, zmm2, 16, 8) \ +X(YMM2D3, 635, zmm2, 24, 8) \ +X(YMM3D0, 636, zmm3, 0, 8) \ +X(YMM3D1, 637, zmm3, 8, 8) \ +X(YMM3D2, 638, zmm3, 16, 8) \ +X(YMM3D3, 639, zmm3, 24, 8) \ +X(YMM4D0, 640, zmm4, 0, 8) \ +X(YMM4D1, 641, zmm4, 8, 8) \ +X(YMM4D2, 642, zmm4, 16, 8) \ +X(YMM4D3, 643, zmm4, 24, 8) \ +X(YMM5D0, 644, zmm5, 0, 8) \ +X(YMM5D1, 645, zmm5, 8, 8) \ +X(YMM5D2, 646, zmm5, 16, 8) \ +X(YMM5D3, 647, zmm5, 24, 8) \ +X(YMM6D0, 648, zmm6, 0, 8) \ +X(YMM6D1, 649, zmm6, 8, 8) \ +X(YMM6D2, 650, zmm6, 16, 8) \ +X(YMM6D3, 651, zmm6, 24, 8) \ +X(YMM7D0, 652, zmm7, 0, 8) \ +X(YMM7D1, 653, zmm7, 8, 8) \ +X(YMM7D2, 654, zmm7, 16, 8) \ +X(YMM7D3, 655, zmm7, 24, 8) \ +X(YMM8D0, 656, zmm8, 0, 8) \ +X(YMM8D1, 657, zmm8, 8, 8) \ +X(YMM8D2, 658, zmm8, 16, 8) \ +X(YMM8D3, 659, zmm8, 24, 8) \ +X(YMM9D0, 660, zmm9, 0, 8) \ +X(YMM9D1, 661, zmm9, 8, 8) \ +X(YMM9D2, 662, zmm9, 16, 8) \ +X(YMM9D3, 663, zmm9, 24, 8) \ +X(YMM10D0, 664, zmm10, 0, 8) \ +X(YMM10D1, 665, zmm10, 8, 8) \ +X(YMM10D2, 666, zmm10, 16, 8) \ +X(YMM10D3, 667, zmm10, 24, 8) \ +X(YMM11D0, 668, zmm11, 0, 8) \ +X(YMM11D1, 669, zmm11, 8, 8) \ +X(YMM11D2, 670, zmm11, 16, 8) \ +X(YMM11D3, 671, zmm11, 24, 8) \ +X(YMM12D0, 672, zmm12, 0, 8) \ +X(YMM12D1, 673, zmm12, 8, 8) \ +X(YMM12D2, 674, zmm12, 16, 8) \ +X(YMM12D3, 675, zmm12, 24, 8) \ +X(YMM13D0, 676, zmm13, 0, 8) \ +X(YMM13D1, 677, zmm13, 8, 8) \ +X(YMM13D2, 678, zmm13, 16, 8) \ +X(YMM13D3, 679, zmm13, 24, 8) \ +X(YMM14D0, 680, zmm14, 0, 8) \ +X(YMM14D1, 681, zmm14, 8, 8) \ +X(YMM14D2, 682, zmm14, 16, 8) \ +X(YMM14D3, 683, zmm14, 24, 8) \ +X(YMM15D0, 684, zmm15, 0, 8) \ +X(YMM15D1, 685, zmm15, 8, 8) \ +X(YMM15D2, 686, zmm15, 16, 8) \ +X(YMM15D3, 687, zmm15, 24, 8) \ +X(XMM16, 694, zmm16, 0, 16) \ +X(XMM17, 695, zmm17, 0, 16) \ +X(XMM18, 696, zmm18, 0, 16) \ +X(XMM19, 697, zmm19, 0, 16) \ +X(XMM20, 698, zmm20, 0, 16) \ +X(XMM21, 699, zmm21, 0, 16) \ +X(XMM22, 700, zmm22, 0, 16) \ +X(XMM23, 701, zmm23, 0, 16) \ +X(XMM24, 702, zmm24, 0, 16) \ +X(XMM25, 703, zmm25, 0, 16) \ +X(XMM26, 704, zmm26, 0, 16) \ +X(XMM27, 705, zmm27, 0, 16) \ +X(XMM28, 706, zmm28, 0, 16) \ +X(XMM29, 707, zmm29, 0, 16) \ +X(XMM30, 708, zmm30, 0, 16) \ +X(XMM31, 709, zmm31, 0, 16) \ +X(YMM16, 710, zmm16, 0, 32) \ +X(YMM17, 711, zmm17, 0, 32) \ +X(YMM18, 712, zmm18, 0, 32) \ +X(YMM19, 713, zmm19, 0, 32) \ +X(YMM20, 714, zmm20, 0, 32) \ +X(YMM21, 715, zmm21, 0, 32) \ +X(YMM22, 716, zmm22, 0, 32) \ +X(YMM23, 717, zmm23, 0, 32) \ +X(YMM24, 718, zmm24, 0, 32) \ +X(YMM25, 719, zmm25, 0, 32) \ +X(YMM26, 720, zmm26, 0, 32) \ +X(YMM27, 721, zmm27, 0, 32) \ +X(YMM28, 722, zmm28, 0, 32) \ +X(YMM29, 723, zmm29, 0, 32) \ +X(YMM30, 724, zmm30, 0, 32) \ +X(YMM31, 725, zmm31, 0, 32) \ +X(ZMM0, 726, zmm0, 0, 64) \ +X(ZMM1, 727, zmm1, 0, 64) \ +X(ZMM2, 728, zmm2, 0, 64) \ +X(ZMM3, 729, zmm3, 0, 64) \ +X(ZMM4, 730, zmm4, 0, 64) \ +X(ZMM5, 731, zmm5, 0, 64) \ +X(ZMM6, 732, zmm6, 0, 64) \ +X(ZMM7, 733, zmm7, 0, 64) \ +X(ZMM8, 734, zmm8, 0, 64) \ +X(ZMM9, 735, zmm9, 0, 64) \ +X(ZMM10, 736, zmm10, 0, 64) \ +X(ZMM11, 737, zmm11, 0, 64) \ +X(ZMM12, 738, zmm12, 0, 64) \ +X(ZMM13, 739, zmm13, 0, 64) \ +X(ZMM14, 740, zmm14, 0, 64) \ +X(ZMM15, 741, zmm15, 0, 64) \ +X(ZMM16, 742, zmm16, 0, 64) \ +X(ZMM17, 743, zmm17, 0, 64) \ +X(ZMM18, 744, zmm18, 0, 64) \ +X(ZMM19, 745, zmm19, 0, 64) \ +X(ZMM20, 746, zmm20, 0, 64) \ +X(ZMM21, 747, zmm21, 0, 64) \ +X(ZMM22, 748, zmm22, 0, 64) \ +X(ZMM23, 749, zmm23, 0, 64) \ +X(ZMM24, 750, zmm24, 0, 64) \ +X(ZMM25, 751, zmm25, 0, 64) \ +X(ZMM26, 752, zmm26, 0, 64) \ +X(ZMM27, 753, zmm27, 0, 64) \ +X(ZMM28, 754, zmm28, 0, 64) \ +X(ZMM29, 755, zmm29, 0, 64) \ +X(ZMM30, 756, zmm30, 0, 64) \ +X(ZMM31, 757, zmm31, 0, 64) \ +X(K0, 758, k0, 0, 8) \ +X(K1, 759, k1, 0, 8) \ +X(K2, 760, k2, 0, 8) \ +X(K3, 761, k3, 0, 8) \ +X(K4, 762, k4, 0, 8) \ +X(K5, 763, k5, 0, 8) \ +X(K6, 764, k6, 0, 8) \ +X(K7, 765, k7, 0, 8) \ +X(ZMM0H, 766, zmm0, 32, 32) \ +X(ZMM1H, 767, zmm1, 32, 32) \ +X(ZMM2H, 768, zmm2, 32, 32) \ +X(ZMM3H, 769, zmm3, 32, 32) \ +X(ZMM4H, 770, zmm4, 32, 32) \ +X(ZMM5H, 771, zmm5, 32, 32) \ +X(ZMM6H, 772, zmm6, 32, 32) \ +X(ZMM7H, 773, zmm7, 32, 32) \ +X(ZMM8H, 774, zmm8, 32, 32) \ +X(ZMM9H, 775, zmm9, 32, 32) \ +X(ZMM10H, 776, zmm10, 32, 32) \ +X(ZMM11H, 777, zmm11, 32, 32) \ +X(ZMM12H, 778, zmm12, 32, 32) \ +X(ZMM13H, 779, zmm13, 32, 32) \ +X(ZMM14H, 780, zmm14, 32, 32) \ +X(ZMM15H, 781, zmm15, 32, 32) typedef U16 CV_Regx64; typedef enum CV_Regx64Enum @@ -1015,11 +1015,11 @@ CV_Regx64Enum; #define CV_SignatureXList(X) \ - X(C6, 0) \ - X(C7, 1) \ - X(C11, 2) \ - X(C13, 4) \ - X(RESERVED, 5) +X(C6, 0) \ +X(C7, 1) \ +X(C11, 2) \ +X(C13, 4) \ +X(RESERVED, 5) typedef U32 CV_Signature; typedef enum CV_SignatureEnum @@ -1032,23 +1032,23 @@ CV_SignatureEnum; #define CV_LanguageXList(X) \ - X(C, 0x00) \ - X(CXX, 0x01) \ - X(FORTRAN, 0x02) \ - X(MASM, 0x03) \ - X(PASCAL, 0x04) \ - X(BASIC, 0x05) \ - X(COBOL, 0x06) \ - X(LINK, 0x07) \ - X(CVTRES, 0x08) \ - X(CVTPGD, 0x09) \ - X(CSHARP, 0x0A) \ - X(VB, 0x0B) \ - X(ILASM, 0x0C) \ - X(JAVA, 0x0D) \ - X(JSCRIPT, 0x0E) \ - X(MSIL, 0x0F) \ - X(HLSL, 0x10) +X(C, 0x00) \ +X(CXX, 0x01) \ +X(FORTRAN, 0x02) \ +X(MASM, 0x03) \ +X(PASCAL, 0x04) \ +X(BASIC, 0x05) \ +X(COBOL, 0x06) \ +X(LINK, 0x07) \ +X(CVTRES, 0x08) \ +X(CVTPGD, 0x09) \ +X(CSHARP, 0x0A) \ +X(VB, 0x0B) \ +X(ILASM, 0x0C) \ +X(JAVA, 0x0D) \ +X(JSCRIPT, 0x0E) \ +X(MSIL, 0x0F) \ +X(HLSL, 0x10) typedef U16 CV_Language; typedef enum CV_LanguageEnum @@ -1732,7 +1732,7 @@ enum CV_Compile3Flag_SDL = (1 << 17), CV_Compile3Flag_PGO = (1 << 18), CV_Compile3Flag_EXP = (1 << 19), - + CV_Compile3Flag_Language_Shift = 0, CV_Compile3Flag_Language_Mask = 0xff, }; @@ -2111,13 +2111,13 @@ struct CV_SymInlinees #define CV_TypeId_Variadic 0 #define CV_BasicPointerKindXList(X) \ - X(VALUE, 0x0) \ - X(16BIT, 0x1) \ - X(FAR_16BIT, 0x2) \ - X(HUGE_16BIT, 0x3) \ - X(32BIT, 0x4) \ - X(16_32BIT, 0x5) \ - X(64BIT, 0x6) +X(VALUE, 0x0) \ +X(16BIT, 0x1) \ +X(FAR_16BIT, 0x2) \ +X(HUGE_16BIT, 0x3) \ +X(32BIT, 0x4) \ +X(16_32BIT, 0x5) \ +X(64BIT, 0x6) typedef U8 CV_BasicPointerKind; typedef enum @@ -2781,21 +2781,21 @@ struct CV_LeafUDTModSrcLine #define CV_C13SubSectionKind_IgnoreFlag 0x80000000 #define CV_C13SubSectionKindXList(X) \ - X(Symbols, 0xF1) \ - X(Lines, 0xF2) \ - X(StringTable, 0xF3) \ - X(FileChksms, 0xF4) \ - X(FrameData, 0xF5) \ - X(InlineeLines, 0xF6) \ - X(CrossScopeImports, 0xF7) \ - X(CrossScopeExports, 0xF8) \ - X(IlLines, 0xF9) \ - X(FuncMDTokenMap, 0xFA) \ - X(TypeMDTokenMap, 0xFB) \ - X(MergedAssemblyInput, 0xFC) \ - X(CoffSymbolRVA, 0xFD) \ - X(XfgHashType, 0xFF) \ - X(XfgHashVirtual, 0x100) +X(Symbols, 0xF1) \ +X(Lines, 0xF2) \ +X(StringTable, 0xF3) \ +X(FileChksms, 0xF4) \ +X(FrameData, 0xF5) \ +X(InlineeLines, 0xF6) \ +X(CrossScopeImports, 0xF7) \ +X(CrossScopeExports, 0xF8) \ +X(IlLines, 0xF9) \ +X(FuncMDTokenMap, 0xFA) \ +X(TypeMDTokenMap, 0xFB) \ +X(MergedAssemblyInput, 0xFC) \ +X(CoffSymbolRVA, 0xFD) \ +X(XfgHashType, 0xFF) \ +X(XfgHashVirtual, 0x100) typedef U32 CV_C13SubSectionKind; typedef enum CV_C13SubSectionKindEnum @@ -2974,4 +2974,4 @@ internal U32 cv_map_encoded_base_pointer(CV_Arch arch, U32 enc internal String8 cv_string_from_inline_range_kind(CV_InlineRangeKind kind); #endif // CODEVIEW_H - + diff --git a/src/codeview/codeview.mdesk b/src/codeview/codeview.mdesk index ac511efd..10a9dd61 100644 --- a/src/codeview/codeview.mdesk +++ b/src/codeview/codeview.mdesk @@ -588,7 +588,7 @@ CV_LeafKindTable: {MATRIX - 0x151c} {VFTABLE - 0x151d} {FUNC_ID FuncId 0x1601} - {MFUNC_ID MFuncId 0x1602} + {MFUNC_ID MFuncId 0x1602} {BUILDINFO BuildInfo 0x1603} {SUBSTR_LIST SubstrList 0x1604} {STRING_ID StringId 0x1605} diff --git a/src/codeview/codeview_enum.c b/src/codeview/codeview_enum.c index 4413fcca..061210ce 100644 --- a/src/codeview/codeview_enum.c +++ b/src/codeview/codeview_enum.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal String8 @@ -11,10 +11,10 @@ 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; + 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(); } @@ -23,9 +23,9 @@ 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 +#define X(_n,_i) case _i: return str8_lit(Stringify(_n)); + CV_LanguageXList(X) +#undef X } return str8_zero(); } @@ -57,21 +57,21 @@ cv_string_from_reg_id(Arena *arena, CV_Arch arch, U32 id) { String8 result = str8_zero(); switch (arch) { - case CV_Arch_8086: { + 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 +#define X(_N, _ID, ...) case _ID: result = str8_lit(Stringify(_N)); break; + CV_Reg_X86_XList(X) +#undef X } - } break; - case CV_Arch_X64: { + } 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 +#define X(_N, _ID, ...) case _ID: result = str8_lit(Stringify(_N)); break; + CV_Reg_X64_XList(X) +#undef X } - } break; - default: NotImplemented; break; + } break; + default: NotImplemented; break; } if (result.size == 0) { result = push_str8f(arena, "%x", id); @@ -327,9 +327,9 @@ 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)); +#define X(_N, _ID) case CV_C13SubSectionKind_##_N: return str8_lit(Stringify(_N)); CV_C13SubSectionKindXList(X) - #undef X +#undef X } return str8_zero(); } @@ -357,7 +357,7 @@ 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; @@ -391,13 +391,13 @@ cv_string_from_pointer_attribs(Arena *arena, CV_PointerAttribs x) 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); @@ -409,11 +409,11 @@ cv_string_from_pointer_attribs(Arena *arena, CV_PointerAttribs x) 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; @@ -591,13 +591,13 @@ 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}; @@ -653,7 +653,7 @@ cv_string_from_type_props(Arena *arena, CV_TypeProps32 x) 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); } @@ -663,7 +663,7 @@ cv_string_from_type_props(Arena *arena, CV_TypeProps32 x) } String8 result = push_str8f(arena, "%S", flags_str); - + scratch_end(scratch); return result; } @@ -785,14 +785,14 @@ 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) { @@ -819,16 +819,16 @@ cv_string_from_field_attribs(Arena *arena, CV_FieldAttribs 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; } @@ -841,7 +841,7 @@ cv_string_from_itype(Arena *arena, CV_TypeIndex min_itype, CV_TypeIndex 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) { @@ -899,7 +899,7 @@ cv_string_from_itype(Arena *arena, CV_TypeIndex min_itype, CV_TypeIndex itype) 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) { @@ -910,7 +910,7 @@ cv_string_from_itype(Arena *arena, CV_TypeIndex min_itype, CV_TypeIndex itype) 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); diff --git a/src/codeview/codeview_enum.h b/src/codeview/codeview_enum.h index 67095f78..1dd0615a 100644 --- a/src/codeview/codeview_enum.h +++ b/src/codeview/codeview_enum.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef CODEVIEW_ENUM_H diff --git a/src/codeview/codeview_parse.c b/src/codeview/codeview_parse.c index 57a0020c..391ad855 100644 --- a/src/codeview/codeview_parse.c +++ b/src/codeview/codeview_parse.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- Hasher diff --git a/src/codeview/codeview_parse.h b/src/codeview/codeview_parse.h index e2b0fb01..d77e2913 100644 --- a/src/codeview/codeview_parse.h +++ b/src/codeview/codeview_parse.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef CODEVIEW_PARSE_H diff --git a/src/codeview/generated/codeview.meta.c b/src/codeview/generated/codeview.meta.c index 898e4989..672e674a 100644 --- a/src/codeview/generated/codeview.meta.c +++ b/src/codeview/generated/codeview.meta.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/codeview/generated/codeview.meta.h b/src/codeview/generated/codeview.meta.h index 9606dbf5..84612e5e 100644 --- a/src/codeview/generated/codeview.meta.h +++ b/src/codeview/generated/codeview.meta.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/coff/coff.c b/src/coff/coff.c index 11e5d92a..582c38b2 100644 --- a/src/coff/coff.c +++ b/src/coff/coff.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U64 @@ -32,20 +32,20 @@ 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 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; @@ -127,12 +127,12 @@ coff_apply_size_from_reloc_x64(COFF_Reloc_X64 x) case COFF_Reloc_X64_Section: return 2; case COFF_Reloc_X64_SecRel: return 4; case COFF_Reloc_X64_SRel32: return 4; - + case COFF_Reloc_X64_SecRel7: case COFF_Reloc_X64_Token: case COFF_Reloc_X64_Pair: case COFF_Reloc_X64_SSpan32: - NotImplemented; + NotImplemented; break; } return 0; @@ -153,7 +153,7 @@ coff_apply_size_from_reloc_x86(COFF_Reloc_X86 x) case COFF_Reloc_X86_Token: return 4; case COFF_Reloc_X86_SecRel7: return 1; case COFF_Reloc_X86_Rel32: return 4; - + case COFF_Reloc_X86_Unknown0: case COFF_Reloc_X86_Unknown2: case COFF_Reloc_X86_Unknown3: @@ -162,7 +162,7 @@ coff_apply_size_from_reloc_x86(COFF_Reloc_X86 x) case COFF_Reloc_X86_Unknown7: case COFF_Reloc_X86_Unknown8: case COFF_Reloc_X86_Unknown9: - NotImplemented; + NotImplemented; break; } return 0; @@ -217,7 +217,7 @@ coff_make_import_header_by_name(Arena *arena, COFF_ImportHeaderFlags flags = 0; flags |= (type & COFF_ImportHeader_TypeMask) << COFF_ImportHeader_TypeShift; flags |= COFF_ImportBy_Name << COFF_ImportHeader_ImportByShift; - + COFF_ImportHeader header = {0}; header.sig1 = COFF_MachineType_Unknown; header.sig2 = max_U16; @@ -260,7 +260,7 @@ coff_make_import_header_by_ordinal(Arena *arena, 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; @@ -296,8 +296,8 @@ coff_word_size_from_machine(COFF_MachineType machine) { U64 result = 0; switch (machine) { - case COFF_MachineType_X64: result = 8; break; - case COFF_MachineType_X86: result = 4; break; + case COFF_MachineType_X64: result = 8; break; + case COFF_MachineType_X86: result = 4; break; } return result; } @@ -307,8 +307,8 @@ coff_default_exe_base_from_machine(COFF_MachineType machine) { U64 exe_base = 0; switch (coff_word_size_from_machine(machine)) { - case 4: exe_base = 0x400000; break; - case 8: exe_base = 0x140000000; break; + case 4: exe_base = 0x400000; break; + case 8: exe_base = 0x140000000; break; } return exe_base; } @@ -318,8 +318,8 @@ coff_default_dll_base_from_machine(COFF_MachineType machine) { U64 dll_base = 0; switch (coff_word_size_from_machine(machine)) { - case 4: dll_base = 0x10000000; break; - case 8: dll_base = 0x180000000; break; + case 4: dll_base = 0x10000000; break; + case 8: dll_base = 0x180000000; break; } return dll_base; } diff --git a/src/coff/coff.h b/src/coff/coff.h index 33cec229..8961ca3c 100644 --- a/src/coff/coff.h +++ b/src/coff/coff.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef COFF_H diff --git a/src/coff/coff_enum.c b/src/coff/coff_enum.c index ccd96eeb..430f139d 100644 --- a/src/coff/coff_enum.c +++ b/src/coff/coff_enum.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal String8 @@ -62,13 +62,13 @@ 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; + 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; } @@ -89,7 +89,7 @@ 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"); } @@ -126,9 +126,9 @@ coff_string_from_flags(Arena *arena, COFF_FileHeaderFlags flags) 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; } @@ -201,7 +201,7 @@ coff_string_from_section_flags(Arena *arena, COFF_SectionFlags flags) if (align) { str8_list_pushf(scratch.arena, &list, "Align=%u", align); } - + if (!list.node_count) { str8_list_pushf(scratch.arena, &list, "None"); } @@ -218,9 +218,9 @@ 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"); @@ -236,9 +236,9 @@ coff_string_from_resource_memory_flags(Arena *arena, COFF_ResourceMemoryFlags fl 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; } diff --git a/src/coff/coff_enum.h b/src/coff/coff_enum.h index 1ea360a7..0c52eb28 100644 --- a/src/coff/coff_enum.h +++ b/src/coff/coff_enum.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef COFF_ENUM_H diff --git a/src/coff/coff_parse.c b/src/coff/coff_parse.c index 15a918a5..3a53e8ba 100644 --- a/src/coff/coff_parse.c +++ b/src/coff/coff_parse.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal B32 @@ -8,9 +8,9 @@ coff_is_big_obj(String8 raw_coff) if (raw_coff.size >= sizeof(COFF_BigObjHeader)) { COFF_BigObjHeader *file_header32 = (COFF_BigObjHeader*)(raw_coff.str); is_big_obj = file_header32->sig1 == COFF_MachineType_Unknown && - file_header32->sig2 == max_U16 && - file_header32->version >= 2 && - MemoryCompare(file_header32->magic, g_coff_big_header_magic, sizeof(file_header32->magic)) == 0; + file_header32->sig2 == max_U16 && + file_header32->version >= 2 && + MemoryCompare(file_header32->magic, g_coff_big_header_magic, sizeof(file_header32->magic)) == 0; } return is_big_obj; } @@ -163,11 +163,11 @@ coff_symbol_array_from_data_16(Arena *arena, String8 raw_coff, U64 symbol_array_ Rng1U64 sym16_arr_range = rng_1u64(symbol_array_off, symbol_array_off + sizeof(COFF_Symbol16) * symbol_count); String8 raw_sym16_arr = str8_substr(raw_coff, sym16_arr_range); COFF_Symbol16 *sym16_arr = (COFF_Symbol16 *)raw_sym16_arr.str; - + for (U64 isymbol = 0, count = raw_sym16_arr.size / sizeof(COFF_Symbol16); isymbol < count; isymbol += 1) { COFF_Symbol16 *sym16 = &sym16_arr[isymbol]; COFF_Symbol32 *sym32 = &result.v[isymbol]; - + sym32->name = sym16->name; sym32->value = sym16->value; if (sym16->section_number == COFF_Symbol_DebugSection16) { @@ -185,7 +185,7 @@ coff_symbol_array_from_data_16(Arena *arena, String8 raw_coff, U64 symbol_array_ for (U64 iaux = isymbol+1, iaux_hi = Min(count, iaux+sym16->aux_symbol_count); iaux < iaux_hi; iaux += 1) { COFF_Symbol16 *aux16 = sym16_arr + iaux; COFF_Symbol32 *aux32 = result.v + iaux; - + // 32bit COFF uses 16bit aux symbols MemoryCopy(aux32, aux16, sizeof(COFF_Symbol16)); MemoryZero((U8 *)aux32 + sizeof(COFF_Symbol16), sizeof(COFF_Symbol32)-sizeof(COFF_Symbol16)); @@ -286,11 +286,11 @@ coff_resource_string_from_str16(Arena *arena, String16 string) { AssertAlways(string.size <= max_U16); U16 size16 = (U16)string.size; - + U16 *buffer = push_array_no_zero(arena, U16, size16 + 1); MemoryCopy(buffer + 0, &size16, sizeof(size16)); MemoryCopy(buffer + 1, string.str, size16 * sizeof(string.str[0])); - + return str8_array(buffer, size16 + 1); } @@ -358,14 +358,14 @@ coff_read_resource(Arena *arena, String8 raw_res, U64 off, COFF_ParsedResource * { String8 raw_header = str8_skip(raw_res, off); U64 header_cursor = 0; - + // prefix COFF_ResourceHeaderPrefix prefix = {0}; header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &prefix); - + Assert(prefix.header_size >= sizeof(COFF_ResourceHeaderPrefix)); raw_header = str8_prefix(raw_header, prefix.header_size); - + // header COFF_ResourceID16 type_16 = {0}; COFF_ResourceID16 name_16 = {0}; @@ -377,11 +377,11 @@ coff_read_resource(Arena *arena, String8 raw_res, U64 off, COFF_ParsedResource * header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->version); header_cursor += str8_deserial_read_struct(raw_header, header_cursor, &res_out->characteristics); Assert(prefix.header_size == header_cursor); - + // convert utf-16 resource ids to utf-8 res_out->type = coff_utf8_resource_id_from_utf16(arena, &type_16); res_out->name = coff_utf8_resource_id_from_utf16(arena, &name_16); - + // read data U64 data_read_size = str8_deserial_read_block(raw_res, off + prefix.header_size, prefix.data_size, &res_out->data); Assert(prefix.data_size == data_read_size); @@ -411,14 +411,14 @@ coff_write_resource_id(Arena *arena, COFF_ResourceID id) { String8 result = str8_zero(); switch (id.type) { - case COFF_ResourceIDType_Null: break; - case COFF_ResourceIDType_Number: { - result = coff_resource_number_from_u16(arena, id.u.number); - } break; - case COFF_ResourceIDType_String: { - result = coff_resource_string_from_str8(arena, id.u.string); - } break; - default: InvalidPath; + case COFF_ResourceIDType_Null: break; + case COFF_ResourceIDType_Number: { + result = coff_resource_number_from_u16(arena, id.u.number); + } break; + case COFF_ResourceIDType_String: { + result = coff_resource_string_from_str8(arena, id.u.string); + } break; + default: InvalidPath; } return result; } @@ -435,13 +435,13 @@ coff_write_resource(Arena *arena, String8 data) { Temp scratch = scratch_begin(&arena, 1); - + String8List list = {0}; - + COFF_ResourceHeaderPrefix *prefix = push_array(scratch.arena, COFF_ResourceHeaderPrefix, 1); String8 packed_type = coff_write_resource_id(scratch.arena, type); String8 packed_name = coff_write_resource_id(scratch.arena, name); - + // prefix + header str8_list_push(scratch.arena, &list, str8_struct(prefix)); str8_list_push(scratch.arena, &list, packed_type); @@ -451,24 +451,24 @@ coff_write_resource(Arena *arena, str8_list_push(scratch.arena, &list, str8_struct(&language_id)); str8_list_push(scratch.arena, &list, str8_struct(&version)); str8_list_push(scratch.arena, &list, str8_struct(&characteristics)); - + prefix->data_size = safe_cast_u32(data.size); prefix->header_size = safe_cast_u32(list.total_size); - + // data str8_list_push(scratch.arena, &list, data); - + // magic str8_list_push_front(scratch.arena, &list, str8_array_fixed(g_coff_res_magic)); - + // align U64 align_size = AlignPow2(list.total_size, COFF_ResourceAlign) - list.total_size; U8 *align = push_array(scratch.arena, U8, align_size); str8_list_push(scratch.arena, &list, str8(align, align_size)); - + // join String8 res = str8_list_join(arena, &list, 0); - + scratch_end(scratch); return res; } @@ -481,10 +481,10 @@ coff_resource_id_compar(void *raw_a, void *raw_b) COFF_ResourceID *b = raw_b; if (a->type == b->type) { switch (a->type) { - default: - case COFF_ResourceIDType_Null: cmp = 0; break; - case COFF_ResourceIDType_Number: cmp = MemoryCompare(&a->u.number, &b->u.number, sizeof(a->u.number)); break; - case COFF_ResourceIDType_String: cmp = strncmp((char *)a->u.string.str, (char *)b->u.string.str, Min(a->u.string.size, b->u.string.size)); break; + default: + case COFF_ResourceIDType_Null: cmp = 0; break; + case COFF_ResourceIDType_Number: cmp = MemoryCompare(&a->u.number, &b->u.number, sizeof(a->u.number)); break; + case COFF_ResourceIDType_String: cmp = strncmp((char *)a->u.string.str, (char *)b->u.string.str, Min(a->u.string.size, b->u.string.size)); break; } } else { cmp = a->type < b->type ? -1 : a->type > b->type ? +1 : 0; @@ -563,10 +563,10 @@ coff_parse_archive_member_header(String8 raw_archive, U64 offset, COFF_ParsedArc String8 mode = str8_skip_chop_whitespace(str8_cstring_capped(header->mode, header->mode + sizeof(header->mode) )); String8 size = str8_skip_chop_whitespace(str8_cstring_capped(header->size, header->size + sizeof(header->size) )); String8 end = str8_cstring_capped(header->end, header->end + sizeof(header->end)); - + U32 data_size = u32_from_str8(size, 10); U64 data_off = offset + sizeof(COFF_ArchiveMemberHeader); - + header_out->name = name; header_out->time_stamp = u32_from_str8(date, 10); header_out->user_id = u32_from_str8(user_id, 10); @@ -574,7 +574,7 @@ coff_parse_archive_member_header(String8 raw_archive, U64 offset, COFF_ParsedArc header_out->mode = mode; header_out->is_end_correct = str8_match_lit("`\n", end, 0); header_out->data_range = rng_1u64(data_off, data_off + data_size); - + return sizeof(*header); } return 0; @@ -584,7 +584,7 @@ internal COFF_ArchiveFirstMember coff_parse_first_archive_member(COFF_ArchiveMember *member) { Assert(str8_match_lit("/", member->header.name, 0)); - + U64 cursor = 0; U32 symbol_count = 0; @@ -597,17 +597,17 @@ coff_parse_first_archive_member(COFF_ArchiveMember *member) Rng1U64 string_table_range = rng_1u64(cursor, member->data.size); cursor += dim_1u64(string_table_range); - + String8 raw_member_offsets = str8_substr(member->data, member_offsets_range); U32 *member_offsets = (U32 *)raw_member_offsets.str; U64 member_offset_count = raw_member_offsets.size / sizeof(member_offsets[0]); - + COFF_ArchiveFirstMember result = {0}; result.symbol_count = symbol_count; result.member_offset_count = member_offset_count; result.member_offsets = member_offsets; result.string_table = str8_substr(member->data, string_table_range); - + return result; } @@ -615,7 +615,7 @@ internal COFF_ArchiveSecondMember coff_parse_second_archive_member(COFF_ArchiveMember *member) { COFF_ArchiveSecondMember result = {0}; - + if (str8_match_lit("/", member->header.name, 0)) { U64 cursor = 0; @@ -632,13 +632,13 @@ coff_parse_second_archive_member(COFF_ArchiveMember *member) cursor += dim_1u64(symbol_indices_range); Rng1U64 string_table_range = rng_1u64(cursor, member->data.size); - + String8 raw_member_offsets = str8_substr(member->data, member_offsets_range); String8 raw_indices = str8_substr(member->data, symbol_indices_range); - + U32 *member_offsets = (U32 *)raw_member_offsets.str; U64 member_offset_count = raw_member_offsets.size / sizeof(member_offsets[0]); - + U16 *symbol_indices = (U16 *)raw_indices.str; U64 symbol_index_count = raw_indices.size / sizeof(symbol_indices[0]); @@ -650,7 +650,7 @@ coff_parse_second_archive_member(COFF_ArchiveMember *member) result.symbol_index_count = symbol_index_count; result.string_table = str8_substr(member->data, string_table_range); } - + return result; } @@ -683,7 +683,7 @@ coff_parse_import(String8 raw_archive_member, U64 offset, COFF_ParsedArchiveImpo Rng1U64 data_range = rng_1u64(offset + sizeof(*header), offset + sizeof(*header) + header->data_size); String8 raw_data = str8_substr(raw_archive_member, data_range); U64 data_cursor = 0; - + header_out->version = header->version; header_out->machine = header->machine; header_out->time_stamp = header->time_stamp; @@ -744,7 +744,7 @@ coff_regular_archive_member_iter_next(String8 raw_archive, U64 *offset, COFF_Arc if (member_out->header.is_end_correct) { member_out->offset = *offset; member_out->data = str8_substr(raw_archive, member_out->header.data_range); - + U64 read_size = AlignPow2(header_size + dim_1u64(member_out->header.data_range), COFF_Archive_MemberAlign); *offset += read_size; @@ -771,19 +771,19 @@ coff_thin_archive_member_iter_next(String8 raw_archive, U64 *offset, COFF_Archiv member_out->header.is_end_correct = 0; U64 header_size = coff_parse_archive_member_header(raw_archive, *offset, &member_out->header); - + if (member_out->header.is_end_correct) { Rng1U64 data_in_archive_range = {0}; if (str8_match_lit("/", member_out->header.name, 0) || str8_match_lit("//", member_out->header.name, 0)) { data_in_archive_range = member_out->header.data_range; } - + member_out->offset = *offset; member_out->data = str8_substr(raw_archive, data_in_archive_range); - + U64 read_size = AlignPow2(header_size + dim_1u64(data_in_archive_range), COFF_Archive_MemberAlign); *offset += read_size; - + is_parsed = 1; } @@ -806,9 +806,9 @@ coff_archive_parse_from_member_list(COFF_ArchiveMemberList member_list) COFF_ArchiveMember first_header = {0}; COFF_ArchiveMember second_header = {0}; COFF_ArchiveMember long_names_member = {0}; - + COFF_ArchiveMemberNode *ptr = member_list.first; - + if (ptr) { if (str8_match_lit("/", ptr->data.header.name, 0)) { if (ptr->data.header.is_end_correct) { @@ -821,7 +821,7 @@ coff_archive_parse_from_member_list(COFF_ArchiveMemberList member_list) } else { error = str8_lit("missing first header"); } - + if (!error.size && ptr) { if (str8_match_lit("/", ptr->data.header.name, 0)) { if (ptr->data.header.is_end_correct) { @@ -833,7 +833,7 @@ coff_archive_parse_from_member_list(COFF_ArchiveMemberList member_list) } } } - + if (!error.size && ptr) { if (str8_match_lit("//", ptr->data.header.name, 0)) { if (ptr->data.header.is_end_correct) { @@ -853,7 +853,7 @@ coff_archive_parse_from_member_list(COFF_ArchiveMemberList member_list) parse.second_member = coff_parse_second_archive_member(&second_header); parse.long_names = long_names_member.data; parse.error = error; - + return parse; } @@ -894,9 +894,9 @@ coff_archive_parse_from_data(String8 raw_archive) { COFF_ArchiveType type = coff_archive_type_from_data(raw_archive); switch (type) { - case COFF_Archive_Null: break; - case COFF_Archive_Regular: return coff_regular_archive_parse_from_data(raw_archive); - case COFF_Archive_Thin: return coff_thin_archive_parse_from_data(raw_archive); + case COFF_Archive_Null: break; + case COFF_Archive_Regular: return coff_regular_archive_parse_from_data(raw_archive); + case COFF_Archive_Thin: return coff_thin_archive_parse_from_data(raw_archive); } COFF_ArchiveParse null_parse = {0}; return null_parse; diff --git a/src/coff/coff_parse.h b/src/coff/coff_parse.h index 7e237646..69c57ff3 100644 --- a/src/coff/coff_parse.h +++ b/src/coff/coff_parse.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef COFF_PARSE_H diff --git a/src/ctrl/ctrl.mdesk b/src/ctrl/ctrl.mdesk index ceb2fca1..9684baeb 100644 --- a/src/ctrl/ctrl.mdesk +++ b/src/ctrl/ctrl.mdesk @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -7,16 +7,17 @@ @table(name code_name display_string) CTRL_EntityKindTable: { - {Root root "Root" } - {Machine machine "Machine" } - {Process process "Process" } - {Thread thread "Thread" } - {Module module "Module" } - {EntryPoint entry_point "Entry Point" } - {DebugInfoPath debug_info_path "Debug Info Path" } - {PendingThreadName pending_thread_name "Pending Thread Name" } - {PendingThreadColor pending_thread_color "Pending Thread Color" } - {Breakpoint breakpoint "Breakpoint" } + {Root root "Root" } + {Machine machine "Machine" } + {Process process "Process" } + {Thread thread "Thread" } + {Module module "Module" } + {EntryPoint entry_point "Entry Point" } + {DebugInfoPath debug_info_path "Debug Info Path" } + {PendingThreadName pending_thread_name "Pending Thread Name" } + {PendingThreadColor pending_thread_color "Pending Thread Color" } + {Breakpoint breakpoint "Breakpoint" } + {AddressRangeAnnotation address_range_annotation "Address Range Annotation" } } @enum CTRL_EntityKind: diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 99cd7cd8..e996b72f 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -1399,6 +1399,15 @@ ctrl_entity_store_apply_events(CTRL_EntityCtxRWStore *store, CTRL_EventList *lis } } }break; + + //- rjf: address range annotations + case CTRL_EventKind_SetVAddrRangeNote: + { + CTRL_Entity *process = ctrl_entity_from_handle(&store->ctx, event->parent); + CTRL_Entity *annotation = ctrl_entity_alloc(store, process, CTRL_EntityKind_AddressRangeAnnotation, Arch_Null, ctrl_handle_zero(), 0); + annotation->vaddr_range = event->vaddr_rng; + ctrl_entity_equip_string(store, annotation, event->string); + }break; } } } @@ -1652,14 +1661,13 @@ ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32 //- rjf: loop: try to look for current results, request if not there, wait if we can, repeat until we can't U64 mem_gen = ctrl_mem_gen(); B32 key_is_stale = 0; - B32 requested = 0; for(;;) { - //- rjf: step 1: [read-only] try to look for current results for key's ID + //- rjf: step 1: [read-only] try to look for current results for key's ID; wait if working & retry B32 id_exists = 0; B32 id_stale = 0; B32 id_working = 0; - OS_MutexScopeR(process_stripe->rw_mutex) + OS_MutexScopeR(process_stripe->rw_mutex) for(;;) { for(CTRL_ProcessMemoryCacheNode *process_n = process_slot->first; process_n != 0; process_n = process_n->next) { @@ -1680,6 +1688,14 @@ ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32 } } end_fast_lookup:; + if(os_now_microseconds() >= endt_us || !id_working) + { + break; + } + else + { + os_condition_variable_wait_rw_r(process_stripe->cv, process_stripe->rw_mutex, endt_us); + } } key_is_stale = id_stale; @@ -1693,7 +1709,9 @@ ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32 //- rjf: step 3: if the ID does not exist in the process' cache, then we // need to build a node for it. if that, or if the ID is stale, then also - // request that that range is streamed. + // request that that range is streamed & wait for its result (for as long + // as we have.) + B32 requested = 0; if(!id_exists || (id_exists && id_stale && !id_working)) { B32 node_needs_stream = 0; @@ -1722,16 +1740,15 @@ ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32 range_n->vaddr_range = vaddr_range; range_n->zero_terminated = zero_terminated; range_n->id = id; - ins_atomic_u64_inc_eval(&range_n->working_count); node_needs_stream = 1; } else { node_needs_stream = (range_n->mem_gen < mem_gen); - if(node_needs_stream) - { - ins_atomic_u64_inc_eval(&range_n->working_count); - } + } + if(node_needs_stream) + { + ins_atomic_u64_inc_eval(&range_n->working_count); } node_working_count = &range_n->working_count; break; @@ -1768,21 +1785,11 @@ ctrl_key_from_process_vaddr_range(CTRL_Handle process, Rng1U64 vaddr_range, B32 } } - //- rjf: step 4: if we have no time to wait, then abort; if we submitted a - // request, but the work is done and we have no results, then abort; - // otherwise, wait on this process' stripe - if(os_now_microseconds() >= endt_us) + //- rjf: step 4: if we didn't request, and if we aren't working, then exit + if(!requested && !id_working) { break; } - else if(!id_working && requested) - { - break; - } - else OS_MutexScopeR(process_stripe->rw_mutex) - { - os_condition_variable_wait_rw_r(process_stripe->cv, process_stripe->rw_mutex, endt_us); - } } if(out_is_stale) { @@ -3399,85 +3406,93 @@ ctrl_call_stack_from_thread(CTRL_Scope *scope, CTRL_EntityCtx *entity_ctx, CTRL_ // B32 can_request = !ins_atomic_u64_eval(&ctrl_state->ctrl_thread_run_state); B32 did_request = 0; - OS_MutexScopeR(stripe->rw_mutex) for(;;) + OS_MutexScopeR(stripe->rw_mutex) { - //////////////////////////// - //- rjf: try to grab cached - // - B32 is_good = 0; - B32 is_stale = 1; - B32 is_working = 0; - CTRL_CallStackCacheNode *node = 0; + CTRL_CallStackCacheNode *taken_node = 0; + for(;;) { - for(CTRL_CallStackCacheNode *n = slot->first; n != 0; n = n->next) + //////////////////////////// + //- rjf: try to grab cached + // + B32 is_good = 0; + B32 is_stale = 1; + B32 is_working = 0; + CTRL_CallStackCacheNode *node = 0; { - if(ctrl_handle_match(n->thread, handle)) + for(CTRL_CallStackCacheNode *n = slot->first; n != 0; n = n->next) { - 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; - ctrl_scope_touch_call_stack_node__stripe_r_guarded(scope, stripe, n); - break; + 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; + } } } - } - - //////////////////////////// - //- 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) + + //////////////////////////// + //- rjf: create node if needed + // + if(!is_good) OS_MutexScopeRWPromote(stripe->rw_mutex) { - if(ctrl_handle_match(n->thread, handle)) + node = 0; + for(CTRL_CallStackCacheNode *n = slot->first; n != 0; n = n->next) { - node = n; - break; + 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 == 0) + + //////////////////////////// + //- rjf: request if needed + // + if(can_request && node != 0 && !is_working && is_stale) { - node = push_array(stripe->arena, CTRL_CallStackCacheNode, 1); - DLLPushBack(slot->first, slot->last, node); - node->thread = thread->handle; + 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) + { + break; + } + + //////////////////////////// + //- rjf: time to wait for new result? -> wait + // + if(did_request && !is_working) + { + break; + } + else if(did_request) + { + os_condition_variable_wait_rw_r(stripe->cv, stripe->rw_mutex, endt_us); } } - - //////////////////////////// - //- rjf: request if needed - // - if(can_request && node != 0 && !is_working && is_stale) + if(taken_node != 0) { - 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) - { - break; - } - - //////////////////////////// - //- rjf: time to wait for new result? -> wait - // - if(did_request && !is_working) - { - break; - } - else if(did_request) - { - os_condition_variable_wait_rw_r(stripe->cv, stripe->rw_mutex, endt_us); + ctrl_scope_touch_call_stack_node__stripe_r_guarded(scope, stripe, taken_node); } } return call_stack; @@ -3974,13 +3989,8 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_ file_header_off + sizeof(COFF_FileHeader) + opt_ext_size); //- rjf: read optional header - U16 optional_magic = 0; - U64 image_base = 0; U64 entry_point = 0; U32 data_dir_count = 0; - U64 virt_section_align = 0; - U64 file_section_align = 0; - Rng1U64 *data_dir_franges = 0; if(opt_ext_size > 0) { // rjf: read magic number @@ -3996,10 +4006,7 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_ { PE_OptionalHeader32 pe_optional = {0}; dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min, &pe_optional); - image_base = pe_optional.image_base; entry_point = pe_optional.entry_point_va; - virt_section_align = pe_optional.section_alignment; - file_section_align = pe_optional.file_alignment; reported_data_dir_offset = sizeof(pe_optional); reported_data_dir_count = pe_optional.data_dir_count; }break; @@ -4007,10 +4014,7 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_ { PE_OptionalHeader32Plus pe_optional = {0}; dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min, &pe_optional); - image_base = pe_optional.image_base; entry_point = pe_optional.entry_point_va; - virt_section_align = pe_optional.section_alignment; - file_section_align = pe_optional.file_alignment; reported_data_dir_offset = sizeof(pe_optional); reported_data_dir_count = pe_optional.data_dir_count; }break; @@ -4660,6 +4664,15 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, out_evt->entity_id = event->code; out_evt->rgba = event->user_data; }break; + case DMN_EventKind_SetVAddrRangeNote: + { + CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); + out_evt->kind = CTRL_EventKind_SetVAddrRangeNote; + out_evt->parent = ctrl_handle_make(CTRL_MachineID_Local, event->process); + out_evt->msg_id = msg->msg_id; + out_evt->vaddr_rng = r1u64(event->address, event->address + event->size); + out_evt->string = event->string; + } case DMN_EventKind_SetBreakpoint: { CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); @@ -6747,7 +6760,7 @@ ASYNC_WORK_DEF(ctrl_mem_stream_work) { if(hs_id_match(range_n->id, key.id)) { - if(!u128_match(u128_zero(), hash)) + if(pre_read_mem_gen == post_read_mem_gen) { range_n->mem_gen = post_read_mem_gen; } @@ -6761,6 +6774,13 @@ ASYNC_WORK_DEF(ctrl_mem_stream_work) //- rjf: broadcast changes os_condition_variable_broadcast(process_stripe->cv); + if(!u128_match(u128_zero(), hash)) + { + if(ctrl_state->wakeup_hook != 0) + { + ctrl_state->wakeup_hook(); + } + } ProfEnd(); ProfEnd(); return 0; @@ -7004,6 +7024,10 @@ ASYNC_WORK_DEF(ctrl_call_stack_build_work) //- rjf: broadcast update os_condition_variable_broadcast(stripe->cv); + if(ctrl_state->wakeup_hook != 0) + { + ctrl_state->wakeup_hook(); + } } scratch_end(scratch); diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index 1eb83b5e..8bac1f4c 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef CTRL_CORE_H @@ -424,6 +424,7 @@ typedef enum CTRL_EventKind CTRL_EventKind_ThreadColor, CTRL_EventKind_SetBreakpoint, CTRL_EventKind_UnsetBreakpoint, + CTRL_EventKind_SetVAddrRangeNote, //- rjf: memory CTRL_EventKind_MemReserve, diff --git a/src/ctrl/ctrl_inc.c b/src/ctrl/ctrl_inc.c index d2dcdb61..45213b22 100644 --- a/src/ctrl/ctrl_inc.c +++ b/src/ctrl/ctrl_inc.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR diff --git a/src/ctrl/ctrl_inc.h b/src/ctrl/ctrl_inc.h index 5a0fcb0d..3226e1b2 100644 --- a/src/ctrl/ctrl_inc.h +++ b/src/ctrl/ctrl_inc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef CTRL_INC_H diff --git a/src/ctrl/generated/ctrl.meta.c b/src/ctrl/generated/ctrl.meta.c index c7d5dd88..09d20976 100644 --- a/src/ctrl/generated/ctrl.meta.c +++ b/src/ctrl/generated/ctrl.meta.c @@ -1,10 +1,10 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE C_LINKAGE_BEGIN -String8 ctrl_entity_kind_code_name_table[11] = +String8 ctrl_entity_kind_code_name_table[12] = { {0}, str8_lit_comp("root"), @@ -17,9 +17,10 @@ str8_lit_comp("debug_info_path"), str8_lit_comp("pending_thread_name"), str8_lit_comp("pending_thread_color"), str8_lit_comp("breakpoint"), +str8_lit_comp("address_range_annotation"), }; -String8 ctrl_entity_kind_display_string_table[11] = +String8 ctrl_entity_kind_display_string_table[12] = { {0}, str8_lit_comp("Root"), @@ -32,6 +33,7 @@ str8_lit_comp("DebugInfoPath"), str8_lit_comp("PendingThreadName"), str8_lit_comp("PendingThreadColor"), str8_lit_comp("Breakpoint"), +str8_lit_comp("AddressRangeAnnotation"), }; U32 ctrl_exception_code_kind_code_table[38] = diff --git a/src/ctrl/generated/ctrl.meta.h b/src/ctrl/generated/ctrl.meta.h index 56f7b8db..5495f320 100644 --- a/src/ctrl/generated/ctrl.meta.h +++ b/src/ctrl/generated/ctrl.meta.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE @@ -19,6 +19,7 @@ CTRL_EntityKind_DebugInfoPath, CTRL_EntityKind_PendingThreadName, CTRL_EntityKind_PendingThreadColor, CTRL_EntityKind_Breakpoint, +CTRL_EntityKind_AddressRangeAnnotation, CTRL_EntityKind_COUNT, } CTRL_EntityKind; @@ -66,8 +67,8 @@ CTRL_ExceptionCodeKind_COUNT, } CTRL_ExceptionCodeKind; C_LINKAGE_BEGIN -extern String8 ctrl_entity_kind_code_name_table[11]; -extern String8 ctrl_entity_kind_display_string_table[11]; +extern String8 ctrl_entity_kind_code_name_table[12]; +extern String8 ctrl_entity_kind_display_string_table[12]; extern U32 ctrl_exception_code_kind_code_table[38]; extern String8 ctrl_exception_code_kind_display_string_table[38]; extern String8 ctrl_exception_code_kind_lowercase_code_string_table[38]; diff --git a/src/dasm_cache/dasm_cache.c b/src/dasm_cache/dasm_cache.c index 26d6df9f..c4ac8bd2 100644 --- a/src/dasm_cache/dasm_cache.c +++ b/src/dasm_cache/dasm_cache.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR diff --git a/src/dasm_cache/dasm_cache.h b/src/dasm_cache/dasm_cache.h index 25a222fe..521e359a 100644 --- a/src/dasm_cache/dasm_cache.h +++ b/src/dasm_cache/dasm_cache.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DASM_CACHE_H diff --git a/src/dbg_engine/dbg_engine.mdesk b/src/dbg_engine/dbg_engine.mdesk index cbfe3352..a92649e2 100644 --- a/src/dbg_engine/dbg_engine.mdesk +++ b/src/dbg_engine/dbg_engine.mdesk @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/dbg_engine/dbg_engine_core.c b/src/dbg_engine/dbg_engine_core.c index 69c5432d..5339b8dd 100644 --- a/src/dbg_engine/dbg_engine_core.c +++ b/src/dbg_engine/dbg_engine_core.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR @@ -378,10 +378,12 @@ d_trap_net_from_thread__step_over_line(Arena *arena, CTRL_Entity *thread) // rjf: line vaddr range => line's machine code String8 machine_code = {0}; + B32 good_machine_code = 0; if(good_line_info) { CTRL_ProcessMemorySlice machine_code_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, line_vaddr_rng, os_now_microseconds()+50000); machine_code = machine_code_slice.data; + good_machine_code = (machine_code.size == dim_1u64(line_vaddr_rng) && !machine_code_slice.any_byte_bad); LogInfoNamedBlockF("machine_code_slice") { log_infof("stale: %i\n", machine_code_slice.stale); @@ -402,7 +404,7 @@ d_trap_net_from_thread__step_over_line(Arena *arena, CTRL_Entity *thread) // rjf: machine code => ctrl flow analysis DASM_CtrlFlowInfo ctrl_flow_info = {0}; - if(good_line_info) + if(good_machine_code) { ctrl_flow_info = dasm_ctrl_flow_info_from_arch_vaddr_code(scratch.arena, DASM_InstFlag_Call| @@ -423,7 +425,7 @@ d_trap_net_from_thread__step_over_line(Arena *arena, CTRL_Entity *thread) } // rjf: push traps for all exit points - if(good_line_info) for(DASM_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next) + if(good_machine_code) for(DASM_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next) { DASM_CtrlFlowPoint *point = &n->v; CTRL_TrapFlags flags = 0; @@ -534,15 +536,17 @@ d_trap_net_from_thread__step_into_line(Arena *arena, CTRL_Entity *thread) // rjf: line vaddr range => line's machine code String8 machine_code = {0}; + B32 good_machine_code = 0; if(good_line_info) { CTRL_ProcessMemorySlice machine_code_slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, line_vaddr_rng, os_now_microseconds()+5000); machine_code = machine_code_slice.data; + good_machine_code = (machine_code.size == dim_1u64(line_vaddr_rng) && !machine_code_slice.any_byte_bad); } // rjf: machine code => ctrl flow analysis DASM_CtrlFlowInfo ctrl_flow_info = {0}; - if(good_line_info) + if(good_machine_code) { ctrl_flow_info = dasm_ctrl_flow_info_from_arch_vaddr_code(scratch.arena, DASM_InstFlag_Call| @@ -557,7 +561,7 @@ d_trap_net_from_thread__step_into_line(Arena *arena, CTRL_Entity *thread) // rjf: determine last DASM_CtrlFlowPoint *last_call_point = 0; - if(good_line_info) for(DASM_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next) + if(good_machine_code) for(DASM_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next) { if(n->v.inst_flags & DASM_InstFlag_Call) { @@ -566,7 +570,7 @@ d_trap_net_from_thread__step_into_line(Arena *arena, CTRL_Entity *thread) } // rjf: push traps for all exit points - if(good_line_info) for(DASM_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next) + if(good_machine_code) for(DASM_CtrlFlowPointNode *n = ctrl_flow_info.exit_points.first; n != 0; n = n->next) { DASM_CtrlFlowPoint *point = &n->v; CTRL_TrapFlags flags = 0; @@ -836,7 +840,7 @@ d_lines_array_from_dbgi_key_file_path_line_range(Arena *arena, DI_Key dbgi_key, override_n = override_n->next) { String8 file_path = override_n->string; - String8 file_path_normalized = lower_from_str8(scratch.arena, file_path); + 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); diff --git a/src/dbg_engine/dbg_engine_core.h b/src/dbg_engine/dbg_engine_core.h index 042ffd3a..e6e535db 100644 --- a/src/dbg_engine/dbg_engine_core.h +++ b/src/dbg_engine/dbg_engine_core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DBG_ENGINE_CORE_H diff --git a/src/dbg_engine/dbg_engine_inc.c b/src/dbg_engine/dbg_engine_inc.c index 81f3a28d..b3d11c5b 100644 --- a/src/dbg_engine/dbg_engine_inc.c +++ b/src/dbg_engine/dbg_engine_inc.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "dbg_engine_core.c" diff --git a/src/dbg_engine/dbg_engine_inc.h b/src/dbg_engine/dbg_engine_inc.h index 96ca410a..5dcf2fb4 100644 --- a/src/dbg_engine/dbg_engine_inc.h +++ b/src/dbg_engine/dbg_engine_inc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DBG_ENGINE_INC_H diff --git a/src/dbg_engine/generated/dbg_engine.meta.c b/src/dbg_engine/generated/dbg_engine.meta.c index 3d32a4c2..437ae10e 100644 --- a/src/dbg_engine/generated/dbg_engine.meta.c +++ b/src/dbg_engine/generated/dbg_engine.meta.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/dbg_engine/generated/dbg_engine.meta.h b/src/dbg_engine/generated/dbg_engine.meta.h index 8451a246..d91994c8 100644 --- a/src/dbg_engine/generated/dbg_engine.meta.h +++ b/src/dbg_engine/generated/dbg_engine.meta.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/dbgi/dbgi.c b/src/dbgi/dbgi.c index 96f0b480..be88fc8a 100644 --- a/src/dbgi/dbgi.c +++ b/src/dbgi/dbgi.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR @@ -1026,15 +1026,16 @@ ASYNC_WORK_DEF(di_parse_work) params.inherit_env = 1; params.consoleless = 1; str8_list_pushf(scratch.arena, ¶ms.cmd_line, "raddbg"); - str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--convert"); + str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--bin"); str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--quiet"); if(should_compress) { str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--compress"); } // str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--capture"); - str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--pdb:%S", og_path); + str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--rdi"); str8_list_pushf(scratch.arena, ¶ms.cmd_line, "--out:%S", rdi_path); + str8_list_pushf(scratch.arena, ¶ms.cmd_line, "%S", og_path); process = os_process_launch(¶ms); } diff --git a/src/dbgi/dbgi.h b/src/dbgi/dbgi.h index ca8b8e77..555e5e03 100644 --- a/src/dbgi/dbgi.h +++ b/src/dbgi/dbgi.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DBGI_H diff --git a/src/demon/demon_core.c b/src/demon/demon_core.c index 85f09574..75cca59e 100644 --- a/src/demon/demon_core.c +++ b/src/demon/demon_core.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -158,31 +158,25 @@ dmn_rsp_from_thread(DMN_Handle thread) } //////////////////////////////// -//~ Memory Helpers +//~ rjf: Process Reading Helper Functions (Helpers, Implemented Once) internal String8 dmn_process_read_cstring(Arena *arena, DMN_Handle process, U64 addr) { Temp scratch = scratch_begin(&arena, 1); - String8List block_list = {0}; - for(U64 cursor = addr, stride = 256; ; cursor += stride) { U8 *raw_block = push_array_no_zero(scratch.arena, U8, stride); U64 read_size = dmn_process_read(process, r1u64(cursor, cursor + stride), raw_block); String8 block = str8_cstring_capped(raw_block, raw_block + read_size); - str8_list_push(scratch.arena, &block_list, block); - if(read_size != stride || (block.size+1 <= read_size && block.str[block.size] == 0)) { break; } } - String8 result = str8_list_join(arena, &block_list, 0); - scratch_end(scratch); return result; } diff --git a/src/demon/demon_core.h b/src/demon/demon_core.h index 94f8d8c3..7904fbf1 100644 --- a/src/demon/demon_core.h +++ b/src/demon/demon_core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DEMON_CORE_H @@ -190,6 +190,11 @@ internal DMN_Event *dmn_event_list_push(Arena *arena, DMN_EventList *list); internal U64 dmn_rip_from_thread(DMN_Handle thread); internal U64 dmn_rsp_from_thread(DMN_Handle thread); +//////////////////////////////// +//~ rjf: Process Reading Helper Functions (Helpers, Implemented Once) + +internal String8 dmn_process_read_cstring(Arena *arena, DMN_Handle process, U64 addr); + //////////////////////////////// //~ rjf: @dmn_os_hooks Main Layer Initialization (Implemented Per-OS) @@ -236,7 +241,6 @@ internal U64 dmn_process_read(DMN_Handle process, Rng1U64 range, void *dst); internal B32 dmn_process_write(DMN_Handle process, Rng1U64 range, void *src); #define dmn_process_read_struct(process, vaddr, ptr) dmn_process_read((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr) #define dmn_process_write_struct(process, vaddr, ptr) dmn_process_write((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr) -internal String8 dmn_process_read_cstring(Arena *arena, DMN_Handle process, U64 addr); //- rjf: threads internal Arch dmn_arch_from_thread(DMN_Handle handle); diff --git a/src/demon/demon_core.mdesk b/src/demon/demon_core.mdesk index 3c9a367e..78e49001 100644 --- a/src/demon/demon_core.mdesk +++ b/src/demon/demon_core.mdesk @@ -24,6 +24,7 @@ DMN_EventKindTable: {SetThreadColor} {SetBreakpoint} {UnsetBreakpoint} + {SetVAddrRangeNote} } @table(name) diff --git a/src/demon/demon_inc.c b/src/demon/demon_inc.c index 0f0507c2..d733b612 100644 --- a/src/demon/demon_inc.c +++ b/src/demon/demon_inc.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "demon/demon_core.c" diff --git a/src/demon/demon_inc.h b/src/demon/demon_inc.h index 8bd7b092..eec32998 100644 --- a/src/demon/demon_inc.h +++ b/src/demon/demon_inc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DEMON_INC_H diff --git a/src/demon/generated/demon.meta.c b/src/demon/generated/demon.meta.c index 47406944..cf282f4a 100644 --- a/src/demon/generated/demon.meta.c +++ b/src/demon/generated/demon.meta.c @@ -1,10 +1,10 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE C_LINKAGE_BEGIN -String8 dmn_event_kind_string_table[20] = +String8 dmn_event_kind_string_table[21] = { str8_lit_comp("Null"), str8_lit_comp("Error"), @@ -26,6 +26,7 @@ str8_lit_comp("SetThreadName"), str8_lit_comp("SetThreadColor"), str8_lit_comp("SetBreakpoint"), str8_lit_comp("UnsetBreakpoint"), +str8_lit_comp("SetVAddrRangeNote"), }; String8 dmn_exception_kind_string_table[5] = diff --git a/src/demon/generated/demon.meta.h b/src/demon/generated/demon.meta.h index 4a8b5b80..7e1513e0 100644 --- a/src/demon/generated/demon.meta.h +++ b/src/demon/generated/demon.meta.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE @@ -28,6 +28,7 @@ DMN_EventKind_SetThreadName, DMN_EventKind_SetThreadColor, DMN_EventKind_SetBreakpoint, DMN_EventKind_UnsetBreakpoint, +DMN_EventKind_SetVAddrRangeNote, DMN_EventKind_COUNT, } DMN_EventKind; @@ -61,7 +62,7 @@ DMN_ExceptionKind_COUNT, } DMN_ExceptionKind; C_LINKAGE_BEGIN -extern String8 dmn_event_kind_string_table[20]; +extern String8 dmn_event_kind_string_table[21]; extern String8 dmn_exception_kind_string_table[5]; C_LINKAGE_END diff --git a/src/demon/linux/demon_core_linux.c b/src/demon/linux/demon_core_linux.c index ffa705af..c6edab7f 100644 --- a/src/demon/linux/demon_core_linux.c +++ b/src/demon/linux/demon_core_linux.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/demon/linux/demon_core_linux.h b/src/demon/linux/demon_core_linux.h index a0bae69a..e11072f7 100644 --- a/src/demon/linux/demon_core_linux.h +++ b/src/demon/linux/demon_core_linux.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DEMON_CORE_LINUX_H diff --git a/src/demon/linux/demon_os_linux.c b/src/demon/linux/demon_os_linux.c index b0b3c972..39c1aa1f 100644 --- a/src/demon/linux/demon_os_linux.c +++ b/src/demon/linux/demon_os_linux.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) // TODO(allen): run controls: ignore_previous_exception diff --git a/src/demon/linux/demon_os_linux.h b/src/demon/linux/demon_os_linux.h index 915e29de..ae737f75 100644 --- a/src/demon/linux/demon_os_linux.h +++ b/src/demon/linux/demon_os_linux.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DEMON_OS_LINUX_H diff --git a/src/demon/win32/demon_core_win32.c b/src/demon/win32/demon_core_win32.c index d9fe31df..1ded7853 100644 --- a/src/demon/win32/demon_core_win32.c +++ b/src/demon/win32/demon_core_win32.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -2560,6 +2560,21 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) if(exec) { e->flags |= DMN_TrapFlag_BreakOnExecute; } }break; + //- rjf: fill set-vaddr-range-note info + case DMN_W32_EXCEPTION_RADDBG_SET_VADDR_RANGE_NOTE: + { + U64 vaddr = exception->ExceptionInformation[0]; + U64 size = exception->ExceptionInformation[1]; + U64 name_vaddr = exception->ExceptionInformation[2]; + U64 name_size = exception->ExceptionInformation[3]; + U8 *name_buffer = push_array(arena, U8, name_size); + dmn_w32_process_read(process->handle, r1u64(name_vaddr, name_vaddr+name_size), name_buffer), + e->kind = DMN_EventKind_SetVAddrRangeNote; + e->address = vaddr; + e->size = size; + e->string = str8(name_buffer, name_size); + }break; + //- rjf: unhandled exception case default: { diff --git a/src/demon/win32/demon_core_win32.h b/src/demon/win32/demon_core_win32.h index 05483e26..bb3fbfbe 100644 --- a/src/demon/win32/demon_core_win32.h +++ b/src/demon/win32/demon_core_win32.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DEMON_CORE_WIN32_H @@ -58,6 +58,7 @@ #define DMN_w32_EXCEPTION_CLR 0xE0434352u #define DMN_W32_EXCEPTION_RADDBG_SET_THREAD_COLOR 0x00524144u #define DMN_W32_EXCEPTION_RADDBG_SET_BREAKPOINT 0x00524145u +#define DMN_W32_EXCEPTION_RADDBG_SET_VADDR_RANGE_NOTE 0x00524156u //////////////////////////////// //~ rjf: Win32 Register Codes diff --git a/src/draw/draw.c b/src/draw/draw.c index db34c9b0..5c31e93e 100644 --- a/src/draw/draw.c +++ b/src/draw/draw.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/draw/draw.h b/src/draw/draw.h index f338e0fd..acc7ce64 100644 --- a/src/draw/draw.h +++ b/src/draw/draw.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DRAW_H diff --git a/src/draw/draw.mdesk b/src/draw/draw.mdesk index 981b3bb2..d412ac7c 100644 --- a/src/draw/draw.mdesk +++ b/src/draw/draw.mdesk @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) @table(name, name_lower, type, default_init) diff --git a/src/draw/generated/draw.meta.c b/src/draw/generated/draw.meta.c index aa5e65c0..2efd51aa 100644 --- a/src/draw/generated/draw.meta.c +++ b/src/draw/generated/draw.meta.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/draw/generated/draw.meta.h b/src/draw/generated/draw.meta.h index 350048e1..58db1f4e 100644 --- a/src/draw/generated/draw.meta.h +++ b/src/draw/generated/draw.meta.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/dwarf/dwarf.c b/src/dwarf/dwarf.c index 05f72bc0..f0877ff8 100644 --- a/src/dwarf/dwarf.c +++ b/src/dwarf/dwarf.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U64 @@ -49,10 +49,10 @@ internal U64 dw_reg_size_from_code(Arch arch, DW_Reg reg_code) { switch (arch) { - case Arch_Null: break; - case Arch_x86: return dw_reg_size_from_code_x86(reg_code); - case Arch_x64: return dw_reg_size_from_code_x64(reg_code); - default: NotImplemented; break; + case Arch_Null: break; + case Arch_x86: return dw_reg_size_from_code_x86(reg_code); + case Arch_x64: return dw_reg_size_from_code_x64(reg_code); + default: NotImplemented; break; } return 0; } @@ -61,10 +61,10 @@ internal U64 dw_reg_pos_from_code(Arch arch, DW_Reg reg_code) { switch (arch) { - case Arch_Null: break; - case Arch_x86: return dw_reg_pos_from_code_x86(reg_code); - case Arch_x64: return dw_reg_pos_from_code_x64(reg_code); - default: NotImplemented; break; + case Arch_Null: break; + case Arch_x86: return dw_reg_pos_from_code_x86(reg_code); + case Arch_x64: return dw_reg_pos_from_code_x64(reg_code); + default: NotImplemented; break; } return max_U64; } @@ -73,9 +73,9 @@ internal DW_AttribClass dw_attrib_class_from_attrib_kind_v2(DW_AttribKind k) { switch (k) { - #define X(_N,_C) case DW_Attrib_##_N: return _C; +#define X(_N,_C) case DW_Attrib_##_N: return _C; DW_AttribKind_ClassFlags_V2_XList(X) - #undef X +#undef X } return DW_AttribClass_Null; } @@ -84,9 +84,9 @@ internal DW_AttribClass dw_attrib_class_from_attrib_kind_v3(DW_AttribKind k) { switch (k) { - #define X(_N,_C) case DW_Attrib_##_N: return _C; +#define X(_N,_C) case DW_Attrib_##_N: return _C; DW_AttribKind_ClassFlags_V3_XList(X) - #undef X +#undef X } return DW_AttribClass_Null; } @@ -95,9 +95,9 @@ internal DW_AttribClass dw_attrib_class_from_attrib_kind_v4(DW_AttribKind k) { switch (k) { - #define X(_N,_C) case DW_Attrib_##_N: return _C; +#define X(_N,_C) case DW_Attrib_##_N: return _C; DW_AttribKind_ClassFlags_V4_XList(X) - #undef X +#undef X } return DW_AttribClass_Null; } @@ -106,9 +106,9 @@ internal DW_AttribClass dw_attrib_class_from_attrib_kind_v5(DW_AttribKind k) { switch (k) { - #define X(_N,_C) case DW_Attrib_##_N: return _C; +#define X(_N,_C) case DW_Attrib_##_N: return _C; DW_AttribKind_ClassFlags_V5_XList(X) - #undef X +#undef X } return DW_AttribClass_Null; } @@ -117,9 +117,9 @@ internal DW_AttribClass dw_attrib_class_from_attrib_kind_gnu(DW_AttribKind k) { switch (k) { - #define X(_N,_C) case DW_Attrib_##_N: return _C; +#define X(_N,_C) case DW_Attrib_##_N: return _C; DW_AttribKind_ClassFlags_GNU_XList(X) - #undef X +#undef X } return DW_AttribClass_Null; } @@ -128,9 +128,9 @@ internal DW_AttribClass dw_attrib_class_from_attrib_kind_llvm(DW_AttribKind k) { switch (k) { - #define X(_N,_C) case DW_Attrib_##_N: return _C; +#define X(_N,_C) case DW_Attrib_##_N: return _C; DW_AttribKind_ClassFlags_LLVM_XList(X) - #undef X +#undef X } return DW_AttribClass_Null; } @@ -139,9 +139,9 @@ internal DW_AttribClass dw_attrib_class_from_attrib_kind_apple(DW_AttribKind k) { switch (k) { - #define X(_N,_C) case DW_Attrib_##_N: return _C; +#define X(_N,_C) case DW_Attrib_##_N: return _C; DW_AttribKind_ClassFlags_APPLE_XList(X) - #undef X +#undef X } return DW_AttribClass_Null; } @@ -150,9 +150,9 @@ internal DW_AttribClass dw_attrib_class_from_attrib_kind_mips(DW_AttribKind k) { switch (k) { - #define X(_N,_C) case DW_Attrib_##_N: return _C; +#define X(_N,_C) case DW_Attrib_##_N: return _C; DW_AttribKind_ClassFlags_MIPS_XList(X) - #undef X +#undef X } return DW_AttribClass_Null; } @@ -161,7 +161,7 @@ internal DW_AttribClass dw_attrib_class_from_attrib_kind(DW_Version ver, DW_Ext ext, DW_AttribKind k) { DW_AttribClass result = DW_AttribClass_Null; - + while (ext) { U64 z = 64-clz64(ext); if (z == 0) { @@ -169,7 +169,7 @@ dw_attrib_class_from_attrib_kind(DW_Version ver, DW_Ext ext, DW_AttribKind k) } U64 flag = 1 << (z-1); ext &= ~flag; - + switch (flag) { case DW_Ext_Null: break; case DW_Ext_GNU: result = dw_attrib_class_from_attrib_kind_gnu(k); break; @@ -178,12 +178,12 @@ dw_attrib_class_from_attrib_kind(DW_Version ver, DW_Ext ext, DW_AttribKind k) case DW_Ext_MIPS: result = dw_attrib_class_from_attrib_kind_mips(k); break; default: InvalidPath; break; } - + if (result != DW_AttribClass_Null) { break; } } - + if (result == DW_AttribClass_Null) { switch (ver) { case DW_Version_Null: break; @@ -195,19 +195,19 @@ dw_attrib_class_from_attrib_kind(DW_Version ver, DW_Ext ext, DW_AttribKind k) default: InvalidPath; break; } } - + return result; } internal DW_AttribClass dw_attrib_class_from_form_kind(DW_Version ver, DW_FormKind k) { - #define X(_N,_C) case DW_Form_##_N: return _C; - +#define X(_N,_C) case DW_Form_##_N: return _C; + switch (k) { DW_Form_AttribClass_GNU_XList(X) } - + switch (ver) { case DW_Version_5: { switch (k) { @@ -233,8 +233,8 @@ dw_attrib_class_from_form_kind(DW_Version ver, DW_FormKind k) } break; case DW_Version_Null: break; } - #undef X - +#undef X + return DW_AttribClass_Null; } @@ -250,9 +250,9 @@ internal String8 dw_name_string_from_section_kind(DW_SectionKind k) { switch (k) { - #define X(_N,_L,_M,_D) case DW_Section_##_N: return str8_lit(_L); +#define X(_N,_L,_M,_D) case DW_Section_##_N: return str8_lit(_L); DW_SectionKind_XList(X) - #undef X +#undef X } return str8_zero(); } @@ -261,9 +261,9 @@ internal String8 dw_mach_name_string_from_section_kind(DW_SectionKind k) { switch (k) { - #define X(_N,_L,_M,_D) case DW_Section_##_N: return str8_lit(_M); +#define X(_N,_L,_M,_D) case DW_Section_##_N: return str8_lit(_M); DW_SectionKind_XList(X) - #undef X +#undef X } return str8_zero(); } @@ -272,9 +272,9 @@ internal String8 dw_dwo_name_string_from_section_kind(DW_SectionKind k) { switch (k) { - #define X(_N,_L,_M,_D) case DW_Section_##_N: return str8_lit(_D); +#define X(_N,_L,_M,_D) case DW_Section_##_N: return str8_lit(_D); DW_SectionKind_XList(X) - #undef X +#undef X } return str8_zero(); } @@ -301,10 +301,10 @@ 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 form_class = dw_attrib_class_from_form_kind(ver, form_kind); - + if(relaxed) { if(attrib_class == DW_AttribClass_Null || form_class == DW_AttribClass_Null) @@ -313,12 +313,12 @@ dw_pick_attrib_value_class(DW_Version ver, DW_Ext ext, B32 relaxed, DW_AttribKin form_class = dw_attrib_class_from_form_kind(DW_Version_Last, form_kind); } } - + DW_AttribClass result = DW_AttribClass_Null; if(attrib_class != DW_AttribClass_Null && form_class != DW_AttribClass_Null) { result = DW_AttribClass_Undefined; - + for(U32 i = 0; i < 32; ++i) { U32 n = 1u << i; @@ -329,7 +329,7 @@ dw_pick_attrib_value_class(DW_Version ver, DW_Ext ext, B32 relaxed, DW_AttribKin } } } - + return result; } @@ -338,50 +338,50 @@ dw_pick_default_lower_bound(DW_Language lang) { U64 lower_bound = max_U64; switch (lang) { - case DW_Language_Null: break; - case DW_Language_C89: - case DW_Language_C: - case DW_Language_CPlusPlus: - case DW_Language_C99: - case DW_Language_CPlusPlus03: - case DW_Language_CPlusPlus11: - case DW_Language_C11: - case DW_Language_CPlusPlus14: - case DW_Language_Java: - case DW_Language_ObjC: - case DW_Language_ObjCPlusPlus: - case DW_Language_UPC: - case DW_Language_D: - case DW_Language_Python: - case DW_Language_OpenCL: - case DW_Language_Go: - case DW_Language_Haskell: - case DW_Language_OCaml: - case DW_Language_Rust: - case DW_Language_Swift: - case DW_Language_Dylan: - case DW_Language_RenderScript: - case DW_Language_BLISS: - lower_bound = 0; - break; - case DW_Language_Ada83: - case DW_Language_Cobol74: - case DW_Language_Cobol85: - case DW_Language_Fortran77: - case DW_Language_Fortran90: - case DW_Language_Pascal83: - case DW_Language_Modula2: - case DW_Language_Ada95: - case DW_Language_Fortran95: - case DW_Language_PLI: - case DW_Language_Modula3: - case DW_Language_Julia: - case DW_Language_Fortran03: - case DW_Language_Fortran08: - lower_bound = 1; - default: - NotImplemented; - break; + case DW_Language_Null: break; + case DW_Language_C89: + case DW_Language_C: + case DW_Language_CPlusPlus: + case DW_Language_C99: + case DW_Language_CPlusPlus03: + case DW_Language_CPlusPlus11: + case DW_Language_C11: + case DW_Language_CPlusPlus14: + case DW_Language_Java: + case DW_Language_ObjC: + case DW_Language_ObjCPlusPlus: + case DW_Language_UPC: + case DW_Language_D: + case DW_Language_Python: + case DW_Language_OpenCL: + case DW_Language_Go: + case DW_Language_Haskell: + case DW_Language_OCaml: + case DW_Language_Rust: + case DW_Language_Swift: + case DW_Language_Dylan: + case DW_Language_RenderScript: + case DW_Language_BLISS: + lower_bound = 0; + break; + case DW_Language_Ada83: + case DW_Language_Cobol74: + case DW_Language_Cobol85: + case DW_Language_Fortran77: + case DW_Language_Fortran90: + case DW_Language_Pascal83: + case DW_Language_Modula2: + case DW_Language_Ada95: + case DW_Language_Fortran95: + case DW_Language_PLI: + case DW_Language_Modula3: + case DW_Language_Julia: + case DW_Language_Fortran03: + case DW_Language_Fortran08: + lower_bound = 1; + default: + NotImplemented; + break; } return lower_bound; } diff --git a/src/dwarf/dwarf.h b/src/dwarf/dwarf.h index 4c7132a4..d56adfdb 100644 --- a/src/dwarf/dwarf.h +++ b/src/dwarf/dwarf.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_H @@ -20,12 +20,12 @@ typedef U64 DW_Ext; typedef enum DW_ExtEnum { DW_Ext_Null, - + DW_Ext_GNU = (1 << 0), DW_Ext_LLVM = (1 << 1), DW_Ext_APPLE = (1 << 2), DW_Ext_MIPS = (1 << 3), - + DW_Ext_All = DW_Ext_GNU|DW_Ext_LLVM|DW_Ext_APPLE|DW_Ext_MIPS, } DW_ExtEnum; @@ -40,24 +40,24 @@ typedef enum DW_Format #define DW_SentinelFromSize(address_size) ((address_size) == 4 ? max_U32 : (address_size) == 8 ? max_U64 : 0) #define DW_SectionKind_XList(X )\ - X(Null, "", "", "" )\ - X(Abbrev, ".debug_abbrev", "__debug_abbrev", ".debug_abbrev.dwo" )\ - X(ARanges, ".debug_aranges", "__debug_aranges", ".debug_aranges.dwo" )\ - X(Frame, ".debug_frame", "__debug_frame", ".debug_frame.dwo" )\ - X(Info, ".debug_info", "__debug_info", ".debug_info.dwo" )\ - X(Line, ".debug_line", "__debug_line", ".debug_line.dwo" )\ - X(Loc, ".debug_loc", "__debug_loc", ".debug_loc.dwo" )\ - X(MacInfo, ".debug_macinfo", "__debug_macinfo", ".debug_macinfo.dwo" )\ - X(PubNames, ".debug_pubnames", "__debug_pubnames", ".debug_pubnames.dwo" )\ - X(PubTypes, ".debug_pubtypes", "__debug_pubtypes", ".debug_pubtypes.dwo" )\ - X(Ranges, ".debug_ranges", "__debug_ranges", ".debug_ranges.dwo" )\ - X(Str, ".debug_str", "__debug_str", ".debug_str.dwo" )\ - X(Addr, ".debug_addr", "__debug_addr", ".debug_addr.dwo" )\ - X(LocLists, ".debug_loclists", "__debug_loclists", ".debug_loclists.dwo" )\ - X(RngLists, ".debug_rnglists", "__debug_rnglists", ".debug_rnglists.dwo" )\ - X(StrOffsets, ".debug_str_offsets", "__debug_str_offsets", ".debug_str_offsets.dwo")\ - X(LineStr, ".debug_line_str", "__debug_line_str", ".debug_line_str.dwo" )\ - X(Names, ".debug_names", "__debug_names", ".debug_names.dwo" ) +X(Null, "", "", "" )\ +X(Abbrev, ".debug_abbrev", "__debug_abbrev", ".debug_abbrev.dwo" )\ +X(ARanges, ".debug_aranges", "__debug_aranges", ".debug_aranges.dwo" )\ +X(Frame, ".debug_frame", "__debug_frame", ".debug_frame.dwo" )\ +X(Info, ".debug_info", "__debug_info", ".debug_info.dwo" )\ +X(Line, ".debug_line", "__debug_line", ".debug_line.dwo" )\ +X(Loc, ".debug_loc", "__debug_loc", ".debug_loc.dwo" )\ +X(MacInfo, ".debug_macinfo", "__debug_macinfo", ".debug_macinfo.dwo" )\ +X(PubNames, ".debug_pubnames", "__debug_pubnames", ".debug_pubnames.dwo" )\ +X(PubTypes, ".debug_pubtypes", "__debug_pubtypes", ".debug_pubtypes.dwo" )\ +X(Ranges, ".debug_ranges", "__debug_ranges", ".debug_ranges.dwo" )\ +X(Str, ".debug_str", "__debug_str", ".debug_str.dwo" )\ +X(Addr, ".debug_addr", "__debug_addr", ".debug_addr.dwo" )\ +X(LocLists, ".debug_loclists", "__debug_loclists", ".debug_loclists.dwo" )\ +X(RngLists, ".debug_rnglists", "__debug_rnglists", ".debug_rnglists.dwo" )\ +X(StrOffsets, ".debug_str_offsets", "__debug_str_offsets", ".debug_str_offsets.dwo")\ +X(LineStr, ".debug_line_str", "__debug_line_str", ".debug_line_str.dwo" )\ +X(Names, ".debug_names", "__debug_names", ".debug_names.dwo" ) typedef U64 DW_SectionKind; typedef enum DW_SectionKindEnum @@ -69,48 +69,48 @@ typedef enum DW_SectionKindEnum } DW_SectionKindEnum; #define DW_Language_XList(X) \ - X(Null, 0x00) \ - X(C89, 0x01) \ - X(C, 0x02) \ - X(Ada83, 0x03) \ - X(CPlusPlus, 0x04) \ - X(Cobol74, 0x05) \ - X(Cobol85, 0x06) \ - X(Fortran77, 0x07) \ - X(Fortran90, 0x08) \ - X(Pascal83, 0x09) \ - X(Modula2, 0x0A) \ - X(Java, 0x0B) \ - X(C99, 0x0C) \ - X(Ada95, 0x0D) \ - X(Fortran95, 0x0E) \ - X(PLI, 0x0F) \ - X(ObjC, 0x10) \ - X(ObjCPlusPlus, 0x11) \ - X(UPC, 0x12) \ - X(D, 0x13) \ - X(Python, 0x14) \ - X(OpenCL, 0x15) \ - X(Go, 0x16) \ - X(Modula3, 0x17) \ - X(Haskell, 0x18) \ - X(CPlusPlus03, 0x19) \ - X(CPlusPlus11, 0x1a) \ - X(OCaml, 0x1b) \ - X(Rust, 0x1c) \ - X(C11, 0x1d) \ - X(Swift, 0x1e) \ - X(Julia, 0x1f) \ - X(Dylan, 0x20) \ - X(CPlusPlus14, 0x21) \ - X(Fortran03, 0x22) \ - X(Fortran08, 0x23) \ - X(RenderScript, 0x24) \ - X(BLISS, 0x25) \ - X(MipsAssembler, 0x8001) \ - X(GoogleRenderScript, 0x8E57) \ - X(SunAssembler, 0x9001) \ - X(BorlandDelphi, 0xB000) +X(Null, 0x00) \ +X(C89, 0x01) \ +X(C, 0x02) \ +X(Ada83, 0x03) \ +X(CPlusPlus, 0x04) \ +X(Cobol74, 0x05) \ +X(Cobol85, 0x06) \ +X(Fortran77, 0x07) \ +X(Fortran90, 0x08) \ +X(Pascal83, 0x09) \ +X(Modula2, 0x0A) \ +X(Java, 0x0B) \ +X(C99, 0x0C) \ +X(Ada95, 0x0D) \ +X(Fortran95, 0x0E) \ +X(PLI, 0x0F) \ +X(ObjC, 0x10) \ +X(ObjCPlusPlus, 0x11) \ +X(UPC, 0x12) \ +X(D, 0x13) \ +X(Python, 0x14) \ +X(OpenCL, 0x15) \ +X(Go, 0x16) \ +X(Modula3, 0x17) \ +X(Haskell, 0x18) \ +X(CPlusPlus03, 0x19) \ +X(CPlusPlus11, 0x1a) \ +X(OCaml, 0x1b) \ +X(Rust, 0x1c) \ +X(C11, 0x1d) \ +X(Swift, 0x1e) \ +X(Julia, 0x1f) \ +X(Dylan, 0x20) \ +X(CPlusPlus14, 0x21) \ +X(Fortran03, 0x22) \ +X(Fortran08, 0x23) \ +X(RenderScript, 0x24) \ +X(BLISS, 0x25) \ +X(MipsAssembler, 0x8001) \ +X(GoogleRenderScript, 0x8E57) \ +X(SunAssembler, 0x9001) \ +X(BorlandDelphi, 0xB000) typedef U32 DW_Language; typedef enum DW_LanguageEnum @@ -123,10 +123,10 @@ typedef enum DW_LanguageEnum } DW_LanguageEnum; #define DW_Inl_XList(X) \ - X(NotInlined, 0) \ - X(Inlined, 1) \ - X(DeclaredNotInlined, 2) \ - X(DeclaredInlined, 3) +X(NotInlined, 0) \ +X(Inlined, 1) \ +X(DeclaredNotInlined, 2) \ +X(DeclaredInlined, 3) typedef U32 DW_InlKind; typedef enum DW_InlKindEnum @@ -137,19 +137,19 @@ typedef enum DW_InlKindEnum } DW_InlKindEnum; #define DW_StdOpcode_XList(X) \ - X(ExtendedOpcode, 0x00) \ - X(Copy, 0x01) \ - X(AdvancePc, 0x02) \ - X(AdvanceLine, 0x03) \ - X(SetFile, 0x04) \ - X(SetColumn, 0x05) \ - X(NegateStmt, 0x06) \ - X(SetBasicBlock, 0x07) \ - X(ConstAddPc, 0x08) \ - X(FixedAdvancePc, 0x09) \ - X(SetPrologueEnd, 0x0A) \ - X(SetEpilogueBegin, 0x0B) \ - X(SetIsa, 0x0C) \ +X(ExtendedOpcode, 0x00) \ +X(Copy, 0x01) \ +X(AdvancePc, 0x02) \ +X(AdvanceLine, 0x03) \ +X(SetFile, 0x04) \ +X(SetColumn, 0x05) \ +X(NegateStmt, 0x06) \ +X(SetBasicBlock, 0x07) \ +X(ConstAddPc, 0x08) \ +X(FixedAdvancePc, 0x09) \ +X(SetPrologueEnd, 0x0A) \ +X(SetEpilogueBegin, 0x0B) \ +X(SetIsa, 0x0C) \ typedef enum DW_StdOpcode { @@ -159,13 +159,13 @@ typedef enum DW_StdOpcode } DW_StdOpcode; #define DW_ExtOpcode_XList(X) \ - X(Undefined, 0x00) \ - X(EndSequence, 0x01) \ - X(SetAddress, 0x02) \ - X(DefineFile, 0x03) \ - X(SetDiscriminator, 0x04) \ - X(UserLo, 0x80) \ - X(UserHi, 0xff) +X(Undefined, 0x00) \ +X(EndSequence, 0x01) \ +X(SetAddress, 0x02) \ +X(DefineFile, 0x03) \ +X(SetDiscriminator, 0x04) \ +X(UserLo, 0x80) \ +X(UserHi, 0xff) typedef enum DW_ExtOpcode { @@ -175,10 +175,10 @@ typedef enum DW_ExtOpcode } DW_ExtOpcode; #define DW_IDCaseKind_XList(X) \ - X(CaseSensitive, 0x00) \ - X(UpCase, 0x01) \ - X(DownCase, 0x02) \ - X(CaseInsensitive, 0x03) +X(CaseSensitive, 0x00) \ +X(UpCase, 0x01) \ +X(DownCase, 0x02) \ +X(CaseInsensitive, 0x03) typedef U64 DW_IDCaseKind; typedef enum DW_IDCaseKindEnum @@ -189,80 +189,80 @@ typedef enum DW_IDCaseKindEnum } DW_IDCaseKindEnum; #define DW_Tag_V3_XList(X) \ - X(ArrayType, 0x01) \ - X(ClassType, 0x02) \ - X(EntryPoint, 0x03) \ - X(EnumerationType, 0x04) \ - X(FormalParameter, 0x05) \ - X(ImportedDeclaration, 0x08) \ - X(Label, 0x0a) \ - X(LexicalBlock, 0x0b) \ - X(Member, 0x0d) \ - X(PointerType, 0x0f) \ - X(ReferenceType, 0x10) \ - X(CompileUnit, 0x11) \ - X(StringType, 0x12) \ - X(StructureType, 0x13) \ - X(SubroutineType, 0x15) \ - X(Typedef, 0x16) \ - X(UnionType, 0x17) \ - X(UnspecifiedParameters, 0x18) \ - X(Variant, 0x19) \ - X(CommonBlock, 0x1a) \ - X(CommonInclusion, 0x1b) \ - X(Inheritance, 0x1c) \ - X(InlinedSubroutine, 0x1d) \ - X(Module, 0x1e) \ - X(PtrToMemberType, 0x1f) \ - X(SetType, 0x20) \ - X(SubrangeType, 0x21) \ - X(WithStmt, 0x22) \ - X(AccessDeclaration, 0x23) \ - X(BaseType, 0x24) \ - X(CatchBlock, 0x25) \ - X(ConstType, 0x26) \ - X(Constant, 0x27) \ - X(Enumerator, 0x28) \ - X(FileType, 0x29) \ - X(Friend, 0x2a) \ - X(NameList, 0x2b) \ - X(NameListItem, 0x2c) \ - X(PackedType, 0x2d) \ - X(SubProgram, 0x2e) \ - X(TemplateTypeParameter, 0x2f) \ - X(TemplateValueParameter, 0x30) \ - X(ThrownType, 0x31) \ - X(TryBlock, 0x32) \ - X(VariantPart, 0x33) \ - X(Variable, 0x34) \ - X(VolatileType, 0x35) \ - X(DwarfProcedure, 0x36) \ - X(RestrictType, 0x37) \ - X(InterfaceType, 0x38) \ - X(Namespace, 0x39) \ - X(ImportedModule, 0x3a) \ - X(UnspecifiedType, 0x3b) \ - X(PartialUnit, 0x3c) \ - X(ImportedUnit, 0x3d) \ - X(Condition, 0x3f) \ - X(SharedType, 0x40) +X(ArrayType, 0x01) \ +X(ClassType, 0x02) \ +X(EntryPoint, 0x03) \ +X(EnumerationType, 0x04) \ +X(FormalParameter, 0x05) \ +X(ImportedDeclaration, 0x08) \ +X(Label, 0x0a) \ +X(LexicalBlock, 0x0b) \ +X(Member, 0x0d) \ +X(PointerType, 0x0f) \ +X(ReferenceType, 0x10) \ +X(CompileUnit, 0x11) \ +X(StringType, 0x12) \ +X(StructureType, 0x13) \ +X(SubroutineType, 0x15) \ +X(Typedef, 0x16) \ +X(UnionType, 0x17) \ +X(UnspecifiedParameters, 0x18) \ +X(Variant, 0x19) \ +X(CommonBlock, 0x1a) \ +X(CommonInclusion, 0x1b) \ +X(Inheritance, 0x1c) \ +X(InlinedSubroutine, 0x1d) \ +X(Module, 0x1e) \ +X(PtrToMemberType, 0x1f) \ +X(SetType, 0x20) \ +X(SubrangeType, 0x21) \ +X(WithStmt, 0x22) \ +X(AccessDeclaration, 0x23) \ +X(BaseType, 0x24) \ +X(CatchBlock, 0x25) \ +X(ConstType, 0x26) \ +X(Constant, 0x27) \ +X(Enumerator, 0x28) \ +X(FileType, 0x29) \ +X(Friend, 0x2a) \ +X(NameList, 0x2b) \ +X(NameListItem, 0x2c) \ +X(PackedType, 0x2d) \ +X(SubProgram, 0x2e) \ +X(TemplateTypeParameter, 0x2f) \ +X(TemplateValueParameter, 0x30) \ +X(ThrownType, 0x31) \ +X(TryBlock, 0x32) \ +X(VariantPart, 0x33) \ +X(Variable, 0x34) \ +X(VolatileType, 0x35) \ +X(DwarfProcedure, 0x36) \ +X(RestrictType, 0x37) \ +X(InterfaceType, 0x38) \ +X(Namespace, 0x39) \ +X(ImportedModule, 0x3a) \ +X(UnspecifiedType, 0x3b) \ +X(PartialUnit, 0x3c) \ +X(ImportedUnit, 0x3d) \ +X(Condition, 0x3f) \ +X(SharedType, 0x40) #define DW_Tag_V5_XList(X) \ - X(TypeUnit, 0x41) \ - X(RValueReferenceType, 0x42) \ - X(TemplateAlias, 0x43) \ - X(CoarrayType, 0x44) \ - X(GenericSubrange, 0x45) \ - X(DynamicType, 0x46) \ - X(AtomicType, 0x47) \ - X(CallSite, 0x48) \ - X(CallSiteParameter, 0x49) \ - X(SkeletonUnit, 0x4A) \ - X(ImmutableType, 0x4B) +X(TypeUnit, 0x41) \ +X(RValueReferenceType, 0x42) \ +X(TemplateAlias, 0x43) \ +X(CoarrayType, 0x44) \ +X(GenericSubrange, 0x45) \ +X(DynamicType, 0x46) \ +X(AtomicType, 0x47) \ +X(CallSite, 0x48) \ +X(CallSiteParameter, 0x49) \ +X(SkeletonUnit, 0x4A) \ +X(ImmutableType, 0x4B) #define DW_Tag_GNU_XList(X) \ - X(GNU_CallSite, 0x4109) \ - X(GNU_CallSiteParameter, 0x410a) +X(GNU_CallSite, 0x4109) \ +X(GNU_CallSiteParameter, 0x410a) typedef U64 DW_TagKind; typedef enum DW_TagKindEnum @@ -270,8 +270,8 @@ 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_Tag_V5_XList(X) + DW_Tag_GNU_XList(X) #undef X DW_Tag_UserLo = 0x4080, DW_Tag_UserHi = 0xffff @@ -280,202 +280,202 @@ typedef enum DW_TagKindEnum //- Attrib Class Encodings #define DW_AttribClass_V3_XList(X) \ - X(Null, 0) \ - X(Undefined, 1) \ - X(Address, 2) \ - X(Block, 3) \ - X(Const, 4) \ - X(ExprLoc, 5) \ - X(Flag, 6) \ - X(LinePtr, 7) \ - X(LocListPtr, 8) \ - X(MacPtr, 9) \ - X(RngListPtr, 10) \ - X(Reference, 11) \ - X(String, 12) +X(Null, 0) \ +X(Undefined, 1) \ +X(Address, 2) \ +X(Block, 3) \ +X(Const, 4) \ +X(ExprLoc, 5) \ +X(Flag, 6) \ +X(LinePtr, 7) \ +X(LocListPtr, 8) \ +X(MacPtr, 9) \ +X(RngListPtr, 10) \ +X(Reference, 11) \ +X(String, 12) #define DW_AttribClass_V4_XList(X) \ - X(LocList, 13) \ - X(RngList, 14) +X(LocList, 13) \ +X(RngList, 14) #define DW_AttribClass_V5_XList(X) \ - X(StrOffsetsPtr, 15) \ - X(AddrPtr, 16) +X(StrOffsetsPtr, 15) \ +X(AddrPtr, 16) typedef U32 DW_AttribClass; typedef enum DW_AttribClassEnum { #define X(_N,_ID) DW_AttribClass_##_N = (1 << _ID), DW_AttribClass_V3_XList(X) - DW_AttribClass_V4_XList(X) - DW_AttribClass_V5_XList(X) + DW_AttribClass_V4_XList(X) + DW_AttribClass_V5_XList(X) #undef X } DW_AttribClassEnum; //- Form Encodings #define DW_Form_V2_XList(X) \ - X(Addr, 0x1) \ - X(Block2, 0x3) \ - X(Block4, 0x4) \ - X(Data2, 0x5) \ - X(Data4, 0x6) \ - X(Data8, 0x7) \ - X(String, 0x8) \ - X(Block, 0x9) \ - X(Block1, 0xa) \ - X(Data1, 0xb) \ - X(Flag, 0xc) \ - X(SData, 0xd) \ - X(Strp, 0xe) \ - X(UData, 0xf) \ - X(RefAddr, 0x10) \ - X(Ref1, 0x11) \ - X(Ref2, 0x12) \ - X(Ref4, 0x13) \ - X(Ref8, 0x14) \ - X(RefUData, 0x15) \ - X(Indirect, 0x16) +X(Addr, 0x1) \ +X(Block2, 0x3) \ +X(Block4, 0x4) \ +X(Data2, 0x5) \ +X(Data4, 0x6) \ +X(Data8, 0x7) \ +X(String, 0x8) \ +X(Block, 0x9) \ +X(Block1, 0xa) \ +X(Data1, 0xb) \ +X(Flag, 0xc) \ +X(SData, 0xd) \ +X(Strp, 0xe) \ +X(UData, 0xf) \ +X(RefAddr, 0x10) \ +X(Ref1, 0x11) \ +X(Ref2, 0x12) \ +X(Ref4, 0x13) \ +X(Ref8, 0x14) \ +X(RefUData, 0x15) \ +X(Indirect, 0x16) #define DW_Form_AttribClass_V2_XList(X) \ - X(Addr, DW_AttribClass_Address) \ - X(Block2, DW_AttribClass_Block) \ - X(Block4, DW_AttribClass_Block) \ - X(Data2, DW_AttribClass_Const) \ - X(Data4, DW_AttribClass_Const) \ - X(Data8, DW_AttribClass_Const) \ - X(String, DW_AttribClass_String) \ - X(Block, DW_AttribClass_Block) \ - X(Block1, DW_AttribClass_Block) \ - X(Data1, DW_AttribClass_Const) \ - X(Flag, DW_AttribClass_Flag) \ - X(SData, DW_AttribClass_Const) \ - X(Strp, DW_AttribClass_String) \ - X(UData, DW_AttribClass_Const) \ - X(RefAddr, DW_AttribClass_Reference) \ - X(Ref1, DW_AttribClass_Reference) \ - X(Ref2, DW_AttribClass_Reference) \ - X(Ref4, DW_AttribClass_Reference) \ - X(Ref8, DW_AttribClass_Reference) \ - X(RefUData, DW_AttribClass_Reference) \ - X(Indirect, DW_AttribClass_Null) +X(Addr, DW_AttribClass_Address) \ +X(Block2, DW_AttribClass_Block) \ +X(Block4, DW_AttribClass_Block) \ +X(Data2, DW_AttribClass_Const) \ +X(Data4, DW_AttribClass_Const) \ +X(Data8, DW_AttribClass_Const) \ +X(String, DW_AttribClass_String) \ +X(Block, DW_AttribClass_Block) \ +X(Block1, DW_AttribClass_Block) \ +X(Data1, DW_AttribClass_Const) \ +X(Flag, DW_AttribClass_Flag) \ +X(SData, DW_AttribClass_Const) \ +X(Strp, DW_AttribClass_String) \ +X(UData, DW_AttribClass_Const) \ +X(RefAddr, DW_AttribClass_Reference) \ +X(Ref1, DW_AttribClass_Reference) \ +X(Ref2, DW_AttribClass_Reference) \ +X(Ref4, DW_AttribClass_Reference) \ +X(Ref8, DW_AttribClass_Reference) \ +X(RefUData, DW_AttribClass_Reference) \ +X(Indirect, DW_AttribClass_Null) #define DW_Form_V4_XList(X) \ - X(SecOffset, 0x17) \ - X(ExprLoc, 0x18) \ - X(FlagPresent, 0x19) \ - X(RefSig8, 0x20) +X(SecOffset, 0x17) \ +X(ExprLoc, 0x18) \ +X(FlagPresent, 0x19) \ +X(RefSig8, 0x20) #define DW_Form_AttribClass_V4_XList(X) \ - X(Addr, DW_AttribClass_Address) \ - X(Block2, DW_AttribClass_Block) \ - X(Block4, DW_AttribClass_Block) \ - X(Data2, DW_AttribClass_Const) \ - X(Data4, DW_AttribClass_Const) \ - X(Data8, DW_AttribClass_Const) \ - X(String, DW_AttribClass_String) \ - X(Block, DW_AttribClass_Block) \ - X(Block1, DW_AttribClass_Block) \ - X(Data1, DW_AttribClass_Const) \ - X(Flag, DW_AttribClass_Flag) \ - X(SData, DW_AttribClass_Const) \ - X(Strp, DW_AttribClass_String) \ - X(UData, DW_AttribClass_Const) \ - X(RefAddr, DW_AttribClass_Reference) \ - X(Ref1, DW_AttribClass_Reference) \ - X(Ref2, DW_AttribClass_Reference) \ - X(Ref4, DW_AttribClass_Reference) \ - X(Ref8, DW_AttribClass_Reference) \ - X(RefUData, DW_AttribClass_Reference) \ - X(Indirect, DW_AttribClass_Null) \ - X(SecOffset, DW_AttribClass_LinePtr|DW_AttribClass_LocListPtr|DW_AttribClass_MacPtr|DW_AttribClass_RngListPtr) \ - X(ExprLoc, DW_AttribClass_ExprLoc) \ - X(FlagPresent, DW_AttribClass_Flag) \ - X(RefSig8, DW_AttribClass_Reference) +X(Addr, DW_AttribClass_Address) \ +X(Block2, DW_AttribClass_Block) \ +X(Block4, DW_AttribClass_Block) \ +X(Data2, DW_AttribClass_Const) \ +X(Data4, DW_AttribClass_Const) \ +X(Data8, DW_AttribClass_Const) \ +X(String, DW_AttribClass_String) \ +X(Block, DW_AttribClass_Block) \ +X(Block1, DW_AttribClass_Block) \ +X(Data1, DW_AttribClass_Const) \ +X(Flag, DW_AttribClass_Flag) \ +X(SData, DW_AttribClass_Const) \ +X(Strp, DW_AttribClass_String) \ +X(UData, DW_AttribClass_Const) \ +X(RefAddr, DW_AttribClass_Reference) \ +X(Ref1, DW_AttribClass_Reference) \ +X(Ref2, DW_AttribClass_Reference) \ +X(Ref4, DW_AttribClass_Reference) \ +X(Ref8, DW_AttribClass_Reference) \ +X(RefUData, DW_AttribClass_Reference) \ +X(Indirect, DW_AttribClass_Null) \ +X(SecOffset, DW_AttribClass_LinePtr|DW_AttribClass_LocListPtr|DW_AttribClass_MacPtr|DW_AttribClass_RngListPtr) \ +X(ExprLoc, DW_AttribClass_ExprLoc) \ +X(FlagPresent, DW_AttribClass_Flag) \ +X(RefSig8, DW_AttribClass_Reference) #define DW_Form_V5_XList(X) \ - X(Strx, 0x1a) \ - X(Addrx, 0x1b) \ - X(RefSup4, 0x1c) \ - X(StrpSup, 0x1d) \ - X(Data16, 0x1e) \ - X(LineStrp, 0x1f) \ - X(ImplicitConst, 0x21) \ - X(LocListx, 0x22) \ - X(RngListx, 0x23) \ - X(RefSup8, 0x24) \ - X(Strx1, 0x25) \ - X(Strx2, 0x26) \ - X(Strx3, 0x27) \ - X(Strx4, 0x28) \ - X(Addrx1, 0x29) \ - X(Addrx2, 0x2a) \ - X(Addrx3, 0x2b) \ - X(Addrx4, 0x2c) +X(Strx, 0x1a) \ +X(Addrx, 0x1b) \ +X(RefSup4, 0x1c) \ +X(StrpSup, 0x1d) \ +X(Data16, 0x1e) \ +X(LineStrp, 0x1f) \ +X(ImplicitConst, 0x21) \ +X(LocListx, 0x22) \ +X(RngListx, 0x23) \ +X(RefSup8, 0x24) \ +X(Strx1, 0x25) \ +X(Strx2, 0x26) \ +X(Strx3, 0x27) \ +X(Strx4, 0x28) \ +X(Addrx1, 0x29) \ +X(Addrx2, 0x2a) \ +X(Addrx3, 0x2b) \ +X(Addrx4, 0x2c) #define DW_Form_AttribClass_V5_XList(X) \ - X(Addr, DW_AttribClass_Address) \ - X(Block2, DW_AttribClass_Block) \ - X(Block4, DW_AttribClass_Block) \ - X(Data2, DW_AttribClass_Const) \ - X(Data4, DW_AttribClass_Const) \ - X(Data8, DW_AttribClass_Const) \ - X(String, DW_AttribClass_String) \ - X(Block, DW_AttribClass_Block) \ - X(Block1, DW_AttribClass_Block) \ - X(Data1, DW_AttribClass_Const) \ - X(Flag, DW_AttribClass_Flag) \ - X(SData, DW_AttribClass_Const) \ - X(Strp, DW_AttribClass_String) \ - X(UData, DW_AttribClass_Const) \ - X(RefAddr, DW_AttribClass_Reference) \ - X(Ref1, DW_AttribClass_Reference) \ - X(Ref2, DW_AttribClass_Reference) \ - X(Ref4, DW_AttribClass_Reference) \ - X(Ref8, DW_AttribClass_Reference) \ - X(RefUData, DW_AttribClass_Reference) \ - X(Indirect, DW_AttribClass_Null) \ - X(SecOffset, DW_AttribClass_AddrPtr| \ - DW_AttribClass_LinePtr| \ - DW_AttribClass_LocList| \ - DW_AttribClass_LocListPtr| \ - DW_AttribClass_MacPtr| \ - DW_AttribClass_RngList| \ - DW_AttribClass_RngListPtr| \ - DW_AttribClass_StrOffsetsPtr) \ - X(ExprLoc, DW_AttribClass_ExprLoc) \ - X(FlagPresent, DW_AttribClass_Flag) \ - X(RefSig8, DW_AttribClass_Reference) \ - X(Strx, DW_AttribClass_String) \ - X(Addrx, DW_AttribClass_Address) \ - X(RefSup4, DW_AttribClass_Reference) \ - X(StrpSup, DW_AttribClass_String) \ - X(Data16, DW_AttribClass_Const) \ - X(LineStrp, DW_AttribClass_String) \ - X(ImplicitConst, DW_AttribClass_Const) \ - X(LocListx, DW_AttribClass_LocListPtr) \ - X(RngListx, DW_AttribClass_RngList) \ - X(RefSup8, DW_AttribClass_Reference) \ - X(Strx1, DW_AttribClass_String) \ - X(Strx2, DW_AttribClass_String) \ - X(Strx3, DW_AttribClass_String) \ - X(Strx4, DW_AttribClass_String) \ - X(Addrx1, DW_AttribClass_Address) \ - X(Addrx2, DW_AttribClass_Address) \ - X(Addrx3, DW_AttribClass_Address) \ - X(Addrx4, DW_AttribClass_Address) +X(Addr, DW_AttribClass_Address) \ +X(Block2, DW_AttribClass_Block) \ +X(Block4, DW_AttribClass_Block) \ +X(Data2, DW_AttribClass_Const) \ +X(Data4, DW_AttribClass_Const) \ +X(Data8, DW_AttribClass_Const) \ +X(String, DW_AttribClass_String) \ +X(Block, DW_AttribClass_Block) \ +X(Block1, DW_AttribClass_Block) \ +X(Data1, DW_AttribClass_Const) \ +X(Flag, DW_AttribClass_Flag) \ +X(SData, DW_AttribClass_Const) \ +X(Strp, DW_AttribClass_String) \ +X(UData, DW_AttribClass_Const) \ +X(RefAddr, DW_AttribClass_Reference) \ +X(Ref1, DW_AttribClass_Reference) \ +X(Ref2, DW_AttribClass_Reference) \ +X(Ref4, DW_AttribClass_Reference) \ +X(Ref8, DW_AttribClass_Reference) \ +X(RefUData, DW_AttribClass_Reference) \ +X(Indirect, DW_AttribClass_Null) \ +X(SecOffset, DW_AttribClass_AddrPtr| \ +DW_AttribClass_LinePtr| \ +DW_AttribClass_LocList| \ +DW_AttribClass_LocListPtr| \ +DW_AttribClass_MacPtr| \ +DW_AttribClass_RngList| \ +DW_AttribClass_RngListPtr| \ +DW_AttribClass_StrOffsetsPtr) \ +X(ExprLoc, DW_AttribClass_ExprLoc) \ +X(FlagPresent, DW_AttribClass_Flag) \ +X(RefSig8, DW_AttribClass_Reference) \ +X(Strx, DW_AttribClass_String) \ +X(Addrx, DW_AttribClass_Address) \ +X(RefSup4, DW_AttribClass_Reference) \ +X(StrpSup, DW_AttribClass_String) \ +X(Data16, DW_AttribClass_Const) \ +X(LineStrp, DW_AttribClass_String) \ +X(ImplicitConst, DW_AttribClass_Const) \ +X(LocListx, DW_AttribClass_LocListPtr) \ +X(RngListx, DW_AttribClass_RngList) \ +X(RefSup8, DW_AttribClass_Reference) \ +X(Strx1, DW_AttribClass_String) \ +X(Strx2, DW_AttribClass_String) \ +X(Strx3, DW_AttribClass_String) \ +X(Strx4, DW_AttribClass_String) \ +X(Addrx1, DW_AttribClass_Address) \ +X(Addrx2, DW_AttribClass_Address) \ +X(Addrx3, DW_AttribClass_Address) \ +X(Addrx4, DW_AttribClass_Address) #define DW_Form_GNU_XList(X) \ - X(GNU_AddrIndex, 0x1f01) \ - X(GNU_StrIndex, 0x1f02) \ - X(GNU_RefAlt, 0x1f20) \ - X(GNU_StrpAlt, 0x1f21) +X(GNU_AddrIndex, 0x1f01) \ +X(GNU_StrIndex, 0x1f02) \ +X(GNU_RefAlt, 0x1f20) \ +X(GNU_StrpAlt, 0x1f21) #define DW_Form_AttribClass_GNU_XList(X) \ - X(GNU_AddrIndex, DW_AttribClass_Undefined) \ - X(GNU_StrIndex, DW_AttribClass_Undefined) \ - X(GNU_RefAlt, DW_AttribClass_Undefined) \ - X(GNU_StrpAlt, DW_AttribClass_String) +X(GNU_AddrIndex, DW_AttribClass_Undefined) \ +X(GNU_StrIndex, DW_AttribClass_Undefined) \ +X(GNU_RefAlt, DW_AttribClass_Undefined) \ +X(GNU_StrpAlt, DW_AttribClass_String) typedef U64 DW_FormKind; typedef enum DW_FormEnum @@ -483,678 +483,678 @@ typedef enum DW_FormEnum DW_Form_Null, #define X(_N, _ID) DW_Form_##_N = _ID, DW_Form_V2_XList(X) - DW_Form_V4_XList(X) - DW_Form_V5_XList(X) - DW_Form_GNU_XList(X) + DW_Form_V4_XList(X) + DW_Form_V5_XList(X) + DW_Form_GNU_XList(X) #undef X } DW_FormEnum; //- Attributes DWARF2 #define DW_AttribKind_V2_XList(X) \ - X(Sibling, 0x1) \ - X(Location, 0x2) \ - X(Name, 0x3) \ - X(Ordering, 0x9) \ - X(ByteSize, 0xB) \ - X(BitOffset, 0xC) \ - X(BitSize, 0xD) \ - X(StmtList, 0x10) \ - X(LowPc, 0x11) \ - X(HighPc, 0x12) \ - X(Language, 0x13) \ - X(Discr, 0x15) \ - X(DiscrValue, 0x16) \ - X(Visibility, 0x17) \ - X(Import, 0x18) \ - X(StringLength, 0x19) \ - X(CommonReference, 0x1a) \ - X(CompDir, 0x1b) \ - X(ConstValue, 0x1c) \ - X(ContainingType, 0x1d) \ - X(DefaultValue, 0x1e) \ - X(Inline, 0x20) \ - X(IsOptional, 0x21) \ - X(LowerBound, 0x22) \ - X(Producer, 0x25) \ - X(Prototyped, 0x27) \ - X(ReturnAddr, 0x2a) \ - X(StartScope, 0x2c) \ - X(BitStride, 0x2e) \ - X(UpperBound, 0x2f) \ - X(AbstractOrigin, 0x31) \ - X(Accessibility, 0x32) \ - X(AddressClass, 0x33) \ - X(Artificial, 0x34) \ - X(BaseTypes, 0x35) \ - X(CallingConvention, 0x36) \ - X(Count, 0x37) \ - X(DataMemberLocation, 0x38) \ - X(DeclColumn, 0x39) \ - X(DeclFile, 0x3a) \ - X(DeclLine, 0x3b) \ - X(Declaration, 0x3c) \ - X(DiscrList, 0x3d) \ - X(Encoding, 0x3e) \ - X(External, 0x3f) \ - X(FrameBase, 0x40) \ - X(Friend, 0x41) \ - X(IdentifierCase, 0x42) \ - X(MacroInfo, 0x43) \ - X(NameListItem, 0x44) \ - X(Priority, 0x45) \ - X(Segment, 0x46) \ - X(Specification, 0x47) \ - X(StaticLink, 0x48) \ - X(Type, 0x49) \ - X(UseLocation, 0x4a) \ - X(VariableParameter, 0x4b) \ - X(Virtuality, 0x4c) \ - X(VTableElemLocation, 0x4d) +X(Sibling, 0x1) \ +X(Location, 0x2) \ +X(Name, 0x3) \ +X(Ordering, 0x9) \ +X(ByteSize, 0xB) \ +X(BitOffset, 0xC) \ +X(BitSize, 0xD) \ +X(StmtList, 0x10) \ +X(LowPc, 0x11) \ +X(HighPc, 0x12) \ +X(Language, 0x13) \ +X(Discr, 0x15) \ +X(DiscrValue, 0x16) \ +X(Visibility, 0x17) \ +X(Import, 0x18) \ +X(StringLength, 0x19) \ +X(CommonReference, 0x1a) \ +X(CompDir, 0x1b) \ +X(ConstValue, 0x1c) \ +X(ContainingType, 0x1d) \ +X(DefaultValue, 0x1e) \ +X(Inline, 0x20) \ +X(IsOptional, 0x21) \ +X(LowerBound, 0x22) \ +X(Producer, 0x25) \ +X(Prototyped, 0x27) \ +X(ReturnAddr, 0x2a) \ +X(StartScope, 0x2c) \ +X(BitStride, 0x2e) \ +X(UpperBound, 0x2f) \ +X(AbstractOrigin, 0x31) \ +X(Accessibility, 0x32) \ +X(AddressClass, 0x33) \ +X(Artificial, 0x34) \ +X(BaseTypes, 0x35) \ +X(CallingConvention, 0x36) \ +X(Count, 0x37) \ +X(DataMemberLocation, 0x38) \ +X(DeclColumn, 0x39) \ +X(DeclFile, 0x3a) \ +X(DeclLine, 0x3b) \ +X(Declaration, 0x3c) \ +X(DiscrList, 0x3d) \ +X(Encoding, 0x3e) \ +X(External, 0x3f) \ +X(FrameBase, 0x40) \ +X(Friend, 0x41) \ +X(IdentifierCase, 0x42) \ +X(MacroInfo, 0x43) \ +X(NameListItem, 0x44) \ +X(Priority, 0x45) \ +X(Segment, 0x46) \ +X(Specification, 0x47) \ +X(StaticLink, 0x48) \ +X(Type, 0x49) \ +X(UseLocation, 0x4a) \ +X(VariableParameter, 0x4b) \ +X(Virtuality, 0x4c) \ +X(VTableElemLocation, 0x4d) #define DW_AttribKind_ClassFlags_V2_XList(X) \ - X(Sibling, DW_AttribClass_Reference) \ - X(Location, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ - X(Name, DW_AttribClass_String) \ - X(Ordering, DW_AttribClass_Const) \ - X(ByteSize, DW_AttribClass_Const) \ - X(BitOffset, DW_AttribClass_Const) \ - X(BitSize, DW_AttribClass_Const) \ - X(StmtList, DW_AttribClass_Const) \ - X(LowPc, DW_AttribClass_Address) \ - X(HighPc, DW_AttribClass_Address) \ - X(Language, DW_AttribClass_Const) \ - X(Discr, DW_AttribClass_Reference) \ - X(DiscrValue, DW_AttribClass_Const) \ - X(Visibility, DW_AttribClass_Const) \ - X(Import, DW_AttribClass_Reference) \ - X(StringLength, DW_AttribClass_Block|DW_AttribClass_Const) \ - X(CommonReference, DW_AttribClass_Reference) \ - X(CompDir, DW_AttribClass_String) \ - X(ConstValue, DW_AttribClass_String|DW_AttribClass_Const|DW_AttribClass_Block) \ - X(ContainingType, DW_AttribClass_Reference) \ - X(DefaultValue, DW_AttribClass_Reference) \ - X(Inline, DW_AttribClass_Const) \ - X(IsOptional, DW_AttribClass_Flag) \ - X(LowerBound, DW_AttribClass_Const|DW_AttribClass_Reference) \ - 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(UpperBound, DW_AttribClass_Const|DW_AttribClass_Reference) \ - X(AbstractOrigin, DW_AttribClass_Reference) \ - X(Accessibility, DW_AttribClass_Const) \ - X(AddressClass, DW_AttribClass_Const) \ - X(Artificial, DW_AttribClass_Flag) \ - X(BaseTypes, DW_AttribClass_Reference) \ - X(CallingConvention, DW_AttribClass_Const) \ - X(Count, DW_AttribClass_Const|DW_AttribClass_Reference) \ - X(DataMemberLocation, DW_AttribClass_Block|DW_AttribClass_Reference) \ - X(DeclColumn, DW_AttribClass_Const) \ - X(DeclFile, DW_AttribClass_Const) \ - X(DeclLine, DW_AttribClass_Const) \ - X(Declaration, DW_AttribClass_Flag) \ - X(DiscrList, DW_AttribClass_Block) \ - X(Encoding, DW_AttribClass_Const) \ - X(External, DW_AttribClass_Flag) \ - X(FrameBase, DW_AttribClass_Block|DW_AttribClass_Const) \ - X(Friend, DW_AttribClass_Reference) \ - X(IdentifierCase, DW_AttribClass_Const) \ - X(MacroInfo, DW_AttribClass_Const) \ - X(NameListItem, DW_AttribClass_Block) \ - X(Priority, DW_AttribClass_Reference) \ - X(Segment, DW_AttribClass_Block|DW_AttribClass_Const) \ - X(Specification, DW_AttribClass_Reference) \ - X(StaticLink, DW_AttribClass_Block|DW_AttribClass_Const) \ - X(Type, DW_AttribClass_Reference) \ - X(UseLocation, DW_AttribClass_Block|DW_AttribClass_Const) \ - X(VariableParameter, DW_AttribClass_Flag) \ - X(Virtuality, DW_AttribClass_Const) \ - X(VTableElemLocation, DW_AttribClass_Block|DW_AttribClass_Reference) +X(Sibling, DW_AttribClass_Reference) \ +X(Location, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ +X(Name, DW_AttribClass_String) \ +X(Ordering, DW_AttribClass_Const) \ +X(ByteSize, DW_AttribClass_Const) \ +X(BitOffset, DW_AttribClass_Const) \ +X(BitSize, DW_AttribClass_Const) \ +X(StmtList, DW_AttribClass_Const) \ +X(LowPc, DW_AttribClass_Address) \ +X(HighPc, DW_AttribClass_Address) \ +X(Language, DW_AttribClass_Const) \ +X(Discr, DW_AttribClass_Reference) \ +X(DiscrValue, DW_AttribClass_Const) \ +X(Visibility, DW_AttribClass_Const) \ +X(Import, DW_AttribClass_Reference) \ +X(StringLength, DW_AttribClass_Block|DW_AttribClass_Const) \ +X(CommonReference, DW_AttribClass_Reference) \ +X(CompDir, DW_AttribClass_String) \ +X(ConstValue, DW_AttribClass_String|DW_AttribClass_Const|DW_AttribClass_Block) \ +X(ContainingType, DW_AttribClass_Reference) \ +X(DefaultValue, DW_AttribClass_Reference) \ +X(Inline, DW_AttribClass_Const) \ +X(IsOptional, DW_AttribClass_Flag) \ +X(LowerBound, DW_AttribClass_Const|DW_AttribClass_Reference) \ +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(UpperBound, DW_AttribClass_Const|DW_AttribClass_Reference) \ +X(AbstractOrigin, DW_AttribClass_Reference) \ +X(Accessibility, DW_AttribClass_Const) \ +X(AddressClass, DW_AttribClass_Const) \ +X(Artificial, DW_AttribClass_Flag) \ +X(BaseTypes, DW_AttribClass_Reference) \ +X(CallingConvention, DW_AttribClass_Const) \ +X(Count, DW_AttribClass_Const|DW_AttribClass_Reference) \ +X(DataMemberLocation, DW_AttribClass_Block|DW_AttribClass_Reference) \ +X(DeclColumn, DW_AttribClass_Const) \ +X(DeclFile, DW_AttribClass_Const) \ +X(DeclLine, DW_AttribClass_Const) \ +X(Declaration, DW_AttribClass_Flag) \ +X(DiscrList, DW_AttribClass_Block) \ +X(Encoding, DW_AttribClass_Const) \ +X(External, DW_AttribClass_Flag) \ +X(FrameBase, DW_AttribClass_Block|DW_AttribClass_Const) \ +X(Friend, DW_AttribClass_Reference) \ +X(IdentifierCase, DW_AttribClass_Const) \ +X(MacroInfo, DW_AttribClass_Const) \ +X(NameListItem, DW_AttribClass_Block) \ +X(Priority, DW_AttribClass_Reference) \ +X(Segment, DW_AttribClass_Block|DW_AttribClass_Const) \ +X(Specification, DW_AttribClass_Reference) \ +X(StaticLink, DW_AttribClass_Block|DW_AttribClass_Const) \ +X(Type, DW_AttribClass_Reference) \ +X(UseLocation, DW_AttribClass_Block|DW_AttribClass_Const) \ +X(VariableParameter, DW_AttribClass_Flag) \ +X(Virtuality, DW_AttribClass_Const) \ +X(VTableElemLocation, DW_AttribClass_Block|DW_AttribClass_Reference) //- Attributes DWARF3 #define DW_AttribKind_V3_XList(X) \ - X(Allocated, 0x4e) \ - X(Associated, 0x4f) \ - X(DataLocation, 0x50) \ - X(ByteStride, 0x51) \ - X(EntryPc, 0x52) \ - X(UseUtf8, 0x53) \ - X(Extension, 0x54) \ - X(Ranges, 0x55) \ - X(Trampoline, 0x56) \ - X(CallColumn, 0x57) \ - X(CallFile, 0x58) \ - X(CallLine, 0x59) \ - X(Description, 0x5a) \ - X(BinaryScale, 0x5b) \ - X(DecimalScale, 0x5c) \ - X(Small, 0x5d) \ - X(DecimalSign, 0x5e) \ - X(DigitCount, 0x5f) \ - X(PictureString, 0x60) \ - X(Mutable, 0x61) \ - X(ThreadsScaled, 0x62) \ - X(Explicit, 0x63) \ - X(ObjectPointer, 0x64) \ - X(Endianity, 0x65) \ - X(Elemental, 0x66) \ - X(Pure, 0x67) \ - X(Recursive, 0x68) +X(Allocated, 0x4e) \ +X(Associated, 0x4f) \ +X(DataLocation, 0x50) \ +X(ByteStride, 0x51) \ +X(EntryPc, 0x52) \ +X(UseUtf8, 0x53) \ +X(Extension, 0x54) \ +X(Ranges, 0x55) \ +X(Trampoline, 0x56) \ +X(CallColumn, 0x57) \ +X(CallFile, 0x58) \ +X(CallLine, 0x59) \ +X(Description, 0x5a) \ +X(BinaryScale, 0x5b) \ +X(DecimalScale, 0x5c) \ +X(Small, 0x5d) \ +X(DecimalSign, 0x5e) \ +X(DigitCount, 0x5f) \ +X(PictureString, 0x60) \ +X(Mutable, 0x61) \ +X(ThreadsScaled, 0x62) \ +X(Explicit, 0x63) \ +X(ObjectPointer, 0x64) \ +X(Endianity, 0x65) \ +X(Elemental, 0x66) \ +X(Pure, 0x67) \ +X(Recursive, 0x68) #define DW_AttribKind_ClassFlags_V3_XList(X) \ - X(Sibling, DW_AttribClass_Reference) \ - X(Location, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ - X(Name, DW_AttribClass_String) \ - X(Ordering, DW_AttribClass_Const) \ - X(ByteSize, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ - X(BitOffset, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ - X(BitSize, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ - X(StmtList, DW_AttribClass_LinePtr) \ - X(LowPc, DW_AttribClass_Address) \ - X(HighPc, DW_AttribClass_Address) \ - X(Language, DW_AttribClass_Const) \ - X(Discr, DW_AttribClass_Reference) \ - X(DiscrValue, DW_AttribClass_Const) \ - X(Visibility, DW_AttribClass_Const) \ - X(Import, DW_AttribClass_Reference) \ - X(StringLength, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ - X(CommonReference, DW_AttribClass_Reference) \ - X(CompDir, DW_AttribClass_String) \ - X(ConstValue, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_String) \ - X(ContainingType, DW_AttribClass_Reference) \ - X(DefaultValue, DW_AttribClass_Reference) \ - X(Inline, DW_AttribClass_Const) \ - X(IsOptional, DW_AttribClass_Flag) \ - X(LowerBound, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ - X(Producer, DW_AttribClass_String) \ - X(Prototyped, DW_AttribClass_Flag) \ - X(ReturnAddr, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ - X(StartScope, DW_AttribClass_Const) \ - X(BitStride, DW_AttribClass_Const) \ - X(UpperBound, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ - X(AbstractOrigin, DW_AttribClass_Reference) \ - X(Accessibility, DW_AttribClass_Const) \ - X(AddressClass, DW_AttribClass_Const) \ - X(Artificial, DW_AttribClass_Flag) \ - X(BaseTypes, DW_AttribClass_Reference) \ - X(CallingConvention, DW_AttribClass_Const) \ - X(Count, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ - X(DataMemberLocation, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_LocListPtr) \ - X(DeclColumn, DW_AttribClass_Const) \ - X(DeclFile, DW_AttribClass_Const) \ - X(DeclLine, DW_AttribClass_Const) \ - X(Declaration, DW_AttribClass_Flag) \ - X(DiscrList, DW_AttribClass_Block) \ - X(Encoding, DW_AttribClass_Const) \ - X(External, DW_AttribClass_Flag) \ - X(FrameBase, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ - X(Friend, DW_AttribClass_Reference) \ - X(IdentifierCase, DW_AttribClass_Const) \ - X(MacroInfo, DW_AttribClass_MacPtr) \ - X(NameListItem, DW_AttribClass_Block) \ - X(Priority, DW_AttribClass_Reference) \ - X(Segment, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ - X(Specification, DW_AttribClass_Reference) \ - X(StaticLink, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ - X(Type, DW_AttribClass_Reference) \ - X(UseLocation, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ - X(VariableParameter, DW_AttribClass_Flag) \ - X(Virtuality, DW_AttribClass_Const) \ - X(VTableElemLocation, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ - X(Allocated, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ - X(Associated, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ - X(DataLocation, DW_AttribClass_Block) \ - X(ByteStride, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ - X(EntryPc, DW_AttribClass_Address) \ - X(UseUtf8, DW_AttribClass_Flag) \ - X(Extension, DW_AttribClass_Reference) \ - X(Ranges, DW_AttribClass_RngListPtr) \ - X(Trampoline, DW_AttribClass_Address|DW_AttribClass_Flag|DW_AttribClass_Reference|DW_AttribClass_String) \ - X(CallColumn, DW_AttribClass_Const) \ - X(CallFile, DW_AttribClass_Const) \ - X(CallLine, DW_AttribClass_Const) \ - X(Description, DW_AttribClass_String) \ - X(BinaryScale, DW_AttribClass_Const) \ - X(DecimalScale, DW_AttribClass_Const) \ - X(Small, DW_AttribClass_Reference) \ - X(DecimalSign, DW_AttribClass_Const) \ - X(DigitCount, DW_AttribClass_Const) \ - X(PictureString, DW_AttribClass_String) \ - X(Mutable, DW_AttribClass_Flag) \ - X(ThreadsScaled, DW_AttribClass_Flag) \ - X(Explicit, DW_AttribClass_Flag) \ - X(ObjectPointer, DW_AttribClass_Reference) \ - X(Endianity, DW_AttribClass_Const) \ - X(Elemental, DW_AttribClass_Flag) \ - X(Pure, DW_AttribClass_Flag) \ - X(Recursive, DW_AttribClass_Flag) +X(Sibling, DW_AttribClass_Reference) \ +X(Location, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ +X(Name, DW_AttribClass_String) \ +X(Ordering, DW_AttribClass_Const) \ +X(ByteSize, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ +X(BitOffset, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ +X(BitSize, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ +X(StmtList, DW_AttribClass_LinePtr) \ +X(LowPc, DW_AttribClass_Address) \ +X(HighPc, DW_AttribClass_Address) \ +X(Language, DW_AttribClass_Const) \ +X(Discr, DW_AttribClass_Reference) \ +X(DiscrValue, DW_AttribClass_Const) \ +X(Visibility, DW_AttribClass_Const) \ +X(Import, DW_AttribClass_Reference) \ +X(StringLength, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ +X(CommonReference, DW_AttribClass_Reference) \ +X(CompDir, DW_AttribClass_String) \ +X(ConstValue, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_String) \ +X(ContainingType, DW_AttribClass_Reference) \ +X(DefaultValue, DW_AttribClass_Reference) \ +X(Inline, DW_AttribClass_Const) \ +X(IsOptional, DW_AttribClass_Flag) \ +X(LowerBound, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ +X(Producer, DW_AttribClass_String) \ +X(Prototyped, DW_AttribClass_Flag) \ +X(ReturnAddr, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ +X(StartScope, DW_AttribClass_Const) \ +X(BitStride, DW_AttribClass_Const) \ +X(UpperBound, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ +X(AbstractOrigin, DW_AttribClass_Reference) \ +X(Accessibility, DW_AttribClass_Const) \ +X(AddressClass, DW_AttribClass_Const) \ +X(Artificial, DW_AttribClass_Flag) \ +X(BaseTypes, DW_AttribClass_Reference) \ +X(CallingConvention, DW_AttribClass_Const) \ +X(Count, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ +X(DataMemberLocation, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_LocListPtr) \ +X(DeclColumn, DW_AttribClass_Const) \ +X(DeclFile, DW_AttribClass_Const) \ +X(DeclLine, DW_AttribClass_Const) \ +X(Declaration, DW_AttribClass_Flag) \ +X(DiscrList, DW_AttribClass_Block) \ +X(Encoding, DW_AttribClass_Const) \ +X(External, DW_AttribClass_Flag) \ +X(FrameBase, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ +X(Friend, DW_AttribClass_Reference) \ +X(IdentifierCase, DW_AttribClass_Const) \ +X(MacroInfo, DW_AttribClass_MacPtr) \ +X(NameListItem, DW_AttribClass_Block) \ +X(Priority, DW_AttribClass_Reference) \ +X(Segment, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ +X(Specification, DW_AttribClass_Reference) \ +X(StaticLink, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ +X(Type, DW_AttribClass_Reference) \ +X(UseLocation, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ +X(VariableParameter, DW_AttribClass_Flag) \ +X(Virtuality, DW_AttribClass_Const) \ +X(VTableElemLocation, DW_AttribClass_Block|DW_AttribClass_LocListPtr) \ +X(Allocated, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ +X(Associated, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ +X(DataLocation, DW_AttribClass_Block) \ +X(ByteStride, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_Reference) \ +X(EntryPc, DW_AttribClass_Address) \ +X(UseUtf8, DW_AttribClass_Flag) \ +X(Extension, DW_AttribClass_Reference) \ +X(Ranges, DW_AttribClass_RngListPtr) \ +X(Trampoline, DW_AttribClass_Address|DW_AttribClass_Flag|DW_AttribClass_Reference|DW_AttribClass_String) \ +X(CallColumn, DW_AttribClass_Const) \ +X(CallFile, DW_AttribClass_Const) \ +X(CallLine, DW_AttribClass_Const) \ +X(Description, DW_AttribClass_String) \ +X(BinaryScale, DW_AttribClass_Const) \ +X(DecimalScale, DW_AttribClass_Const) \ +X(Small, DW_AttribClass_Reference) \ +X(DecimalSign, DW_AttribClass_Const) \ +X(DigitCount, DW_AttribClass_Const) \ +X(PictureString, DW_AttribClass_String) \ +X(Mutable, DW_AttribClass_Flag) \ +X(ThreadsScaled, DW_AttribClass_Flag) \ +X(Explicit, DW_AttribClass_Flag) \ +X(ObjectPointer, DW_AttribClass_Reference) \ +X(Endianity, DW_AttribClass_Const) \ +X(Elemental, DW_AttribClass_Flag) \ +X(Pure, DW_AttribClass_Flag) \ +X(Recursive, DW_AttribClass_Flag) //- Attributes DWARF4 #define DW_AttribKind_V4_XList(X) \ - X(Signature, 0x69) \ - X(MainSubProgram, 0x6a) \ - X(DataBitOffset, 0x6b) \ - X(ConstExpr, 0x6c) \ - X(EnumClass, 0x6d) \ - X(LinkageName, 0x6e) +X(Signature, 0x69) \ +X(MainSubProgram, 0x6a) \ +X(DataBitOffset, 0x6b) \ +X(ConstExpr, 0x6c) \ +X(EnumClass, 0x6d) \ +X(LinkageName, 0x6e) #define DW_AttribKind_ClassFlags_V4_XList(X) \ - X(Sibling, DW_AttribClass_Reference) \ - X(Location, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ - X(Name, DW_AttribClass_String) \ - X(Ordering, DW_AttribClass_Const) \ - X(ByteSize, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(BitOffset, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(BitSize, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(StmtList, DW_AttribClass_LinePtr) \ - X(LowPc, DW_AttribClass_Address) \ - X(HighPc, DW_AttribClass_Address|DW_AttribClass_Const) \ - X(Language, DW_AttribClass_Const) \ - X(Discr, DW_AttribClass_Reference) \ - X(DiscrValue, DW_AttribClass_Const) \ - X(Visibility, DW_AttribClass_Const) \ - X(Import, DW_AttribClass_Reference) \ - X(StringLength, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ - X(CommonReference, DW_AttribClass_Reference) \ - X(CompDir, DW_AttribClass_String) \ - X(ConstValue, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_String) \ - X(ContainingType, DW_AttribClass_Reference) \ - X(DefaultValue, DW_AttribClass_Reference) \ - X(Inline, DW_AttribClass_Const) \ - X(IsOptional, DW_AttribClass_Flag) \ - X(LowerBound, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(Producer, DW_AttribClass_String) \ - X(Prototyped, DW_AttribClass_Flag) \ - X(ReturnAddr, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ - X(StartScope, DW_AttribClass_Const|DW_AttribClass_RngListPtr) \ - X(BitStride, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(UpperBound, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(AbstractOrigin, DW_AttribClass_Reference) \ - X(Accessibility, DW_AttribClass_Const) \ - X(AddressClass, DW_AttribClass_Const) \ - X(Artificial, DW_AttribClass_Flag) \ - X(BaseTypes, DW_AttribClass_Reference) \ - X(CallingConvention, DW_AttribClass_Const) \ - X(Count, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(DataMemberLocation, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ - X(DeclColumn, DW_AttribClass_Const) \ - X(DeclFile, DW_AttribClass_Const) \ - X(DeclLine, DW_AttribClass_Const) \ - X(Declaration, DW_AttribClass_Flag) \ - X(DiscrList, DW_AttribClass_Block) \ - X(Encoding, DW_AttribClass_Const) \ - X(External, DW_AttribClass_Flag) \ - X(FrameBase, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ - X(Friend, DW_AttribClass_Reference) \ - X(IdentifierCase, DW_AttribClass_Const) \ - X(MacroInfo, DW_AttribClass_MacPtr) \ - X(NameListItem, DW_AttribClass_Reference) \ - X(Priority, DW_AttribClass_Reference) \ - X(Segment, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ - X(Specification, DW_AttribClass_Reference) \ - X(StaticLink, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ - X(Type, DW_AttribClass_Reference) \ - X(UseLocation, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ - X(VariableParameter, DW_AttribClass_Flag) \ - X(Virtuality, DW_AttribClass_Const) \ - X(VTableElemLocation, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ - X(Allocated, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(Associated, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(DataLocation, DW_AttribClass_ExprLoc) \ - X(ByteStride, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(EntryPc, DW_AttribClass_Address) \ - X(UseUtf8, DW_AttribClass_Flag) \ - X(Extension, DW_AttribClass_Reference) \ - X(Ranges, DW_AttribClass_RngListPtr) \ - X(Trampoline, DW_AttribClass_Address|DW_AttribClass_Flag|DW_AttribClass_Reference|DW_AttribClass_String) \ - X(CallColumn, DW_AttribClass_Const) \ - X(CallFile, DW_AttribClass_Const) \ - X(CallLine, DW_AttribClass_Const) \ - X(Description, DW_AttribClass_String) \ - X(BinaryScale, DW_AttribClass_Const) \ - X(DecimalScale, DW_AttribClass_Const) \ - X(Small, DW_AttribClass_Reference) \ - X(DecimalSign, DW_AttribClass_Const) \ - X(DigitCount, DW_AttribClass_Const) \ - X(PictureString, DW_AttribClass_String) \ - X(Mutable, DW_AttribClass_Flag) \ - X(ThreadsScaled, DW_AttribClass_Flag) \ - X(Explicit, DW_AttribClass_Flag) \ - X(ObjectPointer, DW_AttribClass_Reference) \ - X(Endianity, DW_AttribClass_Const) \ - X(Elemental, DW_AttribClass_Flag) \ - X(Pure, DW_AttribClass_Flag) \ - X(Recursive, DW_AttribClass_Flag) \ - X(Signature, DW_AttribClass_Reference) \ - X(MainSubProgram, DW_AttribClass_Flag) \ - X(DataBitOffset, DW_AttribClass_Const) \ - X(ConstExpr, DW_AttribClass_Flag) \ - X(EnumClass, DW_AttribClass_Flag) \ - X(LinkageName, DW_AttribClass_String) +X(Sibling, DW_AttribClass_Reference) \ +X(Location, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ +X(Name, DW_AttribClass_String) \ +X(Ordering, DW_AttribClass_Const) \ +X(ByteSize, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(BitOffset, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(BitSize, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(StmtList, DW_AttribClass_LinePtr) \ +X(LowPc, DW_AttribClass_Address) \ +X(HighPc, DW_AttribClass_Address|DW_AttribClass_Const) \ +X(Language, DW_AttribClass_Const) \ +X(Discr, DW_AttribClass_Reference) \ +X(DiscrValue, DW_AttribClass_Const) \ +X(Visibility, DW_AttribClass_Const) \ +X(Import, DW_AttribClass_Reference) \ +X(StringLength, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ +X(CommonReference, DW_AttribClass_Reference) \ +X(CompDir, DW_AttribClass_String) \ +X(ConstValue, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_String) \ +X(ContainingType, DW_AttribClass_Reference) \ +X(DefaultValue, DW_AttribClass_Reference) \ +X(Inline, DW_AttribClass_Const) \ +X(IsOptional, DW_AttribClass_Flag) \ +X(LowerBound, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(Producer, DW_AttribClass_String) \ +X(Prototyped, DW_AttribClass_Flag) \ +X(ReturnAddr, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ +X(StartScope, DW_AttribClass_Const|DW_AttribClass_RngListPtr) \ +X(BitStride, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(UpperBound, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(AbstractOrigin, DW_AttribClass_Reference) \ +X(Accessibility, DW_AttribClass_Const) \ +X(AddressClass, DW_AttribClass_Const) \ +X(Artificial, DW_AttribClass_Flag) \ +X(BaseTypes, DW_AttribClass_Reference) \ +X(CallingConvention, DW_AttribClass_Const) \ +X(Count, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(DataMemberLocation, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ +X(DeclColumn, DW_AttribClass_Const) \ +X(DeclFile, DW_AttribClass_Const) \ +X(DeclLine, DW_AttribClass_Const) \ +X(Declaration, DW_AttribClass_Flag) \ +X(DiscrList, DW_AttribClass_Block) \ +X(Encoding, DW_AttribClass_Const) \ +X(External, DW_AttribClass_Flag) \ +X(FrameBase, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ +X(Friend, DW_AttribClass_Reference) \ +X(IdentifierCase, DW_AttribClass_Const) \ +X(MacroInfo, DW_AttribClass_MacPtr) \ +X(NameListItem, DW_AttribClass_Reference) \ +X(Priority, DW_AttribClass_Reference) \ +X(Segment, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ +X(Specification, DW_AttribClass_Reference) \ +X(StaticLink, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ +X(Type, DW_AttribClass_Reference) \ +X(UseLocation, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ +X(VariableParameter, DW_AttribClass_Flag) \ +X(Virtuality, DW_AttribClass_Const) \ +X(VTableElemLocation, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ +X(Allocated, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(Associated, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(DataLocation, DW_AttribClass_ExprLoc) \ +X(ByteStride, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(EntryPc, DW_AttribClass_Address) \ +X(UseUtf8, DW_AttribClass_Flag) \ +X(Extension, DW_AttribClass_Reference) \ +X(Ranges, DW_AttribClass_RngListPtr) \ +X(Trampoline, DW_AttribClass_Address|DW_AttribClass_Flag|DW_AttribClass_Reference|DW_AttribClass_String) \ +X(CallColumn, DW_AttribClass_Const) \ +X(CallFile, DW_AttribClass_Const) \ +X(CallLine, DW_AttribClass_Const) \ +X(Description, DW_AttribClass_String) \ +X(BinaryScale, DW_AttribClass_Const) \ +X(DecimalScale, DW_AttribClass_Const) \ +X(Small, DW_AttribClass_Reference) \ +X(DecimalSign, DW_AttribClass_Const) \ +X(DigitCount, DW_AttribClass_Const) \ +X(PictureString, DW_AttribClass_String) \ +X(Mutable, DW_AttribClass_Flag) \ +X(ThreadsScaled, DW_AttribClass_Flag) \ +X(Explicit, DW_AttribClass_Flag) \ +X(ObjectPointer, DW_AttribClass_Reference) \ +X(Endianity, DW_AttribClass_Const) \ +X(Elemental, DW_AttribClass_Flag) \ +X(Pure, DW_AttribClass_Flag) \ +X(Recursive, DW_AttribClass_Flag) \ +X(Signature, DW_AttribClass_Reference) \ +X(MainSubProgram, DW_AttribClass_Flag) \ +X(DataBitOffset, DW_AttribClass_Const) \ +X(ConstExpr, DW_AttribClass_Flag) \ +X(EnumClass, DW_AttribClass_Flag) \ +X(LinkageName, DW_AttribClass_String) //- Attributes DWARF5 #define DW_AttribKind_V5_XList(X) \ - X(StringLengthBitSize, 0x6f) \ - X(StringLengthByteSize, 0x70) \ - X(Rank, 0x71) \ - X(StrOffsetsBase, 0x72) \ - X(AddrBase, 0x73) \ - X(RngListsBase, 0x74) \ - X(DwoName, 0x76) \ - X(Reference, 0x77) \ - X(RValueReference, 0x78) \ - X(Macros, 0x79) \ - X(CallAllCalls, 0x7a) \ - X(CallAllSourceCalls, 0x7b) \ - X(CallAllTailCalls, 0x7c) \ - X(CallReturnPc, 0x7d) \ - X(CallValue, 0x7e) \ - X(CallOrigin, 0x7f) \ - X(CallParameter, 0x80) \ - X(CallPc, 0x81) \ - X(CallTailCall, 0x82) \ - X(CallTarget, 0x83) \ - X(CallTargetClobbered, 0x84) \ - X(CallDataLocation, 0x85) \ - X(CallDataValue, 0x86) \ - X(NoReturn, 0x87) \ - X(Alignment, 0x88) \ - X(ExportSymbols, 0x89) \ - X(Deleted, 0x8a) \ - X(Defaulted, 0x8b) \ - X(LocListsBase, 0x8c) +X(StringLengthBitSize, 0x6f) \ +X(StringLengthByteSize, 0x70) \ +X(Rank, 0x71) \ +X(StrOffsetsBase, 0x72) \ +X(AddrBase, 0x73) \ +X(RngListsBase, 0x74) \ +X(DwoName, 0x76) \ +X(Reference, 0x77) \ +X(RValueReference, 0x78) \ +X(Macros, 0x79) \ +X(CallAllCalls, 0x7a) \ +X(CallAllSourceCalls, 0x7b) \ +X(CallAllTailCalls, 0x7c) \ +X(CallReturnPc, 0x7d) \ +X(CallValue, 0x7e) \ +X(CallOrigin, 0x7f) \ +X(CallParameter, 0x80) \ +X(CallPc, 0x81) \ +X(CallTailCall, 0x82) \ +X(CallTarget, 0x83) \ +X(CallTargetClobbered, 0x84) \ +X(CallDataLocation, 0x85) \ +X(CallDataValue, 0x86) \ +X(NoReturn, 0x87) \ +X(Alignment, 0x88) \ +X(ExportSymbols, 0x89) \ +X(Deleted, 0x8a) \ +X(Defaulted, 0x8b) \ +X(LocListsBase, 0x8c) #define DW_AttribKind_ClassFlags_V5_XList(X) \ - X(Sibling, DW_AttribClass_Reference) \ - X(Location, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ - X(Name, DW_AttribClass_String) \ - X(Ordering, DW_AttribClass_Const) \ - X(ByteSize, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(BitOffset, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(BitSize, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(StmtList, DW_AttribClass_LinePtr) \ - X(LowPc, DW_AttribClass_Address) \ - X(HighPc, DW_AttribClass_Address|DW_AttribClass_Const) \ - X(Language, DW_AttribClass_Const) \ - X(Discr, DW_AttribClass_Reference) \ - X(DiscrValue, DW_AttribClass_Const) \ - X(Visibility, DW_AttribClass_Const) \ - X(Import, DW_AttribClass_Reference) \ - X(StringLength, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ - X(CommonReference, DW_AttribClass_Reference) \ - X(CompDir, DW_AttribClass_String) \ - X(ConstValue, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_String) \ - X(ContainingType, DW_AttribClass_Reference) \ - X(DefaultValue, DW_AttribClass_Reference) \ - X(Inline, DW_AttribClass_Const) \ - X(IsOptional, DW_AttribClass_Flag) \ - X(LowerBound, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(Producer, DW_AttribClass_String) \ - X(Prototyped, DW_AttribClass_Flag) \ - X(ReturnAddr, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ - X(StartScope, DW_AttribClass_Const|DW_AttribClass_RngListPtr) \ - X(BitStride, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(UpperBound, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(AbstractOrigin, DW_AttribClass_Reference) \ - X(Accessibility, DW_AttribClass_Const) \ - X(AddressClass, DW_AttribClass_Const) \ - X(Artificial, DW_AttribClass_Flag) \ - X(BaseTypes, DW_AttribClass_Reference) \ - X(CallingConvention, DW_AttribClass_Const) \ - X(Count, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(DataMemberLocation, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ - X(DeclColumn, DW_AttribClass_Const) \ - X(DeclFile, DW_AttribClass_Const) \ - X(DeclLine, DW_AttribClass_Const) \ - X(Declaration, DW_AttribClass_Flag) \ - X(DiscrList, DW_AttribClass_Block) \ - X(Encoding, DW_AttribClass_Const) \ - X(External, DW_AttribClass_Flag) \ - X(FrameBase, DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ - X(Friend, DW_AttribClass_Reference) \ - X(IdentifierCase, DW_AttribClass_Const) \ - X(MacroInfo, DW_AttribClass_MacPtr) \ - X(NameListItem, DW_AttribClass_Reference) \ - X(Priority, DW_AttribClass_Reference) \ - X(Segment, DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ - X(Specification, DW_AttribClass_Reference) \ - X(StaticLink, DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ - X(Type, DW_AttribClass_Reference) \ - X(UseLocation, DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ - X(VariableParameter, DW_AttribClass_Flag) \ - X(Virtuality, DW_AttribClass_Const) \ - X(VTableElemLocation, DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ - X(Allocated, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(Associated, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(DataLocation, DW_AttribClass_ExprLoc) \ - X(ByteStride, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ - X(EntryPc, DW_AttribClass_Address|DW_AttribClass_Const) \ - X(UseUtf8, DW_AttribClass_Flag) \ - X(Extension, DW_AttribClass_Reference) \ - X(Ranges, DW_AttribClass_RngList) \ - X(Trampoline, DW_AttribClass_Address|DW_AttribClass_Flag|DW_AttribClass_Reference|DW_AttribClass_String) \ - X(CallColumn, DW_AttribClass_Const) \ - X(CallFile, DW_AttribClass_Const) \ - X(CallLine, DW_AttribClass_Const) \ - X(Description, DW_AttribClass_String) \ - X(BinaryScale, DW_AttribClass_Const) \ - X(DecimalScale, DW_AttribClass_Const) \ - X(Small, DW_AttribClass_Reference) \ - X(DecimalSign, DW_AttribClass_Const) \ - X(DigitCount, DW_AttribClass_Const) \ - X(PictureString, DW_AttribClass_String) \ - X(Mutable, DW_AttribClass_Flag) \ - X(ThreadsScaled, DW_AttribClass_Flag) \ - X(Explicit, DW_AttribClass_Flag) \ - X(ObjectPointer, DW_AttribClass_Reference) \ - X(Endianity, DW_AttribClass_Const) \ - X(Elemental, DW_AttribClass_Flag) \ - X(Pure, DW_AttribClass_Flag) \ - X(Recursive, DW_AttribClass_Flag) \ - X(Signature, DW_AttribClass_Reference) \ - X(MainSubProgram, DW_AttribClass_Flag) \ - X(DataBitOffset, DW_AttribClass_Const) \ - X(ConstExpr, DW_AttribClass_Flag) \ - X(EnumClass, DW_AttribClass_Flag) \ - X(LinkageName, DW_AttribClass_String) \ - X(StringLengthBitSize, DW_AttribClass_Const) \ - X(StringLengthByteSize, DW_AttribClass_Const) \ - X(Rank, DW_AttribClass_Const|DW_AttribClass_ExprLoc) \ - X(StrOffsetsBase, DW_AttribClass_StrOffsetsPtr) \ - X(AddrBase, DW_AttribClass_AddrPtr) \ - X(RngListsBase, DW_AttribClass_RngListPtr) \ - X(DwoName, DW_AttribClass_String) \ - X(Reference, DW_AttribClass_Flag) \ - X(RValueReference, DW_AttribClass_Flag) \ - X(Macros, DW_AttribClass_MacPtr) \ - X(CallAllCalls, DW_AttribClass_Flag) \ - X(CallAllSourceCalls, DW_AttribClass_Flag) \ - X(CallAllTailCalls, DW_AttribClass_Flag) \ - X(CallReturnPc, DW_AttribClass_Address) \ - X(CallValue, DW_AttribClass_ExprLoc) \ - X(CallOrigin, DW_AttribClass_ExprLoc) \ - X(CallParameter, DW_AttribClass_Reference) \ - X(CallPc, DW_AttribClass_Address) \ - X(CallTailCall, DW_AttribClass_Flag) \ - X(CallTarget, DW_AttribClass_ExprLoc) \ - X(CallTargetClobbered, DW_AttribClass_ExprLoc) \ - X(CallDataLocation, DW_AttribClass_ExprLoc) \ - X(CallDataValue, DW_AttribClass_ExprLoc) \ - X(NoReturn, DW_AttribClass_Flag) \ - X(Alignment, DW_AttribClass_Const) \ - X(ExportSymbols, DW_AttribClass_Flag) \ - X(Deleted, DW_AttribClass_Flag) \ - X(Defaulted, DW_AttribClass_Const) \ - X(LocListsBase, DW_AttribClass_LocListPtr) +X(Sibling, DW_AttribClass_Reference) \ +X(Location, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ +X(Name, DW_AttribClass_String) \ +X(Ordering, DW_AttribClass_Const) \ +X(ByteSize, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(BitOffset, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(BitSize, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(StmtList, DW_AttribClass_LinePtr) \ +X(LowPc, DW_AttribClass_Address) \ +X(HighPc, DW_AttribClass_Address|DW_AttribClass_Const) \ +X(Language, DW_AttribClass_Const) \ +X(Discr, DW_AttribClass_Reference) \ +X(DiscrValue, DW_AttribClass_Const) \ +X(Visibility, DW_AttribClass_Const) \ +X(Import, DW_AttribClass_Reference) \ +X(StringLength, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ +X(CommonReference, DW_AttribClass_Reference) \ +X(CompDir, DW_AttribClass_String) \ +X(ConstValue, DW_AttribClass_Block|DW_AttribClass_Const|DW_AttribClass_String) \ +X(ContainingType, DW_AttribClass_Reference) \ +X(DefaultValue, DW_AttribClass_Reference) \ +X(Inline, DW_AttribClass_Const) \ +X(IsOptional, DW_AttribClass_Flag) \ +X(LowerBound, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(Producer, DW_AttribClass_String) \ +X(Prototyped, DW_AttribClass_Flag) \ +X(ReturnAddr, DW_AttribClass_ExprLoc|DW_AttribClass_LocListPtr) \ +X(StartScope, DW_AttribClass_Const|DW_AttribClass_RngListPtr) \ +X(BitStride, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(UpperBound, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(AbstractOrigin, DW_AttribClass_Reference) \ +X(Accessibility, DW_AttribClass_Const) \ +X(AddressClass, DW_AttribClass_Const) \ +X(Artificial, DW_AttribClass_Flag) \ +X(BaseTypes, DW_AttribClass_Reference) \ +X(CallingConvention, DW_AttribClass_Const) \ +X(Count, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(DataMemberLocation, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ +X(DeclColumn, DW_AttribClass_Const) \ +X(DeclFile, DW_AttribClass_Const) \ +X(DeclLine, DW_AttribClass_Const) \ +X(Declaration, DW_AttribClass_Flag) \ +X(DiscrList, DW_AttribClass_Block) \ +X(Encoding, DW_AttribClass_Const) \ +X(External, DW_AttribClass_Flag) \ +X(FrameBase, DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ +X(Friend, DW_AttribClass_Reference) \ +X(IdentifierCase, DW_AttribClass_Const) \ +X(MacroInfo, DW_AttribClass_MacPtr) \ +X(NameListItem, DW_AttribClass_Reference) \ +X(Priority, DW_AttribClass_Reference) \ +X(Segment, DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ +X(Specification, DW_AttribClass_Reference) \ +X(StaticLink, DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ +X(Type, DW_AttribClass_Reference) \ +X(UseLocation, DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ +X(VariableParameter, DW_AttribClass_Flag) \ +X(Virtuality, DW_AttribClass_Const) \ +X(VTableElemLocation, DW_AttribClass_ExprLoc|DW_AttribClass_LocList) \ +X(Allocated, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(Associated, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(DataLocation, DW_AttribClass_ExprLoc) \ +X(ByteStride, DW_AttribClass_Const|DW_AttribClass_ExprLoc|DW_AttribClass_Reference) \ +X(EntryPc, DW_AttribClass_Address|DW_AttribClass_Const) \ +X(UseUtf8, DW_AttribClass_Flag) \ +X(Extension, DW_AttribClass_Reference) \ +X(Ranges, DW_AttribClass_RngList) \ +X(Trampoline, DW_AttribClass_Address|DW_AttribClass_Flag|DW_AttribClass_Reference|DW_AttribClass_String) \ +X(CallColumn, DW_AttribClass_Const) \ +X(CallFile, DW_AttribClass_Const) \ +X(CallLine, DW_AttribClass_Const) \ +X(Description, DW_AttribClass_String) \ +X(BinaryScale, DW_AttribClass_Const) \ +X(DecimalScale, DW_AttribClass_Const) \ +X(Small, DW_AttribClass_Reference) \ +X(DecimalSign, DW_AttribClass_Const) \ +X(DigitCount, DW_AttribClass_Const) \ +X(PictureString, DW_AttribClass_String) \ +X(Mutable, DW_AttribClass_Flag) \ +X(ThreadsScaled, DW_AttribClass_Flag) \ +X(Explicit, DW_AttribClass_Flag) \ +X(ObjectPointer, DW_AttribClass_Reference) \ +X(Endianity, DW_AttribClass_Const) \ +X(Elemental, DW_AttribClass_Flag) \ +X(Pure, DW_AttribClass_Flag) \ +X(Recursive, DW_AttribClass_Flag) \ +X(Signature, DW_AttribClass_Reference) \ +X(MainSubProgram, DW_AttribClass_Flag) \ +X(DataBitOffset, DW_AttribClass_Const) \ +X(ConstExpr, DW_AttribClass_Flag) \ +X(EnumClass, DW_AttribClass_Flag) \ +X(LinkageName, DW_AttribClass_String) \ +X(StringLengthBitSize, DW_AttribClass_Const) \ +X(StringLengthByteSize, DW_AttribClass_Const) \ +X(Rank, DW_AttribClass_Const|DW_AttribClass_ExprLoc) \ +X(StrOffsetsBase, DW_AttribClass_StrOffsetsPtr) \ +X(AddrBase, DW_AttribClass_AddrPtr) \ +X(RngListsBase, DW_AttribClass_RngListPtr) \ +X(DwoName, DW_AttribClass_String) \ +X(Reference, DW_AttribClass_Flag) \ +X(RValueReference, DW_AttribClass_Flag) \ +X(Macros, DW_AttribClass_MacPtr) \ +X(CallAllCalls, DW_AttribClass_Flag) \ +X(CallAllSourceCalls, DW_AttribClass_Flag) \ +X(CallAllTailCalls, DW_AttribClass_Flag) \ +X(CallReturnPc, DW_AttribClass_Address) \ +X(CallValue, DW_AttribClass_ExprLoc) \ +X(CallOrigin, DW_AttribClass_ExprLoc) \ +X(CallParameter, DW_AttribClass_Reference) \ +X(CallPc, DW_AttribClass_Address) \ +X(CallTailCall, DW_AttribClass_Flag) \ +X(CallTarget, DW_AttribClass_ExprLoc) \ +X(CallTargetClobbered, DW_AttribClass_ExprLoc) \ +X(CallDataLocation, DW_AttribClass_ExprLoc) \ +X(CallDataValue, DW_AttribClass_ExprLoc) \ +X(NoReturn, DW_AttribClass_Flag) \ +X(Alignment, DW_AttribClass_Const) \ +X(ExportSymbols, DW_AttribClass_Flag) \ +X(Deleted, DW_AttribClass_Flag) \ +X(Defaulted, DW_AttribClass_Const) \ +X(LocListsBase, DW_AttribClass_LocListPtr) //- Attributes GNU #define DW_AttribKind_GNU_XList(X) \ - X(GNU_Vector, 0x2107) \ - X(GNU_GuardedBy, 0x2108) \ - X(GNU_PtGuardedBy, 0x2109) \ - X(GNU_Guarded, 0x210a) \ - X(GNU_PtGuarded, 0x210b) \ - X(GNU_LocksExcluded, 0x210c) \ - X(GNU_ExclusiveLocksRequired, 0x210d) \ - X(GNU_SharedLocksRequired, 0x210e) \ - X(GNU_OdrSignature, 0x210f) \ - X(GNU_TemplateName, 0x2110) \ - X(GNU_CallSiteValue, 0x2111) \ - X(GNU_CallSiteDataValue, 0x2112) \ - X(GNU_CallSiteTarget, 0x2113) \ - X(GNU_CallSiteTargetClobbered, 0x2114) \ - X(GNU_TailCall, 0x2115) \ - X(GNU_AllTailCallsSites, 0x2116) \ - X(GNU_AllCallSites, 0x2117) \ - X(GNU_AllSourceCallSites, 0x2118) \ - X(GNU_Macros, 0x2119) \ - X(GNU_Deleted, 0x211a) \ - X(GNU_DwoName, 0x2130) \ - X(GNU_DwoId, 0x2131) \ - X(GNU_RangesBase, 0x2132) \ - X(GNU_AddrBase, 0x2133) \ - X(GNU_PubNames, 0x2134) \ - X(GNU_PubTypes, 0x2135) \ - X(GNU_Discriminator, 0x2136) \ - X(GNU_LocViews, 0x2137) \ - X(GNU_EntryView, 0x2138) \ - X(GNU_DescriptiveType, 0x2302) \ - X(GNU_Numerator, 0x2303) \ - X(GNU_Denominator, 0x2304) \ - X(GNU_Bias, 0x2305) +X(GNU_Vector, 0x2107) \ +X(GNU_GuardedBy, 0x2108) \ +X(GNU_PtGuardedBy, 0x2109) \ +X(GNU_Guarded, 0x210a) \ +X(GNU_PtGuarded, 0x210b) \ +X(GNU_LocksExcluded, 0x210c) \ +X(GNU_ExclusiveLocksRequired, 0x210d) \ +X(GNU_SharedLocksRequired, 0x210e) \ +X(GNU_OdrSignature, 0x210f) \ +X(GNU_TemplateName, 0x2110) \ +X(GNU_CallSiteValue, 0x2111) \ +X(GNU_CallSiteDataValue, 0x2112) \ +X(GNU_CallSiteTarget, 0x2113) \ +X(GNU_CallSiteTargetClobbered, 0x2114) \ +X(GNU_TailCall, 0x2115) \ +X(GNU_AllTailCallsSites, 0x2116) \ +X(GNU_AllCallSites, 0x2117) \ +X(GNU_AllSourceCallSites, 0x2118) \ +X(GNU_Macros, 0x2119) \ +X(GNU_Deleted, 0x211a) \ +X(GNU_DwoName, 0x2130) \ +X(GNU_DwoId, 0x2131) \ +X(GNU_RangesBase, 0x2132) \ +X(GNU_AddrBase, 0x2133) \ +X(GNU_PubNames, 0x2134) \ +X(GNU_PubTypes, 0x2135) \ +X(GNU_Discriminator, 0x2136) \ +X(GNU_LocViews, 0x2137) \ +X(GNU_EntryView, 0x2138) \ +X(GNU_DescriptiveType, 0x2302) \ +X(GNU_Numerator, 0x2303) \ +X(GNU_Denominator, 0x2304) \ +X(GNU_Bias, 0x2305) #define DW_AttribKind_ClassFlags_GNU_XList(X) \ - X(GNU_Vector, DW_AttribClass_Flag) \ - X(GNU_GuardedBy, DW_AttribClass_Undefined) \ - X(GNU_PtGuardedBy, DW_AttribClass_Undefined) \ - X(GNU_Guarded, DW_AttribClass_Undefined) \ - X(GNU_PtGuarded, DW_AttribClass_Undefined) \ - X(GNU_LocksExcluded, DW_AttribClass_Undefined) \ - X(GNU_ExclusiveLocksRequired, DW_AttribClass_Undefined) \ - X(GNU_SharedLocksRequired, DW_AttribClass_Undefined) \ - X(GNU_OdrSignature, DW_AttribClass_Undefined) \ - X(GNU_TemplateName, DW_AttribClass_Undefined) \ - X(GNU_CallSiteValue, DW_AttribClass_ExprLoc) \ - X(GNU_CallSiteDataValue, DW_AttribClass_ExprLoc) \ - X(GNU_CallSiteTarget, DW_AttribClass_ExprLoc) \ - X(GNU_CallSiteTargetClobbered, DW_AttribClass_ExprLoc) \ - X(GNU_TailCall, DW_AttribClass_Flag) \ - X(GNU_AllTailCallsSites, DW_AttribClass_Flag) \ - X(GNU_AllCallSites, DW_AttribClass_Flag) \ - X(GNU_AllSourceCallSites, DW_AttribClass_Flag) \ - X(GNU_Macros, DW_AttribClass_Flag) \ - X(GNU_Deleted, DW_AttribClass_Undefined) \ - X(GNU_DwoName, DW_AttribClass_String) \ - X(GNU_DwoId, DW_AttribClass_Const) \ - X(GNU_RangesBase, DW_AttribClass_Undefined) \ - X(GNU_AddrBase, DW_AttribClass_AddrPtr) \ - X(GNU_PubNames, DW_AttribClass_Flag) \ - X(GNU_PubTypes, DW_AttribClass_Undefined) \ - X(GNU_Discriminator, DW_AttribClass_Const) \ - X(GNU_LocViews, DW_AttribClass_Undefined) \ - X(GNU_EntryView, DW_AttribClass_Undefined) \ - X(GNU_DescriptiveType, DW_AttribClass_Undefined) \ - X(GNU_Numerator, DW_AttribClass_Undefined) \ - X(GNU_Denominator, DW_AttribClass_Undefined) \ - X(GNU_Bias, DW_AttribClass_Undefined) +X(GNU_Vector, DW_AttribClass_Flag) \ +X(GNU_GuardedBy, DW_AttribClass_Undefined) \ +X(GNU_PtGuardedBy, DW_AttribClass_Undefined) \ +X(GNU_Guarded, DW_AttribClass_Undefined) \ +X(GNU_PtGuarded, DW_AttribClass_Undefined) \ +X(GNU_LocksExcluded, DW_AttribClass_Undefined) \ +X(GNU_ExclusiveLocksRequired, DW_AttribClass_Undefined) \ +X(GNU_SharedLocksRequired, DW_AttribClass_Undefined) \ +X(GNU_OdrSignature, DW_AttribClass_Undefined) \ +X(GNU_TemplateName, DW_AttribClass_Undefined) \ +X(GNU_CallSiteValue, DW_AttribClass_ExprLoc) \ +X(GNU_CallSiteDataValue, DW_AttribClass_ExprLoc) \ +X(GNU_CallSiteTarget, DW_AttribClass_ExprLoc) \ +X(GNU_CallSiteTargetClobbered, DW_AttribClass_ExprLoc) \ +X(GNU_TailCall, DW_AttribClass_Flag) \ +X(GNU_AllTailCallsSites, DW_AttribClass_Flag) \ +X(GNU_AllCallSites, DW_AttribClass_Flag) \ +X(GNU_AllSourceCallSites, DW_AttribClass_Flag) \ +X(GNU_Macros, DW_AttribClass_Flag) \ +X(GNU_Deleted, DW_AttribClass_Undefined) \ +X(GNU_DwoName, DW_AttribClass_String) \ +X(GNU_DwoId, DW_AttribClass_Const) \ +X(GNU_RangesBase, DW_AttribClass_Undefined) \ +X(GNU_AddrBase, DW_AttribClass_AddrPtr) \ +X(GNU_PubNames, DW_AttribClass_Flag) \ +X(GNU_PubTypes, DW_AttribClass_Undefined) \ +X(GNU_Discriminator, DW_AttribClass_Const) \ +X(GNU_LocViews, DW_AttribClass_Undefined) \ +X(GNU_EntryView, DW_AttribClass_Undefined) \ +X(GNU_DescriptiveType, DW_AttribClass_Undefined) \ +X(GNU_Numerator, DW_AttribClass_Undefined) \ +X(GNU_Denominator, DW_AttribClass_Undefined) \ +X(GNU_Bias, DW_AttribClass_Undefined) //- Attributes LLVM #define DW_AttribKind_LLVM_XList(X) \ - X(LLVM_IncludePath, 0x3e00) \ - X(LLVM_ConfigMacros, 0x3e01) \ - X(LLVM_SysRoot, 0x3e02) \ - X(LLVM_TagOffset, 0x3e03) \ - X(LLVM_ApiNotes, 0x3e07) +X(LLVM_IncludePath, 0x3e00) \ +X(LLVM_ConfigMacros, 0x3e01) \ +X(LLVM_SysRoot, 0x3e02) \ +X(LLVM_TagOffset, 0x3e03) \ +X(LLVM_ApiNotes, 0x3e07) #define DW_AttribKind_ClassFlags_LLVM_XList(X) \ - X(LLVM_IncludePath, DW_AttribClass_String) \ - X(LLVM_ConfigMacros, DW_AttribClass_String) \ - X(LLVM_SysRoot, DW_AttribClass_String) \ - X(LLVM_TagOffset, DW_AttribClass_Undefined) \ - X(LLVM_ApiNotes, DW_AttribClass_String) +X(LLVM_IncludePath, DW_AttribClass_String) \ +X(LLVM_ConfigMacros, DW_AttribClass_String) \ +X(LLVM_SysRoot, DW_AttribClass_String) \ +X(LLVM_TagOffset, DW_AttribClass_Undefined) \ +X(LLVM_ApiNotes, DW_AttribClass_String) //- Attributes Apple #define DW_AttribKind_APPLE_XList(X) \ - X(APPLE_Optimized, 0x3fe1) \ - X(APPLE_Flags, 0x3fe2) \ - X(APPLE_Isa, 0x3fe3) \ - X(APPLE_Block, 0x3fe4) \ - X(APPLE_MajorRuntimeVers, 0x3fe5) \ - X(APPLE_RuntimeClass, 0x3fe6) \ - X(APPLE_OmitFramePtr, 0x3fe7) \ - X(APPLE_PropertyName, 0x3fe8) \ - X(APPLE_PropertyGetter, 0x3fe9) \ - X(APPLE_PropertySetter, 0x3fea) \ - X(APPLE_PropertyAttribute, 0x3feb) \ - X(APPLE_ObjcCompleteType, 0x3fec) \ - X(APPLE_Property, 0x3fed) \ - X(APPLE_ObjDirect, 0x3fee) \ - X(APPLE_Sdk, 0x3fef) +X(APPLE_Optimized, 0x3fe1) \ +X(APPLE_Flags, 0x3fe2) \ +X(APPLE_Isa, 0x3fe3) \ +X(APPLE_Block, 0x3fe4) \ +X(APPLE_MajorRuntimeVers, 0x3fe5) \ +X(APPLE_RuntimeClass, 0x3fe6) \ +X(APPLE_OmitFramePtr, 0x3fe7) \ +X(APPLE_PropertyName, 0x3fe8) \ +X(APPLE_PropertyGetter, 0x3fe9) \ +X(APPLE_PropertySetter, 0x3fea) \ +X(APPLE_PropertyAttribute, 0x3feb) \ +X(APPLE_ObjcCompleteType, 0x3fec) \ +X(APPLE_Property, 0x3fed) \ +X(APPLE_ObjDirect, 0x3fee) \ +X(APPLE_Sdk, 0x3fef) #define DW_AttribKind_ClassFlags_APPLE_XList(X) \ - X(APPLE_Optimized, DW_AttribClass_Flag) \ - X(APPLE_Flags, DW_AttribClass_Flag) \ - X(APPLE_Isa, DW_AttribClass_Flag) \ - X(APPLE_Block, DW_AttribClass_Undefined) \ - X(APPLE_MajorRuntimeVers, DW_AttribClass_Undefined) \ - X(APPLE_RuntimeClass, DW_AttribClass_Undefined) \ - X(APPLE_OmitFramePtr, DW_AttribClass_Flag) \ - X(APPLE_PropertyName, DW_AttribClass_Undefined) \ - X(APPLE_PropertyGetter, DW_AttribClass_Undefined) \ - X(APPLE_PropertySetter, DW_AttribClass_Undefined) \ - X(APPLE_PropertyAttribute, DW_AttribClass_Undefined) \ - X(APPLE_ObjcCompleteType, DW_AttribClass_Undefined) \ - X(APPLE_Property, DW_AttribClass_Undefined) \ - X(APPLE_ObjDirect, DW_AttribClass_Undefined) \ - X(APPLE_Sdk, DW_AttribClass_String) +X(APPLE_Optimized, DW_AttribClass_Flag) \ +X(APPLE_Flags, DW_AttribClass_Flag) \ +X(APPLE_Isa, DW_AttribClass_Flag) \ +X(APPLE_Block, DW_AttribClass_Undefined) \ +X(APPLE_MajorRuntimeVers, DW_AttribClass_Undefined) \ +X(APPLE_RuntimeClass, DW_AttribClass_Undefined) \ +X(APPLE_OmitFramePtr, DW_AttribClass_Flag) \ +X(APPLE_PropertyName, DW_AttribClass_Undefined) \ +X(APPLE_PropertyGetter, DW_AttribClass_Undefined) \ +X(APPLE_PropertySetter, DW_AttribClass_Undefined) \ +X(APPLE_PropertyAttribute, DW_AttribClass_Undefined) \ +X(APPLE_ObjcCompleteType, DW_AttribClass_Undefined) \ +X(APPLE_Property, DW_AttribClass_Undefined) \ +X(APPLE_ObjDirect, DW_AttribClass_Undefined) \ +X(APPLE_Sdk, DW_AttribClass_String) //- Attributes MIPS #define DW_AttribKind_MIPS_XList(X) \ - X(MIPS_Fde, 0x2001) \ - X(MIPS_LoopBegin, 0x2002) \ - X(MIPS_TailLoopBegin, 0x2003) \ - X(MIPS_EpilogBegin, 0x2004) \ - X(MIPS_LoopUnrollFactor, 0x2005) \ - X(MIPS_SoftwarePipelineDepth, 0x2006) \ - X(MIPS_LinkageName, 0x2007) \ - X(MIPS_Stride, 0x2008) \ - X(MIPS_AbstractName, 0x2009) \ - X(MIPS_CloneOrigin, 0x200a) \ - X(MIPS_HasInlines, 0x200b) \ - X(MIPS_StrideByte, 0x200c) \ - X(MIPS_StrideElem, 0x200d) \ - X(MIPS_PtrDopeType, 0x200e) \ - X(MIPS_AllocatableDopeType, 0x200f) \ - X(MIPS_AssumedShapeDopeType, 0x2010) \ - X(MIPS_AssumedSize, 0x2011) +X(MIPS_Fde, 0x2001) \ +X(MIPS_LoopBegin, 0x2002) \ +X(MIPS_TailLoopBegin, 0x2003) \ +X(MIPS_EpilogBegin, 0x2004) \ +X(MIPS_LoopUnrollFactor, 0x2005) \ +X(MIPS_SoftwarePipelineDepth, 0x2006) \ +X(MIPS_LinkageName, 0x2007) \ +X(MIPS_Stride, 0x2008) \ +X(MIPS_AbstractName, 0x2009) \ +X(MIPS_CloneOrigin, 0x200a) \ +X(MIPS_HasInlines, 0x200b) \ +X(MIPS_StrideByte, 0x200c) \ +X(MIPS_StrideElem, 0x200d) \ +X(MIPS_PtrDopeType, 0x200e) \ +X(MIPS_AllocatableDopeType, 0x200f) \ +X(MIPS_AssumedShapeDopeType, 0x2010) \ +X(MIPS_AssumedSize, 0x2011) #define DW_AttribKind_ClassFlags_MIPS_XList(X) \ - X(MIPS_Fde, DW_AttribClass_Block) \ - X(MIPS_LoopBegin, DW_AttribClass_Block) \ - X(MIPS_TailLoopBegin, DW_AttribClass_Block) \ - X(MIPS_EpilogBegin, DW_AttribClass_Block) \ - X(MIPS_LoopUnrollFactor, DW_AttribClass_Block) \ - X(MIPS_SoftwarePipelineDepth, DW_AttribClass_Block) \ - X(MIPS_LinkageName, DW_AttribClass_String) \ - X(MIPS_Stride, DW_AttribClass_Block) \ - X(MIPS_AbstractName, DW_AttribClass_String) \ - X(MIPS_CloneOrigin, DW_AttribClass_String) \ - X(MIPS_HasInlines, DW_AttribClass_Reference) \ - X(MIPS_StrideByte, DW_AttribClass_Reference) \ - X(MIPS_StrideElem, DW_AttribClass_Reference) \ - X(MIPS_PtrDopeType, DW_AttribClass_Reference) \ - X(MIPS_AllocatableDopeType, DW_AttribClass_Reference) \ - X(MIPS_AssumedShapeDopeType, DW_AttribClass_Reference) \ - X(MIPS_AssumedSize, DW_AttribClass_Reference) +X(MIPS_Fde, DW_AttribClass_Block) \ +X(MIPS_LoopBegin, DW_AttribClass_Block) \ +X(MIPS_TailLoopBegin, DW_AttribClass_Block) \ +X(MIPS_EpilogBegin, DW_AttribClass_Block) \ +X(MIPS_LoopUnrollFactor, DW_AttribClass_Block) \ +X(MIPS_SoftwarePipelineDepth, DW_AttribClass_Block) \ +X(MIPS_LinkageName, DW_AttribClass_String) \ +X(MIPS_Stride, DW_AttribClass_Block) \ +X(MIPS_AbstractName, DW_AttribClass_String) \ +X(MIPS_CloneOrigin, DW_AttribClass_String) \ +X(MIPS_HasInlines, DW_AttribClass_Reference) \ +X(MIPS_StrideByte, DW_AttribClass_Reference) \ +X(MIPS_StrideElem, DW_AttribClass_Reference) \ +X(MIPS_PtrDopeType, DW_AttribClass_Reference) \ +X(MIPS_AllocatableDopeType, DW_AttribClass_Reference) \ +X(MIPS_AssumedShapeDopeType, DW_AttribClass_Reference) \ +X(MIPS_AssumedSize, DW_AttribClass_Reference) typedef U32 DW_AttribKind; typedef enum DW_AttribKindEnum @@ -1162,38 +1162,38 @@ typedef enum DW_AttribKindEnum DW_Attrib_Null, #define X(_N,_ID,...) DW_Attrib_##_N = _ID, DW_AttribKind_V2_XList(X) - DW_AttribKind_V3_XList(X) - DW_AttribKind_V4_XList(X) - DW_AttribKind_V5_XList(X) - DW_AttribKind_GNU_XList(X) - DW_AttribKind_LLVM_XList(X) - DW_AttribKind_APPLE_XList(X) - DW_AttribKind_MIPS_XList(X) + DW_AttribKind_V3_XList(X) + DW_AttribKind_V4_XList(X) + DW_AttribKind_V5_XList(X) + DW_AttribKind_GNU_XList(X) + DW_AttribKind_LLVM_XList(X) + DW_AttribKind_APPLE_XList(X) + DW_AttribKind_MIPS_XList(X) #undef X DW_Attrib_UserLo = 0x2000, DW_Attrib_UserHi = 0x3fff } DW_AttribKindEnum; #define DW_ATE_XList(X) \ - X(Null, 0x00) \ - X(Address, 0x01) \ - X(Boolean, 0x02) \ - X(ComplexFloat, 0x03) \ - X(Float, 0x04) \ - X(Signed, 0x05) \ - X(SignedChar, 0x06) \ - X(Unsigned, 0x07) \ - X(UnsignedChar, 0x08) \ - X(ImaginaryFloat, 0x09) \ - X(PackedDecimal, 0x0A) \ - X(NumericString, 0x0B) \ - X(Edited, 0x0C) \ - X(SignedFixed, 0x0D) \ - X(UnsignedFixed, 0x0E) \ - X(DecimalFloat, 0x0F) \ - X(Utf, 0x10) \ - X(Ucs, 0x11) \ - X(Ascii, 0x12) +X(Null, 0x00) \ +X(Address, 0x01) \ +X(Boolean, 0x02) \ +X(ComplexFloat, 0x03) \ +X(Float, 0x04) \ +X(Signed, 0x05) \ +X(SignedChar, 0x06) \ +X(Unsigned, 0x07) \ +X(UnsignedChar, 0x08) \ +X(ImaginaryFloat, 0x09) \ +X(PackedDecimal, 0x0A) \ +X(NumericString, 0x0B) \ +X(Edited, 0x0C) \ +X(SignedFixed, 0x0D) \ +X(UnsignedFixed, 0x0E) \ +X(DecimalFloat, 0x0F) \ +X(Utf, 0x10) \ +X(Ucs, 0x11) \ +X(Ascii, 0x12) typedef U64 DW_ATE; typedef enum DW_ATEEnum @@ -1204,11 +1204,11 @@ typedef enum DW_ATEEnum } DW_ATEnum; #define DW_CallingConventionKind_XList(X) \ - X(Normal, 0x0) \ - X(Program, 0x1) \ - X(NoCall, 0x3) \ - X(PassByValue, 0x4) \ - X(PassByReference, 0x5) +X(Normal, 0x0) \ +X(Program, 0x1) \ +X(NoCall, 0x3) \ +X(PassByValue, 0x4) \ +X(PassByReference, 0x5) typedef U64 DW_CallingConventionKind; typedef enum DW_CallingConventionKindEnum @@ -1219,10 +1219,10 @@ typedef enum DW_CallingConventionKindEnum } DW_CallingConventionKindEnum; #define DW_AccessKind_XList(X) \ - X(Public, 0x00) \ - X(Private, 0x01) \ - X(Protected, 0x02) - +X(Public, 0x00) \ +X(Private, 0x01) \ +X(Protected, 0x02) + typedef U64 DW_AccessKind; typedef enum DW_AccessKindEnum { @@ -1232,9 +1232,9 @@ typedef enum DW_AccessKindEnum } DW_AccessKindEnum; #define DW_VirtualityKind_XList(X) \ - X(None, 0x00) \ - X(Virtual, 0x01) \ - X(PureVirtual, 0x02) +X(None, 0x00) \ +X(Virtual, 0x01) \ +X(PureVirtual, 0x02) typedef U64 DW_VirtualityKind; typedef enum DW_VirtualityEnum @@ -1245,14 +1245,14 @@ typedef enum DW_VirtualityEnum } DW_VirtualityEnum; #define DW_RngListEntryKind(X) \ - X(EndOfList, 0x00) \ - X(BaseAddressx, 0x01) \ - X(StartxEndx, 0x02) \ - X(StartxLength, 0x03) \ - X(OffsetPair, 0x04) \ - X(BaseAddress, 0x05) \ - X(StartEnd, 0x06) \ - X(StartLength, 0x07) +X(EndOfList, 0x00) \ +X(BaseAddressx, 0x01) \ +X(StartxEndx, 0x02) \ +X(StartxLength, 0x03) \ +X(OffsetPair, 0x04) \ +X(BaseAddress, 0x05) \ +X(StartEnd, 0x06) \ +X(StartLength, 0x07) typedef U8 DW_RLE; typedef enum DW_RLE_Enum @@ -1263,18 +1263,18 @@ typedef enum DW_RLE_Enum } DW_RLE_Enum; #define DW_LocListEntry_XList(X) \ - X(EndOfList, 0x00) \ - X(BaseAddressx, 0x01) \ - X(StartxEndx, 0x02) \ - X(StartxLength, 0x03) \ - X(OffsetPair, 0x04) \ - X(DefaultLocation, 0x05) \ - X(BaseAddress, 0x06) \ - X(StartEnd, 0x07) \ - X(StartLength, 0x08) +X(EndOfList, 0x00) \ +X(BaseAddressx, 0x01) \ +X(StartxEndx, 0x02) \ +X(StartxLength, 0x03) \ +X(OffsetPair, 0x04) \ +X(DefaultLocation, 0x05) \ +X(BaseAddress, 0x06) \ +X(StartEnd, 0x07) \ +X(StartLength, 0x08) #define DW_LocListEntry_GNU_XList(X) \ - X(GNU_ViewPair, 0x9) +X(GNU_ViewPair, 0x9) typedef U8 DW_LLE; typedef enum DW_LLE_Enum @@ -1285,12 +1285,12 @@ typedef enum DW_LLE_Enum } DW_LLEEnum; #define DW_AddrClass_XList(X) \ - X(None, 0) \ - X(Near16, 1) \ - X(Far16, 2) \ - X(Huge16, 3) \ - X(Near32, 4) \ - X(Far32, 5) +X(None, 0) \ +X(Near16, 1) \ +X(Far16, 2) \ +X(Huge16, 3) \ +X(Near32, 4) \ +X(Far32, 5) typedef U64 DW_AddrClass; typedef enum DW_AddrClassEnum @@ -1301,13 +1301,13 @@ typedef enum DW_AddrClassEnum } DW_AddrClassEnum; #define DW_CompUnitKind_XList(X) \ - X(Reserved, 0) \ - X(Compile, 1) \ - X(Type, 2) \ - X(Partial, 3) \ - X(Skeleton, 4) \ - X(SplitCompile, 5) \ - X(SplitType, 6) +X(Reserved, 0) \ +X(Compile, 1) \ +X(Type, 2) \ +X(Partial, 3) \ +X(Skeleton, 4) \ +X(SplitCompile, 5) \ +X(SplitType, 6) typedef U8 DW_CompUnitKind; typedef enum DW_CompUnitKindEnum @@ -1320,12 +1320,12 @@ typedef enum DW_CompUnitKindEnum } DW_CompUnitKindEnum; #define DW_LNCT_XList(X) \ - X(Path, 0x1) \ - X(DirectoryIndex, 0x2) \ - X(TimeStamp, 0x3) \ - X(Size, 0x4) \ - X(MD5, 0x5) \ - X(LLVM_Source, 0x2001) +X(Path, 0x1) \ +X(DirectoryIndex, 0x2) \ +X(TimeStamp, 0x3) \ +X(Size, 0x4) \ +X(MD5, 0x5) \ +X(LLVM_Source, 0x2001) typedef U64 DW_LNCT; typedef enum DW_LNCTEnum @@ -1338,43 +1338,43 @@ typedef enum DW_LNCTEnum } DW_LNCTEnum; #define DW_CFA_Kind1_XList(X) \ - X(Nop, 0x0) \ - X(SetLoc, 0x1) \ - X(AdvanceLoc1, 0x2) \ - X(AdvanceLoc2, 0x3) \ - X(AdvanceLoc4, 0x4) \ - X(OffsetExt, 0x5) \ - X(RestoreExt, 0x6) \ - X(Undefined, 0x7) \ - X(SameValue, 0x8) \ - X(Register, 0x9) \ - X(RememberState, 0xA) \ - X(RestoreState, 0xB) \ - X(DefCfa, 0xC) \ - X(DefCfaRegister, 0xD) \ - X(DefCfaOffset, 0xE) \ - X(DefCfaExpr, 0xF) \ - X(Expr, 0x10) \ - X(OffsetExtSf, 0x11) \ - X(DefCfaSf, 0x12) \ - X(DefCfaOffsetSf, 0x13) \ - X(ValOffset, 0x14) \ - X(ValOffsetSf, 0x15) \ - X(ValExpr, 0x16) +X(Nop, 0x0) \ +X(SetLoc, 0x1) \ +X(AdvanceLoc1, 0x2) \ +X(AdvanceLoc2, 0x3) \ +X(AdvanceLoc4, 0x4) \ +X(OffsetExt, 0x5) \ +X(RestoreExt, 0x6) \ +X(Undefined, 0x7) \ +X(SameValue, 0x8) \ +X(Register, 0x9) \ +X(RememberState, 0xA) \ +X(RestoreState, 0xB) \ +X(DefCfa, 0xC) \ +X(DefCfaRegister, 0xD) \ +X(DefCfaOffset, 0xE) \ +X(DefCfaExpr, 0xF) \ +X(Expr, 0x10) \ +X(OffsetExtSf, 0x11) \ +X(DefCfaSf, 0x12) \ +X(DefCfaOffsetSf, 0x13) \ +X(ValOffset, 0x14) \ +X(ValOffsetSf, 0x15) \ +X(ValExpr, 0x16) #define DW_CFA_Kind2_XList(X) \ - X(AdvanceLoc, 0x40) \ - X(Offset, 0x80) \ - X(Restore, 0xC0) +X(AdvanceLoc, 0x40) \ +X(Offset, 0x80) \ +X(Restore, 0xC0) typedef U8 DW_CFA; typedef enum DW_CFAEnum { #define X(_N, _ID) DW_CFA_##_N = _ID, DW_CFA_Kind1_XList(X) - DW_CFA_Kind2_XList(X) + DW_CFA_Kind2_XList(X) #undef X - + DW_CFA_OplKind1 = DW_CFA_ValExpr, DW_CFA_OplKind2 = DW_CFA_Restore, } DW_CFAEnum; @@ -1392,327 +1392,327 @@ enum // Expression Opcodes #define DW_Expr_V3_XList(X) \ - X(Null, 0x00) \ - X(Addr, 0x03) \ - X(Deref, 0x06) \ - X(Const1U, 0x08) \ - X(Const1S, 0x09) \ - X(Const2U, 0x0a) \ - X(Const2S, 0x0b) \ - X(Const4U, 0x0c) \ - X(Const4S, 0x0d) \ - X(Const8U, 0x0e) \ - X(Const8S, 0x0f) \ - X(ConstU, 0x10) \ - X(ConstS, 0x11) \ - X(Dup, 0x12) \ - X(Drop, 0x13) \ - X(Over, 0x14) \ - X(Pick, 0x15) \ - X(Swap, 0x16) \ - X(Rot, 0x17) \ - X(XDeref, 0x18) \ - X(Abs, 0x19) \ - X(And, 0x1a) \ - X(Div, 0x1b) \ - X(Minus, 0x1c) \ - X(Mod, 0x1d) \ - X(Mul, 0x1e) \ - X(Neg, 0x1f) \ - X(Not, 0x20) \ - X(Or, 0x21) \ - X(Plus, 0x22) \ - X(PlusUConst, 0x23) \ - X(Shl, 0x24) \ - X(Shr, 0x25) \ - X(Shra, 0x26) \ - X(Xor, 0x27) \ - X(Skip, 0x2f) \ - X(Bra, 0x28) \ - X(Eq, 0x29) \ - X(Ge, 0x2a) \ - X(Gt, 0x2b) \ - X(Le, 0x2c) \ - X(Lt, 0x2d) \ - X(Ne, 0x2e) \ - X(Lit0, 0x30) \ - X(Lit1, 0x31) \ - X(Lit2, 0x32) \ - X(Lit3, 0x33) \ - X(Lit4, 0x34) \ - X(Lit5, 0x35) \ - X(Lit6, 0x36) \ - X(Lit7, 0x37) \ - X(Lit8, 0x38) \ - X(Lit9, 0x39) \ - X(Lit10, 0x3a) \ - X(Lit11, 0x3b) \ - X(Lit12, 0x3c) \ - X(Lit13, 0x3d) \ - X(Lit14, 0x3e) \ - X(Lit15, 0x3f) \ - X(Lit16, 0x40) \ - X(Lit17, 0x41) \ - X(Lit18, 0x42) \ - X(Lit19, 0x43) \ - X(Lit20, 0x44) \ - X(Lit21, 0x45) \ - X(Lit22, 0x46) \ - X(Lit23, 0x47) \ - X(Lit24, 0x48) \ - X(Lit25, 0x49) \ - X(Lit26, 0x4a) \ - X(Lit27, 0x4b) \ - X(Lit28, 0x4c) \ - X(Lit29, 0x4d) \ - X(Lit30, 0x4e) \ - X(Lit31, 0x4f) \ - X(Reg0, 0x50) \ - X(Reg1, 0x51) \ - X(Reg2, 0x52) \ - X(Reg3, 0x53) \ - X(Reg4, 0x54) \ - X(Reg5, 0x55) \ - X(Reg6, 0x56) \ - X(Reg7, 0x57) \ - X(Reg8, 0x58) \ - X(Reg9, 0x59) \ - X(Reg10, 0x5a) \ - X(Reg11, 0x5b) \ - X(Reg12, 0x5c) \ - X(Reg13, 0x5d) \ - X(Reg14, 0x5e) \ - X(Reg15, 0x5f) \ - X(Reg16, 0x60) \ - X(Reg17, 0x61) \ - X(Reg18, 0x62) \ - X(Reg19, 0x63) \ - X(Reg20, 0x64) \ - X(Reg21, 0x65) \ - X(Reg22, 0x66) \ - X(Reg23, 0x67) \ - X(Reg24, 0x68) \ - X(Reg25, 0x69) \ - X(Reg26, 0x6a) \ - X(Reg27, 0x6b) \ - X(Reg28, 0x6c) \ - X(Reg29, 0x6d) \ - X(Reg30, 0x6e) \ - X(Reg31, 0x6f) \ - X(BReg0, 0x70) \ - X(BReg1, 0x71) \ - X(BReg2, 0x72) \ - X(BReg3, 0x73) \ - X(BReg4, 0x74) \ - X(BReg5, 0x75) \ - X(BReg6, 0x76) \ - X(BReg7, 0x77) \ - X(BReg8, 0x78) \ - X(BReg9, 0x79) \ - X(BReg10, 0x7a) \ - X(BReg11, 0x7b) \ - X(BReg12, 0x7c) \ - X(BReg13, 0x7d) \ - X(BReg14, 0x7e) \ - X(BReg15, 0x7f) \ - X(BReg16, 0x80) \ - X(BReg17, 0x81) \ - X(BReg18, 0x82) \ - X(BReg19, 0x83) \ - X(BReg20, 0x84) \ - X(BReg21, 0x85) \ - X(BReg22, 0x86) \ - X(BReg23, 0x87) \ - X(BReg24, 0x88) \ - X(BReg25, 0x89) \ - X(BReg26, 0x8a) \ - X(BReg27, 0x8b) \ - X(BReg28, 0x8c) \ - X(BReg29, 0x8d) \ - X(BReg30, 0x8e) \ - X(BReg31, 0x8f) \ - X(RegX, 0x90) \ - X(FBReg, 0x91) \ - X(BRegX, 0x92) \ - X(Piece, 0x93) \ - X(DerefSize, 0x94) \ - X(XDerefSize, 0x95) \ - X(Nop, 0x96) \ - X(PushObjectAddress, 0x97) \ - X(Call2, 0x98) \ - X(Call4, 0x99) \ - X(CallRef, 0x9a) \ - X(FormTlsAddress, 0x9b) \ - X(CallFrameCfa, 0x9c) \ - X(BitPiece, 0x9d) +X(Null, 0x00) \ +X(Addr, 0x03) \ +X(Deref, 0x06) \ +X(Const1U, 0x08) \ +X(Const1S, 0x09) \ +X(Const2U, 0x0a) \ +X(Const2S, 0x0b) \ +X(Const4U, 0x0c) \ +X(Const4S, 0x0d) \ +X(Const8U, 0x0e) \ +X(Const8S, 0x0f) \ +X(ConstU, 0x10) \ +X(ConstS, 0x11) \ +X(Dup, 0x12) \ +X(Drop, 0x13) \ +X(Over, 0x14) \ +X(Pick, 0x15) \ +X(Swap, 0x16) \ +X(Rot, 0x17) \ +X(XDeref, 0x18) \ +X(Abs, 0x19) \ +X(And, 0x1a) \ +X(Div, 0x1b) \ +X(Minus, 0x1c) \ +X(Mod, 0x1d) \ +X(Mul, 0x1e) \ +X(Neg, 0x1f) \ +X(Not, 0x20) \ +X(Or, 0x21) \ +X(Plus, 0x22) \ +X(PlusUConst, 0x23) \ +X(Shl, 0x24) \ +X(Shr, 0x25) \ +X(Shra, 0x26) \ +X(Xor, 0x27) \ +X(Skip, 0x2f) \ +X(Bra, 0x28) \ +X(Eq, 0x29) \ +X(Ge, 0x2a) \ +X(Gt, 0x2b) \ +X(Le, 0x2c) \ +X(Lt, 0x2d) \ +X(Ne, 0x2e) \ +X(Lit0, 0x30) \ +X(Lit1, 0x31) \ +X(Lit2, 0x32) \ +X(Lit3, 0x33) \ +X(Lit4, 0x34) \ +X(Lit5, 0x35) \ +X(Lit6, 0x36) \ +X(Lit7, 0x37) \ +X(Lit8, 0x38) \ +X(Lit9, 0x39) \ +X(Lit10, 0x3a) \ +X(Lit11, 0x3b) \ +X(Lit12, 0x3c) \ +X(Lit13, 0x3d) \ +X(Lit14, 0x3e) \ +X(Lit15, 0x3f) \ +X(Lit16, 0x40) \ +X(Lit17, 0x41) \ +X(Lit18, 0x42) \ +X(Lit19, 0x43) \ +X(Lit20, 0x44) \ +X(Lit21, 0x45) \ +X(Lit22, 0x46) \ +X(Lit23, 0x47) \ +X(Lit24, 0x48) \ +X(Lit25, 0x49) \ +X(Lit26, 0x4a) \ +X(Lit27, 0x4b) \ +X(Lit28, 0x4c) \ +X(Lit29, 0x4d) \ +X(Lit30, 0x4e) \ +X(Lit31, 0x4f) \ +X(Reg0, 0x50) \ +X(Reg1, 0x51) \ +X(Reg2, 0x52) \ +X(Reg3, 0x53) \ +X(Reg4, 0x54) \ +X(Reg5, 0x55) \ +X(Reg6, 0x56) \ +X(Reg7, 0x57) \ +X(Reg8, 0x58) \ +X(Reg9, 0x59) \ +X(Reg10, 0x5a) \ +X(Reg11, 0x5b) \ +X(Reg12, 0x5c) \ +X(Reg13, 0x5d) \ +X(Reg14, 0x5e) \ +X(Reg15, 0x5f) \ +X(Reg16, 0x60) \ +X(Reg17, 0x61) \ +X(Reg18, 0x62) \ +X(Reg19, 0x63) \ +X(Reg20, 0x64) \ +X(Reg21, 0x65) \ +X(Reg22, 0x66) \ +X(Reg23, 0x67) \ +X(Reg24, 0x68) \ +X(Reg25, 0x69) \ +X(Reg26, 0x6a) \ +X(Reg27, 0x6b) \ +X(Reg28, 0x6c) \ +X(Reg29, 0x6d) \ +X(Reg30, 0x6e) \ +X(Reg31, 0x6f) \ +X(BReg0, 0x70) \ +X(BReg1, 0x71) \ +X(BReg2, 0x72) \ +X(BReg3, 0x73) \ +X(BReg4, 0x74) \ +X(BReg5, 0x75) \ +X(BReg6, 0x76) \ +X(BReg7, 0x77) \ +X(BReg8, 0x78) \ +X(BReg9, 0x79) \ +X(BReg10, 0x7a) \ +X(BReg11, 0x7b) \ +X(BReg12, 0x7c) \ +X(BReg13, 0x7d) \ +X(BReg14, 0x7e) \ +X(BReg15, 0x7f) \ +X(BReg16, 0x80) \ +X(BReg17, 0x81) \ +X(BReg18, 0x82) \ +X(BReg19, 0x83) \ +X(BReg20, 0x84) \ +X(BReg21, 0x85) \ +X(BReg22, 0x86) \ +X(BReg23, 0x87) \ +X(BReg24, 0x88) \ +X(BReg25, 0x89) \ +X(BReg26, 0x8a) \ +X(BReg27, 0x8b) \ +X(BReg28, 0x8c) \ +X(BReg29, 0x8d) \ +X(BReg30, 0x8e) \ +X(BReg31, 0x8f) \ +X(RegX, 0x90) \ +X(FBReg, 0x91) \ +X(BRegX, 0x92) \ +X(Piece, 0x93) \ +X(DerefSize, 0x94) \ +X(XDerefSize, 0x95) \ +X(Nop, 0x96) \ +X(PushObjectAddress, 0x97) \ +X(Call2, 0x98) \ +X(Call4, 0x99) \ +X(CallRef, 0x9a) \ +X(FormTlsAddress, 0x9b) \ +X(CallFrameCfa, 0x9c) \ +X(BitPiece, 0x9d) #define DW_Expr_V4_XList(X) \ - X(ImplicitValue, 0x9e) \ - X(StackValue, 0x9f) +X(ImplicitValue, 0x9e) \ +X(StackValue, 0x9f) #define DW_Expr_V5_XList(X) \ - X(ImplicitPointer, 0xa0) \ - X(Addrx, 0xa1) \ - X(Constx, 0xa2) \ - X(EntryValue, 0xa3) \ - X(ConstType, 0xa4) \ - X(RegvalType, 0xa5) \ - X(DerefType, 0xa6) \ - X(XderefType, 0xa7) \ - X(Convert, 0xa8) \ - X(ReInterpret, 0xa9) +X(ImplicitPointer, 0xa0) \ +X(Addrx, 0xa1) \ +X(Constx, 0xa2) \ +X(EntryValue, 0xa3) \ +X(ConstType, 0xa4) \ +X(RegvalType, 0xa5) \ +X(DerefType, 0xa6) \ +X(XderefType, 0xa7) \ +X(Convert, 0xa8) \ +X(ReInterpret, 0xa9) #define DW_Expr_GNU_XList(X) \ - X(GNU_PushTlsAddress, 0xe0) \ - X(GNU_UnInit, 0xf0) \ - X(GNU_ImplicitPointer, 0xf2) \ - X(GNU_EntryValue, 0xf3) \ - X(GNU_ConstType, 0xf4) \ - X(GNU_RegvalType, 0xf5) \ - X(GNU_DerefType, 0xf6) \ - X(GNU_Convert, 0xf7) \ - X(GNU_ParameterRef, 0xfa) \ - X(GNU_AddrIndex, 0xfb) \ - X(GNU_ConstIndex, 0xfc) - +X(GNU_PushTlsAddress, 0xe0) \ +X(GNU_UnInit, 0xf0) \ +X(GNU_ImplicitPointer, 0xf2) \ +X(GNU_EntryValue, 0xf3) \ +X(GNU_ConstType, 0xf4) \ +X(GNU_RegvalType, 0xf5) \ +X(GNU_DerefType, 0xf6) \ +X(GNU_Convert, 0xf7) \ +X(GNU_ParameterRef, 0xfa) \ +X(GNU_AddrIndex, 0xfb) \ +X(GNU_ConstIndex, 0xfc) + typedef U64 DW_ExprOp; typedef enum DW_ExprOpEnum { #define X(_N, _ID) DW_ExprOp_##_N = _ID, DW_Expr_V3_XList(X) - DW_Expr_V4_XList(X) - DW_Expr_V5_XList(X) - DW_Expr_GNU_XList(X) + DW_Expr_V4_XList(X) + DW_Expr_V5_XList(X) + DW_Expr_GNU_XList(X) #undef X } DW_ExprOpEnum; //- Regs #define DW_Regs_X86_XList(X) \ - X(Eax, 0, eax, 0, 4) \ - X(Ecx, 1, ecx, 0, 4) \ - X(Edx, 2, edx, 0, 4) \ - X(Ebx, 3, ebx, 0, 4) \ - X(Esp, 4, esp, 0, 4) \ - X(Ebp, 5, ebp, 0, 4) \ - X(Esi, 6, esi, 0, 4) \ - X(Edi, 7, edi, 0, 4) \ - X(Eip, 8, eip, 0, 4) \ - X(Eflags, 9, eflags, 0, 4) \ - X(Trapno, 10, nil, 0, 0) \ - X(St0, 11, st0, 0, 10) \ - X(St1, 12, st1, 0, 10) \ - X(St2, 13, st2, 0, 10) \ - X(St3, 14, st3, 0, 10) \ - X(St4, 15, st4, 0, 10) \ - X(St5, 16, st5, 0, 10) \ - X(St6, 17, st6, 0, 10) \ - X(St7, 18, st7, 0, 10) \ - X(Xmm0, 21, ymm0, 0, 16) \ - X(Xmm1, 22, ymm1, 0, 16) \ - X(Xmm2, 23, ymm2, 0, 16) \ - X(Xmm3, 24, ymm3, 0, 16) \ - X(Xmm4, 25, ymm4, 0, 16) \ - X(Xmm5, 26, ymm5, 0, 16) \ - X(Xmm6, 27, ymm6, 0, 16) \ - X(Xmm7, 28, ymm7, 0, 16) \ - X(Mm0, 29, fpr0, 0, 8) \ - X(Mm1, 30, fpr1, 0, 8) \ - X(Mm2, 31, fpr2, 0, 8) \ - X(Mm3, 32, fpr3, 0, 8) \ - X(Mm4, 33, fpr4, 0, 8) \ - X(Mm5, 34, fpr5, 0, 8) \ - X(Mm6, 35, fpr6, 0, 8) \ - X(Mm7, 36, fpr7, 0, 8) \ - X(Fcw, 37, fcw, 0, 2) \ - X(Fsw, 38, fsw, 0, 2) \ - X(Mxcsr, 39, mxcsr, 0, 4) \ - X(Es, 40, es, 0, 2) \ - X(Cs, 41, cs, 0, 2) \ - X(Ss, 42, ss, 0, 2) \ - X(Ds, 43, ds, 0, 2) \ - X(Fs, 44, fs, 0, 2) \ - X(Gs, 45, gs, 0, 2) \ - X(Tr, 48, nil, 0, 0) \ - X(Ldtr, 49, nil, 0, 0) +X(Eax, 0, eax, 0, 4) \ +X(Ecx, 1, ecx, 0, 4) \ +X(Edx, 2, edx, 0, 4) \ +X(Ebx, 3, ebx, 0, 4) \ +X(Esp, 4, esp, 0, 4) \ +X(Ebp, 5, ebp, 0, 4) \ +X(Esi, 6, esi, 0, 4) \ +X(Edi, 7, edi, 0, 4) \ +X(Eip, 8, eip, 0, 4) \ +X(Eflags, 9, eflags, 0, 4) \ +X(Trapno, 10, nil, 0, 0) \ +X(St0, 11, st0, 0, 10) \ +X(St1, 12, st1, 0, 10) \ +X(St2, 13, st2, 0, 10) \ +X(St3, 14, st3, 0, 10) \ +X(St4, 15, st4, 0, 10) \ +X(St5, 16, st5, 0, 10) \ +X(St6, 17, st6, 0, 10) \ +X(St7, 18, st7, 0, 10) \ +X(Xmm0, 21, ymm0, 0, 16) \ +X(Xmm1, 22, ymm1, 0, 16) \ +X(Xmm2, 23, ymm2, 0, 16) \ +X(Xmm3, 24, ymm3, 0, 16) \ +X(Xmm4, 25, ymm4, 0, 16) \ +X(Xmm5, 26, ymm5, 0, 16) \ +X(Xmm6, 27, ymm6, 0, 16) \ +X(Xmm7, 28, ymm7, 0, 16) \ +X(Mm0, 29, fpr0, 0, 8) \ +X(Mm1, 30, fpr1, 0, 8) \ +X(Mm2, 31, fpr2, 0, 8) \ +X(Mm3, 32, fpr3, 0, 8) \ +X(Mm4, 33, fpr4, 0, 8) \ +X(Mm5, 34, fpr5, 0, 8) \ +X(Mm6, 35, fpr6, 0, 8) \ +X(Mm7, 36, fpr7, 0, 8) \ +X(Fcw, 37, fcw, 0, 2) \ +X(Fsw, 38, fsw, 0, 2) \ +X(Mxcsr, 39, mxcsr, 0, 4) \ +X(Es, 40, es, 0, 2) \ +X(Cs, 41, cs, 0, 2) \ +X(Ss, 42, ss, 0, 2) \ +X(Ds, 43, ds, 0, 2) \ +X(Fs, 44, fs, 0, 2) \ +X(Gs, 45, gs, 0, 2) \ +X(Tr, 48, nil, 0, 0) \ +X(Ldtr, 49, nil, 0, 0) #define DW_Regs_X64_XList(X) \ - X(Rax, 0, rax, 0, 8) \ - X(Rdx, 1, rdx, 0, 8) \ - X(Rcx, 2, rcx, 0, 8) \ - X(Rbx, 3, rbx, 0, 8) \ - X(Rsi, 4, rsi, 0, 8) \ - X(Rdi, 5, rdi, 0, 8) \ - X(Rbp, 6, rbp, 0, 8) \ - X(Rsp, 7, rsp, 0, 8) \ - X(R8, 8, r8, 0, 8) \ - X(R9, 9, r9, 0, 8) \ - X(R10, 10, r10, 0, 8) \ - X(R11, 11, r11, 0, 8) \ - X(R12, 12, r12, 0, 8) \ - X(R13, 13, r13, 0, 8) \ - X(R14, 14, r14, 0, 8) \ - X(R15, 15, r15, 0, 8) \ - X(Rip, 16, rip, 0, 8) \ - X(Xmm0, 17, zmm0, 0, 16) \ - X(Xmm1, 18, zmm1, 0, 16) \ - X(Xmm2, 19, zmm2, 0, 16) \ - X(Xmm3, 20, zmm3, 0, 16) \ - X(Xmm4, 21, zmm4, 0, 16) \ - X(Xmm5, 22, zmm5, 0, 16) \ - X(Xmm6, 23, zmm6, 0, 16) \ - X(Xmm7, 24, zmm7, 0, 16) \ - X(Xmm8, 25, zmm8, 0, 16) \ - X(Xmm9, 26, zmm9, 0, 16) \ - X(Xmm10, 27, zmm10, 0, 16) \ - X(Xmm11, 28, zmm11, 0, 16) \ - X(Xmm12, 29, zmm12, 0, 16) \ - X(Xmm13, 30, zmm13, 0, 16) \ - X(Xmm14, 31, zmm14, 0, 16) \ - X(Xmm15, 32, zmm15, 0, 16) \ - X(Xmm16, 67, zmm16, 0, 16) \ - X(Xmm17, 68, zmm17, 0, 16) \ - X(Xmm18, 69, zmm18, 0, 16) \ - X(Xmm19, 70, zmm19, 0, 16) \ - X(Xmm20, 71, zmm20, 0, 16) \ - X(Xmm21, 72, zmm21, 0, 16) \ - X(Xmm22, 73, zmm22, 0, 16) \ - X(Xmm23, 74, zmm23, 0, 16) \ - X(Xmm24, 75, zmm24, 0, 16) \ - X(Xmm25, 76, zmm25, 0, 16) \ - X(Xmm26, 77, zmm26, 0, 16) \ - X(Xmm27, 78, zmm27, 0, 16) \ - X(Xmm28, 79, zmm28, 0, 16) \ - X(Xmm29, 80, zmm29, 0, 16) \ - X(Xmm30, 81, zmm30, 0, 16) \ - X(Xmm31, 82, zmm31, 0, 16) \ - X(St0, 33, st0, 0, 10) \ - X(St1, 34, st1, 0, 10) \ - X(St2, 35, st2, 0, 10) \ - X(St3, 36, st3, 0, 10) \ - X(St4, 37, st4, 0, 10) \ - X(St5, 38, st5, 0, 10) \ - X(St6, 39, st6, 0, 10) \ - X(St7, 40, st7, 0, 10) \ - X(Mm0, 41, fpr0, 0, 8) \ - X(Mm1, 42, fpr1, 0, 8) \ - X(Mm2, 43, fpr2, 0, 8) \ - X(Mm3, 44, fpr3, 0, 8) \ - X(Mm4, 45, fpr4, 0, 8) \ - X(Mm5, 46, fpr5, 0, 8) \ - X(Mm6, 47, fpr6, 0, 8) \ - X(Mm7, 48, fpr7, 0, 8) \ - X(Rflags, 49, rflags, 0, 4) \ - X(Es, 50, es, 0, 2) \ - X(Cs, 51, cs, 0, 2) \ - X(Ss, 52, ss, 0, 2) \ - X(Ds, 53, ds, 0, 2) \ - X(Fs, 54, fs, 0, 2) \ - X(Gs, 55, gs, 0, 2) \ - X(FsBase, 58, nil, 0, 0) \ - X(GsBase, 59, nil, 0, 0) \ - X(Tr, 62, nil, 0, 0) \ - X(Ldtr, 63, nil, 0, 0) +X(Rax, 0, rax, 0, 8) \ +X(Rdx, 1, rdx, 0, 8) \ +X(Rcx, 2, rcx, 0, 8) \ +X(Rbx, 3, rbx, 0, 8) \ +X(Rsi, 4, rsi, 0, 8) \ +X(Rdi, 5, rdi, 0, 8) \ +X(Rbp, 6, rbp, 0, 8) \ +X(Rsp, 7, rsp, 0, 8) \ +X(R8, 8, r8, 0, 8) \ +X(R9, 9, r9, 0, 8) \ +X(R10, 10, r10, 0, 8) \ +X(R11, 11, r11, 0, 8) \ +X(R12, 12, r12, 0, 8) \ +X(R13, 13, r13, 0, 8) \ +X(R14, 14, r14, 0, 8) \ +X(R15, 15, r15, 0, 8) \ +X(Rip, 16, rip, 0, 8) \ +X(Xmm0, 17, zmm0, 0, 16) \ +X(Xmm1, 18, zmm1, 0, 16) \ +X(Xmm2, 19, zmm2, 0, 16) \ +X(Xmm3, 20, zmm3, 0, 16) \ +X(Xmm4, 21, zmm4, 0, 16) \ +X(Xmm5, 22, zmm5, 0, 16) \ +X(Xmm6, 23, zmm6, 0, 16) \ +X(Xmm7, 24, zmm7, 0, 16) \ +X(Xmm8, 25, zmm8, 0, 16) \ +X(Xmm9, 26, zmm9, 0, 16) \ +X(Xmm10, 27, zmm10, 0, 16) \ +X(Xmm11, 28, zmm11, 0, 16) \ +X(Xmm12, 29, zmm12, 0, 16) \ +X(Xmm13, 30, zmm13, 0, 16) \ +X(Xmm14, 31, zmm14, 0, 16) \ +X(Xmm15, 32, zmm15, 0, 16) \ +X(Xmm16, 67, zmm16, 0, 16) \ +X(Xmm17, 68, zmm17, 0, 16) \ +X(Xmm18, 69, zmm18, 0, 16) \ +X(Xmm19, 70, zmm19, 0, 16) \ +X(Xmm20, 71, zmm20, 0, 16) \ +X(Xmm21, 72, zmm21, 0, 16) \ +X(Xmm22, 73, zmm22, 0, 16) \ +X(Xmm23, 74, zmm23, 0, 16) \ +X(Xmm24, 75, zmm24, 0, 16) \ +X(Xmm25, 76, zmm25, 0, 16) \ +X(Xmm26, 77, zmm26, 0, 16) \ +X(Xmm27, 78, zmm27, 0, 16) \ +X(Xmm28, 79, zmm28, 0, 16) \ +X(Xmm29, 80, zmm29, 0, 16) \ +X(Xmm30, 81, zmm30, 0, 16) \ +X(Xmm31, 82, zmm31, 0, 16) \ +X(St0, 33, st0, 0, 10) \ +X(St1, 34, st1, 0, 10) \ +X(St2, 35, st2, 0, 10) \ +X(St3, 36, st3, 0, 10) \ +X(St4, 37, st4, 0, 10) \ +X(St5, 38, st5, 0, 10) \ +X(St6, 39, st6, 0, 10) \ +X(St7, 40, st7, 0, 10) \ +X(Mm0, 41, fpr0, 0, 8) \ +X(Mm1, 42, fpr1, 0, 8) \ +X(Mm2, 43, fpr2, 0, 8) \ +X(Mm3, 44, fpr3, 0, 8) \ +X(Mm4, 45, fpr4, 0, 8) \ +X(Mm5, 46, fpr5, 0, 8) \ +X(Mm6, 47, fpr6, 0, 8) \ +X(Mm7, 48, fpr7, 0, 8) \ +X(Rflags, 49, rflags, 0, 4) \ +X(Es, 50, es, 0, 2) \ +X(Cs, 51, cs, 0, 2) \ +X(Ss, 52, ss, 0, 2) \ +X(Ds, 53, ds, 0, 2) \ +X(Fs, 54, fs, 0, 2) \ +X(Gs, 55, gs, 0, 2) \ +X(FsBase, 58, nil, 0, 0) \ +X(GsBase, 59, nil, 0, 0) \ +X(Tr, 62, nil, 0, 0) \ +X(Ldtr, 63, nil, 0, 0) typedef U32 DW_Reg; diff --git a/src/dwarf/dwarf_coff.c b/src/dwarf/dwarf_coff.c index 423761bc..a89ec810 100644 --- a/src/dwarf/dwarf_coff.c +++ b/src/dwarf/dwarf_coff.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal B32 @@ -8,22 +8,22 @@ dw_is_dwarf_present_coff_section_table(String8 raw_image, COFF_SectionHeader *section_table) { B32 is_dwarf_present = 0; - + for (U64 i = 0; i < section_count; ++i) { COFF_SectionHeader *header = §ion_table[i]; String8 name = coff_name_from_section_header(string_table, header); - + DW_SectionKind s = dw_section_kind_from_string(name); if (s == DW_Section_Null) { s = dw_section_dwo_kind_from_string(name); } - + is_dwarf_present = s != DW_Section_Null; if (is_dwarf_present) { break; } } - + return is_dwarf_present; } @@ -36,19 +36,19 @@ dw_input_from_coff_section_table(Arena *arena, { DW_Input input = {0}; B32 sect_status[ArrayCount(input.sec)] = {0}; - + for (U64 i = 0; i < section_count; ++i) { COFF_SectionHeader *header = §ion_table[i]; Rng1U64 raw_data_range = rng_1u64(header->foff, header->foff + header->fsize); String8 name = coff_name_from_section_header(string_table, header); - + DW_SectionKind s = dw_section_kind_from_string(name); B32 is_dwo = 0; if (s == DW_Section_Null) { s = dw_section_dwo_kind_from_string(name); is_dwo = 1; } - + if (s != DW_Section_Null) { if (sect_status[s]) { Assert(!"too many debug sections with identical name, picking first"); @@ -61,7 +61,7 @@ dw_input_from_coff_section_table(Arena *arena, } } } - + return input; } diff --git a/src/dwarf/dwarf_coff.h b/src/dwarf/dwarf_coff.h index e612897a..27441198 100644 --- a/src/dwarf/dwarf_coff.h +++ b/src/dwarf/dwarf_coff.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_COFF_H diff --git a/src/dwarf/dwarf_elf.c b/src/dwarf/dwarf_elf.c index 99117b2e..9154741b 100644 --- a/src/dwarf/dwarf_elf.c +++ b/src/dwarf/dwarf_elf.c @@ -5,72 +5,75 @@ internal B32 dw_is_dwarf_present_elf_section_table(String8 raw_image, ELF_BinInfo *bin) { Temp scratch = scratch_begin(0,0); - + B32 is_dwarf_present = 0; - + ELF_Shdr64Array sections = elf_shdr64_array_from_bin(scratch.arena, raw_image, &bin->hdr); - + for (U64 i = 0; i < sections.count; ++i) { ELF_Shdr64 *shdr = §ions.v[i]; String8 name = elf_name_from_shdr64(raw_image, &bin->hdr, bin->sh_name_range, shdr); - + if (shdr->sh_type != ELF_SectionCode_ProgBits) { continue; } - + DW_SectionKind s = dw_section_kind_from_string(name); if (s == DW_Section_Null) { s = dw_section_dwo_kind_from_string(name); } - + is_dwarf_present = s != DW_Section_Null; if (is_dwarf_present) { break; } } - + scratch_end(scratch); return is_dwarf_present; } +#define SINFL_IMPLEMENTATION +#include "third_party/sinfl/sinfl.h" + internal DW_Input dw_input_from_elf_section_table(Arena *arena, String8 raw_image, ELF_BinInfo *bin) { Temp scratch = scratch_begin(&arena, 1); - + DW_Input result = {0}; B32 sect_status[ArrayCount(result.sec)] = {0}; - + ELF_Shdr64Array sections = elf_shdr64_array_from_bin(scratch.arena, raw_image, &bin->hdr); - + for (U64 sect_idx = 1; sect_idx < sections.count; ++sect_idx) { ELF_Shdr64 *shdr = §ions.v[sect_idx]; - + // skip BSS sections if (shdr->sh_type != ELF_SectionCode_ProgBits) { continue; } - + String8 name = elf_name_from_shdr64(raw_image, &bin->hdr, bin->sh_name_range, shdr); - + DW_SectionKind s = dw_section_kind_from_string(name); B32 is_dwo = 0; if (s == DW_Section_Null) { s = dw_section_dwo_kind_from_string(name); is_dwo = 1; } - + if (s != DW_Section_Null) { if (sect_status[s]) { Assert(!"too many debug sections with identical name, picking first"); } else { Rng1U64 raw_data_range = rng_1u64(shdr->sh_offset, shdr->sh_offset + shdr->sh_size); String8 data = str8_substr(raw_image, raw_data_range); - + // ELF was compiled with compressed debug info if (shdr->sh_flags & ELF_Shf_Compressed) { String8 comp_data_with_header = data; - + // read header ELF_Chdr64 chdr64 = {0}; U64 chdr_size = 0; @@ -86,38 +89,38 @@ dw_input_from_elf_section_table(Arena *arena, String8 raw_image, ELF_BinInfo *bi 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; + 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); @@ -126,7 +129,7 @@ dw_input_from_elf_section_table(Arena *arena, String8 raw_image, ELF_BinInfo *bi } } } - + scratch_end(scratch); return result; } diff --git a/src/dwarf/dwarf_enum.c b/src/dwarf/dwarf_enum.c index ae41b06b..bbbba08c 100644 --- a/src/dwarf/dwarf_enum.c +++ b/src/dwarf/dwarf_enum.c @@ -1,18 +1,18 @@ -// Copyright (c) 2024 Epic Games Tools +// 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; + +#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) { @@ -32,13 +32,13 @@ dw_string_from_expr_op(Arena *arena, DW_Version ver, DW_Ext ext, DW_ExprOp op) case DW_Version_2: case DW_Version_1: case DW_Version_Null: - break; + break; } - #undef X - +#undef X + result = push_str8f(arena, "%x", op); - -exit:; + + exit:; return result; } @@ -46,12 +46,12 @@ 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)); + 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 + DW_Tag_V5_XList(X) + DW_Tag_GNU_XList(X) +#undef X } return push_str8f(arena, "%llx", kind); } @@ -59,8 +59,8 @@ 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) { - #define X(_N,...) case DW_Attrib_##_N: return str8_lit(Stringify(_N)); - +#define X(_N,...) case DW_Attrib_##_N: return str8_lit(Stringify(_N)); + while (ext) { U64 z = 64-clz64(ext); if (z == 0) { @@ -68,7 +68,7 @@ dw_string_from_attrib_kind(Arena *arena, DW_Version ver, DW_Ext ext, DW_AttribKi } 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; @@ -78,7 +78,7 @@ dw_string_from_attrib_kind(Arena *arena, DW_Version ver, DW_Ext ext, DW_AttribKi default: InvalidPath; break; } } - + switch (ver) { case DW_Version_5: { switch (kind) { @@ -104,15 +104,15 @@ dw_string_from_attrib_kind(Arena *arena, DW_Version ver, DW_Ext ext, DW_AttribKi } // fall-through case DW_Version_Null: break; } - #undef X - +#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)); +#define X(_N,...) case DW_Form_##_N: return str8_lit(Stringify(_N)); switch (ver) { case DW_Version_5: { switch (kind) { @@ -132,7 +132,7 @@ dw_string_from_form_kind(Arena *arena, DW_Version ver, DW_FormKind kind) } // fall-through case DW_Version_Null: break; } - #undef X +#undef X String8 result = push_str8f(arena, "%x", kind); return result; } @@ -141,9 +141,9 @@ 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)); +#define X(_N,_ID) case DW_Language_##_N: return str8_lit(Stringify(_N)); DW_Language_XList(X) - #undef X +#undef X } return push_str8f(arena, "%x", kind); } @@ -196,9 +196,9 @@ 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)); +#define X(_N,_ID) case DW_StdOpcode_##_N: return str8_lit(Stringify(_N)); DW_StdOpcode_XList(X) - #undef X +#undef X } return push_str8f(arena, "%x", kind); } @@ -207,9 +207,9 @@ 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)); +#define X(_N,_ID) case DW_ExtOpcode_##_N: return str8_lit(Stringify(_N)); DW_ExtOpcode_XList(X) - #undef X +#undef X default: InvalidPath; break; } return push_str8f(arena, "%x", kind); @@ -244,16 +244,16 @@ dw_string_from_register(Arena *arena, Arch arch, U64 reg_id) case Arch_Null: break; case Arch_x86: { switch (reg_id) { - #define X(_N, _ID, ...) case DW_RegX86_##_N: reg_str = str8_lit(Stringify(_N)); break; +#define X(_N, _ID, ...) case DW_RegX86_##_N: reg_str = str8_lit(Stringify(_N)); break; DW_Regs_X86_XList(X) - #undef 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; +#define X(_N, _ID, ...) case DW_RegX64_##_N: reg_str = str8_lit(Stringify(_N)); break; DW_Regs_X64_XList(X) - #undef X +#undef X } } break; case Arch_arm32: NotImplemented; break; diff --git a/src/dwarf/dwarf_enum.h b/src/dwarf/dwarf_enum.h index 1a770ee9..add27760 100644 --- a/src/dwarf/dwarf_enum.h +++ b/src/dwarf/dwarf_enum.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_ENUM_H diff --git a/src/dwarf/dwarf_expr.c b/src/dwarf/dwarf_expr.c index 98309b97..63e1ea29 100644 --- a/src/dwarf/dwarf_expr.c +++ b/src/dwarf/dwarf_expr.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- analyzers @@ -10,7 +10,7 @@ dw_expr__analyze_fast(void *base, Rng1U64 range, U64 text_section_base) DW_SimpleLoc result = {DW_SimpleLocKind_Empty}; String8 expr_data = str8((U8*)data+range.min, (U8*)data+range.max); - + U8 op = 0; if (str8_deserial_read_struct(expr_data, 0, &op)) { // step params @@ -52,11 +52,11 @@ dw_expr__analyze_fast(void *base, Rng1U64 range, U64 text_section_base) { U64 x = 0; step_cursor += dw_based_range_read(base, range, step_cursor, size_param, &x); - + if (is_signed) { x = extend_sign64(x, size_param); } - + result.kind = DW_SimpleLocKind_Address; result.addr = x; } break; @@ -180,7 +180,7 @@ internal DW_ExprAnalysis dw_expr__analyze_details(void *in_base, Rng1U64 in_range, DW_ExprMachineCallConfig *call_config) { Temp scratch = scratch_begin(0, 0); - + DW_ExprAnalysis result = {0}; // are we resolving calls? @@ -560,7 +560,7 @@ dw_expr__eval(Arena *arena_optional, void *expr_base, Rng1U64 expr_range, DW_Exp { #if 0 Temp scratch = scratch_begin(&arena_optional, 1); - + DW_Location result = {0}; // setup stack @@ -655,7 +655,7 @@ dw_expr__eval(Arena *arena_optional, void *expr_base, Rng1U64 expr_range, DW_Exp { U64 offset = 0; step_cursor += dw_based_range_read(base, range, step_cursor, 8, &offset); - + // earlier versions of GCC emit TLS offset with DW_ExprOp_Addr. B32 is_text_relative; { @@ -663,9 +663,9 @@ dw_expr__eval(Arena *arena_optional, void *expr_base, Rng1U64 expr_range, DW_Exp dw_based_range_read_struct(base, range, step_cursor, &next_op); is_text_relative = (next_op != DW_ExprOp_GNU_PushTlsAddress); } - + U64 addr = offset; - + if (is_text_relative) { if (config->text_section_base != 0) { addr += *config->text_section_base; @@ -675,7 +675,7 @@ dw_expr__eval(Arena *arena_optional, void *expr_base, Rng1U64 expr_range, DW_Exp goto finish; } } - + dw_expr__stack_push(scratch.arena, &stack, addr); } break; @@ -748,7 +748,7 @@ dw_expr__eval(Arena *arena_optional, void *expr_base, Rng1U64 expr_range, DW_Exp U64 reg_idx = 0; S64 offset = 0; step_cursor += dw_based_range_read_uleb128(base, range, step_cursor, ®_idx); step_cursor += dw_based_range_read_sleb128(base, range, step_cursor, &offset); - + DW_RegsX64 *regs = config->regs; if (regs != 0) { if (reg_idx < ArrayCount(regs->r)) { @@ -816,7 +816,7 @@ dw_expr__eval(Arena *arena_optional, void *expr_base, Rng1U64 expr_range, DW_Exp case DW_ExprOp_Deref: { U64 addr = dw_expr__stack_pop(&stack); - + B32 read_success = 0; if (config->read_memory) { U64 x = 0; @@ -825,7 +825,7 @@ dw_expr__eval(Arena *arena_optional, void *expr_base, Rng1U64 expr_range, DW_Exp read_success = 1; } } - + if (!read_success) { stashed_loc.kind = DW_SimpleLocKind_Fail; stashed_loc.fail_kind = DW_LocFailKind_MissingMemory; @@ -838,10 +838,10 @@ dw_expr__eval(Arena *arena_optional, void *expr_base, Rng1U64 expr_range, DW_Exp { U64 raw_size = 0; step_cursor += dw_based_range_read(base, range, step_cursor, 1, &raw_size); - + U64 size = ClampTop(raw_size, 8); U64 addr = dw_expr__stack_pop(&stack); - + B32 read_success = 0; if (config->read_memory) { U64 x = 0; @@ -883,7 +883,7 @@ dw_expr__eval(Arena *arena_optional, void *expr_base, Rng1U64 expr_range, DW_Exp case DW_ExprOp_FormTlsAddress: { S64 s = (S64)dw_expr__stack_pop(&stack); - + if (config->tls_address != 0) { U64 x = *config->tls_address + s; dw_expr__stack_push(scratch.arena, &stack, x); diff --git a/src/dwarf/dwarf_expr.h b/src/dwarf/dwarf_expr.h index 0d8cb10a..9daf7f73 100644 --- a/src/dwarf/dwarf_expr.h +++ b/src/dwarf/dwarf_expr.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_EXPR_H diff --git a/src/dwarf/dwarf_parse.c b/src/dwarf/dwarf_parse.c index a8722d0e..67fd831d 100644 --- a/src/dwarf/dwarf_parse.c +++ b/src/dwarf/dwarf_parse.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U64 @@ -30,14 +30,14 @@ str8_deserial_read_dwarf_uint(String8 string, U64 off, DW_Format format, U64 *ui { U64 bytes_read = 0; switch (format) { - case DW_Format_Null: break; - case DW_Format_32Bit: { - *uint_out &= (U64)max_U32; - bytes_read = str8_deserial_read(string, off, uint_out, sizeof(U32), sizeof(U32)); - } break; - case DW_Format_64Bit: { - bytes_read = str8_deserial_read_struct(string, off, uint_out); - } break; + case DW_Format_Null: break; + case DW_Format_32Bit: { + *uint_out &= (U64)max_U32; + bytes_read = str8_deserial_read(string, off, uint_out, sizeof(U32), sizeof(U32)); + } break; + case DW_Format_64Bit: { + bytes_read = str8_deserial_read_struct(string, off, uint_out); + } break; } return bytes_read; } @@ -52,18 +52,18 @@ str8_deserial_read_uleb128(String8 string, U64 off, U64 *value_out) { U8 byte = 0; U64 bytes_read = str8_deserial_read_struct(string, cursor, &byte); - + if(bytes_read != sizeof(byte)) { break; } - + U8 val = byte & 0x7fu; value |= ((U64)val) << shift; - + cursor += bytes_read; shift += 7u; - + if((byte & 0x80u) == 0) { break; @@ -91,13 +91,13 @@ str8_deserial_read_sleb128(String8 string, U64 off, S64 *value_out) { break; } - + U8 val = byte & 0x7fu; value |= ((U64)val) << shift; - + cursor += bytes_read; shift += 7u; - + if((byte & 0x80u) == 0) { if(shift < sizeof(value) * 8 && (byte & 0x40u) != 0) @@ -119,7 +119,7 @@ internal U64 str8_deserial_read_uleb128_array(Arena *arena, String8 string, U64 off, U64 count, U64 **arr_out) { Temp temp = temp_begin(arena); - + U64 *arr = push_array(arena, U64, count); U64 i, cursor; for (i = 0, cursor = off; i < count; ++i) { @@ -129,7 +129,7 @@ str8_deserial_read_uleb128_array(Arena *arena, String8 string, U64 off, U64 coun } cursor += read_size; } - + U64 bytes_read = 0; if (i == count) { *arr_out = arr; @@ -138,7 +138,7 @@ str8_deserial_read_uleb128_array(Arena *arena, String8 string, U64 off, U64 coun temp_end(temp); *arr_out = 0; } - + return bytes_read; } @@ -146,7 +146,7 @@ internal U64 str8_deserial_read_sleb128_array(Arena *arena, String8 string, U64 off, U64 count, S64 **arr_out) { Temp temp = temp_begin(arena); - + S64 *arr = push_array(arena, S64, count); U64 i, cursor; for (i = 0, cursor = off; i < count; ++i) { @@ -156,7 +156,7 @@ str8_deserial_read_sleb128_array(Arena *arena, String8 string, U64 off, U64 coun } cursor += read_size; } - + U64 bytes_read = 0; if (i == count) { *arr_out = arr; @@ -165,7 +165,7 @@ str8_deserial_read_sleb128_array(Arena *arena, String8 string, U64 off, U64 coun temp_end(temp); *arr_out = 0; } - + return bytes_read; } @@ -174,8 +174,8 @@ dw_section_kind_from_string(String8 string) { DW_SectionKind s = DW_Section_Null; #define X(_K,_L,_M,_W) \ - if (str8_match_lit(_L, string, 0)) { s = DW_Section_##_K; } \ - if (str8_match_lit(_M, string, 0)) { s = DW_Section_##_K; } +if (str8_match_lit(_L, string, 0)) { s = DW_Section_##_K; } \ +if (str8_match_lit(_M, string, 0)) { s = DW_Section_##_K; } DW_SectionKind_XList(X) #undef X return s; @@ -186,7 +186,7 @@ dw_section_dwo_kind_from_string(String8 string) { DW_SectionKind s = DW_Section_Null; #define X(_K,_L,_M,_W) \ - if (str8_match_lit(_W, string, 0)) { s = DW_Section_##_K; } +if (str8_match_lit(_W, string, 0)) { s = DW_Section_##_K; } DW_SectionKind_XList(X) #undef X return s; @@ -196,27 +196,27 @@ internal Rng1U64List dw_unit_ranges_from_data(Arena *arena, String8 data) { Rng1U64List result = {0}; - + for (U64 cursor = 0; cursor < data.size; ) { // read CU size U64 cu_size = 0; U64 cu_size_size = str8_deserial_read_dwarf_packed_size(data, cursor, &cu_size); - + // was read ok? if (cu_size_size == 0) { break; } - + if (cu_size > 0) { // push unit range rng1u64_list_push(arena, &result, rng_1u64(cursor, cursor+cu_size+cu_size_size)); } - + // advance cursor += cu_size_size; cursor += cu_size; } - + return result; } @@ -224,21 +224,21 @@ internal U64 dw_read_list_unit_header_addr(String8 unit_data, DW_ListUnit *lu_out) { U64 header_size = 0; - + U64 unit_length = 0; U64 unit_length_size = str8_deserial_read_dwarf_packed_size(unit_data, 0, &unit_length); - + if (unit_length_size) { DW_Version version = DW_Version_Null; U64 version_size = str8_deserial_read_struct(unit_data, unit_length_size, &version); - + if (version_size) { if (version >= DW_Version_5) { U8 address_size = 0; U64 address_size_size = str8_deserial_read_struct(unit_data, unit_length_size + version_size, &address_size); - + if (address_size_size && address_size) { U8 segment_selector_size = 0; U64 segment_selector_size_size = str8_deserial_read_struct(unit_data, @@ -246,7 +246,7 @@ dw_read_list_unit_header_addr(String8 unit_data, DW_ListUnit *lu_out) &segment_selector_size); if (segment_selector_size_size) { header_size = unit_length_size + version_size + address_size_size + segment_selector_size_size; - + lu_out->version = version; lu_out->segment_selector_size = segment_selector_size; lu_out->address_size = address_size; @@ -257,7 +257,7 @@ dw_read_list_unit_header_addr(String8 unit_data, DW_ListUnit *lu_out) } } } - + return header_size; } @@ -265,21 +265,21 @@ internal U64 dw_read_list_unit_header_str_offsets(String8 unit_data, DW_ListUnit *lu_out) { U64 header_size = 0; - + U64 unit_length = 0; U64 unit_length_size = str8_deserial_read_dwarf_packed_size(unit_data, 0, &unit_length); - + if (unit_length_size) { DW_Version version = DW_Version_Null; U64 version_size = str8_deserial_read_struct(unit_data, unit_length_size, &version); - + if (version >= DW_Version_5) { U16 padding = 0; U64 padding_size = str8_deserial_read_struct(unit_data, unit_length_size + version_size, &padding); - + if (padding_size && padding == 0) { header_size = unit_length_size + version_size + padding_size; - + lu_out->version = version; lu_out->address_size = 0; lu_out->segment_selector_size = 0; @@ -288,7 +288,7 @@ dw_read_list_unit_header_str_offsets(String8 unit_data, DW_ListUnit *lu_out) } } } - + return header_size; } @@ -296,29 +296,29 @@ internal U64 dw_read_list_unit_header_list(String8 unit_data, DW_ListUnit *lu_out) { U64 header_size = 0; - + U64 unit_length = 0; U64 unit_length_size = str8_deserial_read_dwarf_packed_size(unit_data, 0, &unit_length); - + if (unit_length_size) { DW_Version version = DW_Version_Null; U64 version_size = str8_deserial_read_struct(unit_data, unit_length_size, &version); - + if (version >= DW_Version_5) { U8 address_size = 0; U64 address_size_size = str8_deserial_read_struct(unit_data, unit_length_size + version_size, &address_size); - + if (address_size_size && address_size > 0) { U8 segment_selector_size = 0; U64 segment_selector_size_size = str8_deserial_read_struct(unit_data, unit_length_size + version_size + address_size_size, &segment_selector_size); - + if (segment_selector_size_size) { U32 offset_entry_count = 0; U64 offset_entry_count_size = str8_deserial_read_struct(unit_data, unit_length_size + version_size + address_size_size + segment_selector_size, &offset_entry_count); - + if (offset_entry_count_size) { header_size = unit_length_size + version_size + address_size_size + segment_selector_size_size + offset_entry_count_size; - + lu_out->version = version; lu_out->address_size = address_size; lu_out->segment_selector_size = segment_selector_size; @@ -329,7 +329,7 @@ dw_read_list_unit_header_list(String8 unit_data, DW_ListUnit *lu_out) } } } - + return header_size; } @@ -337,69 +337,69 @@ internal DW_ListUnitInput dw_list_unit_input_from_input(Arena *arena, DW_Input *input) { Temp scratch = scratch_begin(&arena, 1); - + DW_ListUnitInput result = {0}; - + DW_Section debug_addr = input->sec[DW_Section_Addr]; { String8 data = debug_addr.data; Rng1U64List unit_ranges = dw_unit_ranges_from_data(scratch.arena, data); - + result.addr_ranges = rng1u64_array_from_list(arena, &unit_ranges); result.addr_count = unit_ranges.count; result.addrs = push_array(arena, DW_ListUnit, unit_ranges.count); - + for (U64 unit_idx = 0; unit_idx < result.addr_ranges.count; ++unit_idx) { String8 unit_data = str8_substr(debug_addr.data, result.addr_ranges.v[unit_idx]); dw_read_list_unit_header_addr(unit_data, &result.addrs[unit_idx]); } } - + DW_Section debug_str_offsets = input->sec[DW_Section_StrOffsets]; { String8 data = debug_str_offsets.data; Rng1U64List unit_ranges = dw_unit_ranges_from_data(scratch.arena, data); - + result.str_offset_ranges = rng1u64_array_from_list(arena, &unit_ranges); result.str_offset_count = unit_ranges.count; result.str_offsets = push_array(arena, DW_ListUnit, unit_ranges.count); - + for (U64 unit_idx = 0; unit_idx < result.str_offset_ranges.count; ++unit_idx) { String8 unit_data = str8_substr(data, result.str_offset_ranges.v[unit_idx]); dw_read_list_unit_header_str_offsets(unit_data, &result.str_offsets[unit_idx]); } } - + DW_Section debug_rnglists = input->sec[DW_Section_RngLists]; { String8 data = debug_rnglists.data; Rng1U64List unit_ranges = dw_unit_ranges_from_data(scratch.arena, data); - + result.rnglist_ranges = rng1u64_array_from_list(arena, &unit_ranges); result.rnglist_count = unit_ranges.count; result.rnglists = push_array(arena, DW_ListUnit, unit_ranges.count); - + for (U64 unit_idx = 0; unit_idx < result.rnglist_ranges.count; ++unit_idx) { String8 unit_data = str8_substr(data, result.rnglist_ranges.v[unit_idx]); dw_read_list_unit_header_list(unit_data, &result.rnglists[unit_idx]); } } - + DW_Section debug_loclists = input->sec[DW_Section_LocLists]; { String8 data = debug_loclists.data; Rng1U64List unit_ranges = dw_unit_ranges_from_data(scratch.arena, data); - + result.loclist_ranges = rng1u64_array_from_list(arena, &unit_ranges); result.loclist_count = unit_ranges.count; result.loclists = push_array(arena, DW_ListUnit, unit_ranges.count); - + for (U64 unit_idx = 0; unit_idx < result.loclist_ranges.count; ++unit_idx) { String8 unit_data = str8_substr(data, result.loclist_ranges.v[unit_idx]); dw_read_list_unit_header_list(unit_data, &result.loclists[unit_idx]); } } - + scratch_end(scratch); return result; } @@ -570,12 +570,12 @@ dw_make_abbrev_table(Arena *arena, String8 abbrev_data, U64 abbrev_offset) table.count = tag_count; table.entries = push_array(arena, DW_AbbrevTableEntry, table.count); MemorySet(table.entries, 0, sizeof(DW_AbbrevTableEntry)*table.count); - + U64 tag_idx = 0; for(U64 abbrev_read_off = abbrev_offset;;) { U64 tag_abbrev_off = abbrev_read_off; - + DW_Abbrev tag; { U64 bytes_read = dw_read_abbrev_tag(abbrev_data, abbrev_read_off, &tag); @@ -643,178 +643,178 @@ dw_read_form(String8 data, DW_Form form = {0}; switch (form_kind) { - case DW_Form_Null: break; - - case DW_Form_Addr: { - bytes_read = str8_deserial_read_block(data, off, address_size, &form.addr); - } break; - case DW_Form_Block2: { - U16 size = 0; - U64 size_size = str8_deserial_read_struct(data, off, &size); - if (size_size) { - U64 block_size = str8_deserial_read_block(data, off + size_size, size, &form.block); - if (block_size) { - bytes_read = size_size + block_size; + case DW_Form_Null: break; + + case DW_Form_Addr: { + bytes_read = str8_deserial_read_block(data, off, address_size, &form.addr); + } break; + case DW_Form_Block2: { + U16 size = 0; + U64 size_size = str8_deserial_read_struct(data, off, &size); + if (size_size) { + U64 block_size = str8_deserial_read_block(data, off + size_size, size, &form.block); + if (block_size) { + bytes_read = size_size + block_size; + } } - } - } break; - case DW_Form_Block4: { - U32 size = 0; - U64 size_size = str8_deserial_read_struct(data, off, &size); - if (size_size) { - U64 block_size = str8_deserial_read_block(data, off + size_size, size, &form.block); - if (block_size) { - bytes_read = size_size + block_size; + } break; + case DW_Form_Block4: { + U32 size = 0; + U64 size_size = str8_deserial_read_struct(data, off, &size); + if (size_size) { + U64 block_size = str8_deserial_read_block(data, off + size_size, size, &form.block); + if (block_size) { + bytes_read = size_size + block_size; + } } - } - } break; - case DW_Form_Data2: { - bytes_read = str8_deserial_read_block(data, off, sizeof(U16), &form.data); - } break; - case DW_Form_Data4: { - bytes_read = str8_deserial_read_block(data, off, sizeof(U32), &form.data); - } break; - case DW_Form_Data8: { - bytes_read = str8_deserial_read_block(data, off, sizeof(U64), &form.data); - } break; - case DW_Form_String: { - bytes_read = str8_deserial_read_cstr(data, off, &form.string); - } break; - case DW_Form_Block: { - U64 size = 0; - U64 size_size = str8_deserial_read_uleb128(data, off, &size); - if (size_size) { - U64 block_size = str8_deserial_read_block(data, off + size_size, size, &form.block); - if (block_size) { - bytes_read = size_size + block_size; + } break; + case DW_Form_Data2: { + bytes_read = str8_deserial_read_block(data, off, sizeof(U16), &form.data); + } break; + case DW_Form_Data4: { + bytes_read = str8_deserial_read_block(data, off, sizeof(U32), &form.data); + } break; + case DW_Form_Data8: { + bytes_read = str8_deserial_read_block(data, off, sizeof(U64), &form.data); + } break; + case DW_Form_String: { + bytes_read = str8_deserial_read_cstr(data, off, &form.string); + } break; + case DW_Form_Block: { + U64 size = 0; + U64 size_size = str8_deserial_read_uleb128(data, off, &size); + if (size_size) { + U64 block_size = str8_deserial_read_block(data, off + size_size, size, &form.block); + if (block_size) { + bytes_read = size_size + block_size; + } } - } - } break; - case DW_Form_Block1: { - U8 size = 0; - U64 size_size = str8_deserial_read_struct(data, off, &size); - if (size_size) { - U64 block_size = str8_deserial_read_block(data, off, size, &form.block); - if (block_size == size) { - bytes_read = size_size + block_size; + } break; + case DW_Form_Block1: { + U8 size = 0; + U64 size_size = str8_deserial_read_struct(data, off, &size); + if (size_size) { + U64 block_size = str8_deserial_read_block(data, off, size, &form.block); + if (block_size == size) { + bytes_read = size_size + block_size; + } } - } - } break; - case DW_Form_Data1: { - bytes_read = str8_deserial_read_block(data, off, sizeof(U8), &form.data); - } break; - case DW_Form_Flag: { - bytes_read = str8_deserial_read_struct(data, off, &form.flag); - } break; - case DW_Form_SData: { - bytes_read = str8_deserial_read_sleb128(data, off, &form.sdata); - } break; - case DW_Form_UData: { - bytes_read = str8_deserial_read_uleb128(data, off, &form.udata); - } break; - case DW_Form_RefAddr: { - if (version < DW_Version_3) { - bytes_read = str8_deserial_read(data, off, &form.ref, address_size, address_size); - } else { + } break; + case DW_Form_Data1: { + bytes_read = str8_deserial_read_block(data, off, sizeof(U8), &form.data); + } break; + case DW_Form_Flag: { + bytes_read = str8_deserial_read_struct(data, off, &form.flag); + } break; + case DW_Form_SData: { + bytes_read = str8_deserial_read_sleb128(data, off, &form.sdata); + } break; + case DW_Form_UData: { + bytes_read = str8_deserial_read_uleb128(data, off, &form.udata); + } break; + case DW_Form_RefAddr: { + if (version < DW_Version_3) { + bytes_read = str8_deserial_read(data, off, &form.ref, address_size, address_size); + } else { + bytes_read = str8_deserial_read_dwarf_uint(data, off, unit_format, &form.ref); + } + } break; + case DW_Form_GNU_RefAlt: { bytes_read = str8_deserial_read_dwarf_uint(data, off, unit_format, &form.ref); - } - } break; - case DW_Form_GNU_RefAlt: { - bytes_read = str8_deserial_read_dwarf_uint(data, off, unit_format, &form.ref); - } break; - case DW_Form_Ref1: { - bytes_read = str8_deserial_read(data, off, &form.ref, 1, 1); - } break; - case DW_Form_Ref2: { - bytes_read = str8_deserial_read(data, off, &form.ref, 2, 2); - } break; - case DW_Form_Ref4: { - bytes_read = str8_deserial_read(data, off, &form.ref, 4, 4); - } break; - case DW_Form_Ref8: { - bytes_read = str8_deserial_read(data, off, &form.ref, 8, 8); - } break; - case DW_Form_RefUData: { - bytes_read = str8_deserial_read_uleb128(data, off, &form.ref); - } break; - case DW_Form_SecOffset: - case DW_Form_LineStrp: - case DW_Form_GNU_StrpAlt: - case DW_Form_Strp: { - bytes_read = str8_deserial_read_dwarf_uint(data, off, unit_format, &form.sec_offset); - } break; - case DW_Form_ExprLoc: { - U64 expr_size = 0; - U64 expr_size_size = str8_deserial_read_uleb128(data, off, &expr_size); - if (expr_size_size) { - if (str8_deserial_read_block(data, off + expr_size_size, expr_size, &form.exprloc)) { - bytes_read = expr_size_size + expr_size; + } break; + case DW_Form_Ref1: { + bytes_read = str8_deserial_read(data, off, &form.ref, 1, 1); + } break; + case DW_Form_Ref2: { + bytes_read = str8_deserial_read(data, off, &form.ref, 2, 2); + } break; + case DW_Form_Ref4: { + bytes_read = str8_deserial_read(data, off, &form.ref, 4, 4); + } break; + case DW_Form_Ref8: { + bytes_read = str8_deserial_read(data, off, &form.ref, 8, 8); + } break; + case DW_Form_RefUData: { + bytes_read = str8_deserial_read_uleb128(data, off, &form.ref); + } break; + case DW_Form_SecOffset: + case DW_Form_LineStrp: + case DW_Form_GNU_StrpAlt: + case DW_Form_Strp: { + bytes_read = str8_deserial_read_dwarf_uint(data, off, unit_format, &form.sec_offset); + } break; + case DW_Form_ExprLoc: { + U64 expr_size = 0; + U64 expr_size_size = str8_deserial_read_uleb128(data, off, &expr_size); + if (expr_size_size) { + if (str8_deserial_read_block(data, off + expr_size_size, expr_size, &form.exprloc)) { + bytes_read = expr_size_size + expr_size; + } } - } - } break; - case DW_Form_FlagPresent: { - form.flag = 1; - } break; - case DW_Form_RefSig8: { - //U64 ref = 0; - //bytes_read = str8_deserial_read_struct(data, off, &ref); - NotImplemented; - } break; - case DW_Form_Addrx: - case DW_Form_RngListx: - case DW_Form_Strx: { - bytes_read = str8_deserial_read_uleb128(data, off, &form.xval); - } break; - case DW_Form_RefSup4: { - //U32 ref_sup4 = 0; - //bytes_read = str8_deserial_read_struct(data, off, &ref_sup4); - NotImplemented; - } break; - case DW_Form_StrpSup: { - bytes_read = str8_deserial_read_dwarf_uint(data, off, unit_format, &form.strp_sup); - } break; - case DW_Form_Data16: { - bytes_read = str8_deserial_read_block(data, off, 16, &form.data); - } break; - case DW_Form_ImplicitConst: { - // Special case. - // Unlike other forms that have their values stored in the .debug_info section, - // This one defines it's value in the .debug_abbrev section. - form.implicit_const = implicit_const; - } break; - case DW_Form_LocListx: { + } break; + case DW_Form_FlagPresent: { + form.flag = 1; + } break; + case DW_Form_RefSig8: { + //U64 ref = 0; + //bytes_read = str8_deserial_read_struct(data, off, &ref); + NotImplemented; + } break; + case DW_Form_Addrx: + case DW_Form_RngListx: + case DW_Form_Strx: { bytes_read = str8_deserial_read_uleb128(data, off, &form.xval); - } break; - case DW_Form_RefSup8: { - NotImplemented; - } break; - case DW_Form_Strx1: { - bytes_read = str8_deserial_read(data, off, &form.xval, 1, 1); - } break; - case DW_Form_Strx2: { - bytes_read = str8_deserial_read(data, off, &form.xval, 2, 2); - } break; - case DW_Form_Strx3: { - bytes_read = str8_deserial_read(data, off, &form.xval, 3, 3); - } break; - case DW_Form_Strx4: { - bytes_read = str8_deserial_read(data, off, &form.xval, 4, 4); - } break; - case DW_Form_Addrx1: { - bytes_read = str8_deserial_read(data, off, &form.xval, 1, 1); - } break; - case DW_Form_Addrx2: { - bytes_read = str8_deserial_read(data, off, &form.xval, 2, 2); - } break; - case DW_Form_Addrx3: { - bytes_read = str8_deserial_read(data, off, &form.xval, 3, 3); - } break; - case DW_Form_Addrx4: { - bytes_read = str8_deserial_read(data, off, &form.xval, 4, 4); - } break; - default: InvalidPath; break; + } break; + case DW_Form_RefSup4: { + //U32 ref_sup4 = 0; + //bytes_read = str8_deserial_read_struct(data, off, &ref_sup4); + NotImplemented; + } break; + case DW_Form_StrpSup: { + bytes_read = str8_deserial_read_dwarf_uint(data, off, unit_format, &form.strp_sup); + } break; + case DW_Form_Data16: { + bytes_read = str8_deserial_read_block(data, off, 16, &form.data); + } break; + case DW_Form_ImplicitConst: { + // Special case. + // Unlike other forms that have their values stored in the .debug_info section, + // This one defines it's value in the .debug_abbrev section. + form.implicit_const = implicit_const; + } break; + case DW_Form_LocListx: { + bytes_read = str8_deserial_read_uleb128(data, off, &form.xval); + } break; + case DW_Form_RefSup8: { + NotImplemented; + } break; + case DW_Form_Strx1: { + bytes_read = str8_deserial_read(data, off, &form.xval, 1, 1); + } break; + case DW_Form_Strx2: { + bytes_read = str8_deserial_read(data, off, &form.xval, 2, 2); + } break; + case DW_Form_Strx3: { + bytes_read = str8_deserial_read(data, off, &form.xval, 3, 3); + } break; + case DW_Form_Strx4: { + bytes_read = str8_deserial_read(data, off, &form.xval, 4, 4); + } break; + case DW_Form_Addrx1: { + bytes_read = str8_deserial_read(data, off, &form.xval, 1, 1); + } break; + case DW_Form_Addrx2: { + bytes_read = str8_deserial_read(data, off, &form.xval, 2, 2); + } break; + case DW_Form_Addrx3: { + bytes_read = str8_deserial_read(data, off, &form.xval, 3, 3); + } break; + case DW_Form_Addrx4: { + bytes_read = str8_deserial_read(data, off, &form.xval, 4, 4); + } break; + default: InvalidPath; break; } - + if (form_out) { *form_out = form; } @@ -835,53 +835,53 @@ dw_read_tag(Arena *arena, DW_Tag *tag_out) { U64 tag_cursor = tag_off; - + // read tag abbrev id U64 tag_abbrev_id = 0; U64 tag_abbrev_id_size = str8_deserial_read_uleb128(tag_data, tag_cursor, &tag_abbrev_id); Assert(tag_abbrev_id_size); tag_cursor += tag_abbrev_id_size; - + // read tag abbrev U64 abbrev_cursor = dw_abbrev_offset_from_abbrev_id(abbrev_table, tag_abbrev_id); DW_Abbrev tag_abbrev = {0}; U64 tag_abbrev_size = dw_read_abbrev_tag(abbrev_data, abbrev_cursor, &tag_abbrev); - + // read attribs DW_AttribList attribs = {0}; if (tag_abbrev_size > 0) { abbrev_cursor += tag_abbrev_size; - + for (; tag_cursor < tag_data.size && abbrev_cursor < abbrev_data.size; ) { U64 attrib_tag_cursor = tag_cursor; U64 attrib_abbrev_off = abbrev_cursor; - + // read attrib abbrev DW_Abbrev attrib_abbrev = {0}; abbrev_cursor += dw_read_abbrev_attrib(abbrev_data, abbrev_cursor, &attrib_abbrev); if (attrib_abbrev.id == 0) { break; } - + DW_AttribKind attrib_kind = (DW_AttribKind)attrib_abbrev.id; DW_FormKind form_kind = (DW_FormKind)attrib_abbrev.sub_kind; - + // special case, allows producer to embed form in .debug_info if (form_kind == DW_Form_Indirect) { U64 form_kind_size = str8_deserial_read_uleb128(tag_data, tag_cursor, &form_kind); - + if (form_kind_size == 0) { Assert(!"unable to read indirect form kind"); break; } - + tag_cursor += form_kind_size; } - + // read form value DW_Form form = {0}; tag_cursor += dw_read_form(tag_data, tag_cursor, version, unit_format, address_size, form_kind, attrib_abbrev.const_value, &form); - + // fill out node DW_AttribNode *attrib_n = push_array(arena, DW_AttribNode, 1); attrib_n->v.info_off = tag_base + attrib_tag_cursor; @@ -890,20 +890,20 @@ dw_read_tag(Arena *arena, attrib_n->v.attrib_kind = attrib_kind; attrib_n->v.form_kind = form_kind; attrib_n->v.form = form; - + // push node to list SLLQueuePush(attribs.first, attribs.last, attrib_n); ++attribs.count; } } - + // fill out tag tag_out->abbrev_id = tag_abbrev_id; tag_out->has_children = !!(tag_abbrev.flags & DW_AbbrevFlag_HasChildren); tag_out->kind = (DW_TagKind)tag_abbrev.sub_kind; tag_out->attribs = attribs; tag_out->info_off = tag_base + tag_off; - + U64 bytes_read = tag_cursor - tag_off; return bytes_read; } @@ -1156,7 +1156,7 @@ internal DW_LocList dw_interp_loclist(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind form_kind, DW_Form form) { DW_LocList loclist = {0}; - + if (cu->version < DW_Version_5) { if (form_kind == DW_Form_SecOffset) { U64 sec_offset = max_U64; @@ -1170,7 +1170,7 @@ dw_interp_loclist(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind fo } else if (form_kind == DW_Form_Null) { Assert(!"unexpected form"); } - + String8 sec = str8_skip(input->sec[DW_Section_Loc].data, sec_offset); U64 base_addr = cu->low_pc; U64 base_sel = DW_SentinelFromSize(cu->address_size); @@ -1188,7 +1188,7 @@ dw_interp_loclist(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind fo break; } cursor += cu->address_size * 2; - + // series terminator if (range_min == 0 && range_max == 0) { break; @@ -1206,17 +1206,17 @@ dw_interp_loclist(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind fo break; } cursor += expr_size_size; - + Assert(cursor + expr_size <= sec.size); Rng1U64 expr_range = rng_1u64(cursor, ClampTop(cursor + expr_size, sec.size)); - + DW_LocNode *loc_n = push_array(arena, DW_LocNode, 1); loc_n->v.range = rng_1u64(base_addr + range_min, base_addr + range_max); loc_n->v.expr = str8_substr(sec, expr_range); - + SLLQueuePush(loclist.first, loclist.last, loc_n); ++loclist.count; - + // advance past expression cursor += expr_size; } @@ -1239,162 +1239,162 @@ dw_interp_loclist(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind fo } else if (form_kind != DW_Form_Null) { AssertAlways(!"unexpected form"); } - + for (U64 cursor = 0, keep_parsing = 1, base_addr = cu->low_pc; cursor < raw_lle.size && keep_parsing; ) { DW_LLE kind = DW_LLE_EndOfList; cursor += str8_deserial_read_struct(raw_lle, cursor, &kind); - + Rng1U64 range = {0}; switch (kind) { - default: + default: Assert(!"unknown kind"); - case DW_LLE_EndOfList: { - keep_parsing = 0; - } break; - case DW_LLE_BaseAddressx: { - if (!cu->addr_lu) { + case DW_LLE_EndOfList: { keep_parsing = 0; - break; - } - - U64 addrx = 0; - U64 addrx_size = str8_deserial_read_uleb128(raw_lle, cursor, &addrx); - if (addrx_size == 0) { - keep_parsing = 0; - break; - } - - U64 base_addr_new = dw_addr_from_list_unit(cu->addr_lu, addrx); - if (base_addr_new == max_U64) { - InvalidPath; - break; - } - - base_addr = base_addr_new; - cursor += addrx_size; - } break; - case DW_LLE_StartxEndx: { - U64 start_addrx = 0; - U64 start_addrx_size = str8_deserial_read_uleb128(raw_lle, cursor, &start_addrx); - if (start_addrx_size == 0) { - keep_parsing = 0; - break; - } - U64 end_addrx = 0; - U64 end_addrx_size = str8_deserial_read_uleb128(raw_lle, cursor + start_addrx_size, &end_addrx); - if (end_addrx_size == 0) { - keep_parsing = 0; - break; - } - cursor += start_addrx_size; - cursor += end_addrx_size; - - U64 start = dw_addr_from_list_unit(cu->addr_lu, start_addrx); - U64 end = dw_addr_from_list_unit(cu->addr_lu, end_addrx); - Assert(start != max_U64); - Assert(end != max_U64); - - range = rng_1u64(start, end); - } break; - case DW_LLE_StartxLength: { - U64 start_addrx = 0; - U64 start_addrx_size = str8_deserial_read_uleb128(raw_lle, cursor, &start_addrx); - if (start_addrx_size == 0) { - keep_parsing = 0; - break; - } - - // parse pre-standard & standard length - U64 length_off = cursor + start_addrx_size; - U64 length = 0; - U64 length_size = str8_deserial_read_uleb128(raw_lle, length_off, &length); - if (length_size == 0) { - keep_parsing = 0; - break; - } - - cursor += start_addrx_size; - cursor += length_size; - - if (cu->addr_lu) { + } break; + case DW_LLE_BaseAddressx: { + if (!cu->addr_lu) { + keep_parsing = 0; + break; + } + + U64 addrx = 0; + U64 addrx_size = str8_deserial_read_uleb128(raw_lle, cursor, &addrx); + if (addrx_size == 0) { + keep_parsing = 0; + break; + } + + U64 base_addr_new = dw_addr_from_list_unit(cu->addr_lu, addrx); + if (base_addr_new == max_U64) { + InvalidPath; + break; + } + + base_addr = base_addr_new; + cursor += addrx_size; + } break; + case DW_LLE_StartxEndx: { + U64 start_addrx = 0; + U64 start_addrx_size = str8_deserial_read_uleb128(raw_lle, cursor, &start_addrx); + if (start_addrx_size == 0) { + keep_parsing = 0; + break; + } + U64 end_addrx = 0; + U64 end_addrx_size = str8_deserial_read_uleb128(raw_lle, cursor + start_addrx_size, &end_addrx); + if (end_addrx_size == 0) { + keep_parsing = 0; + break; + } + cursor += start_addrx_size; + cursor += end_addrx_size; + U64 start = dw_addr_from_list_unit(cu->addr_lu, start_addrx); - Assert(start < max_U64); - + U64 end = dw_addr_from_list_unit(cu->addr_lu, end_addrx); + Assert(start != max_U64); + Assert(end != max_U64); + + range = rng_1u64(start, end); + } break; + case DW_LLE_StartxLength: { + U64 start_addrx = 0; + U64 start_addrx_size = str8_deserial_read_uleb128(raw_lle, cursor, &start_addrx); + if (start_addrx_size == 0) { + keep_parsing = 0; + break; + } + + // parse pre-standard & standard length + U64 length_off = cursor + start_addrx_size; + U64 length = 0; + U64 length_size = str8_deserial_read_uleb128(raw_lle, length_off, &length); + if (length_size == 0) { + keep_parsing = 0; + break; + } + + cursor += start_addrx_size; + cursor += length_size; + + if (cu->addr_lu) { + U64 start = dw_addr_from_list_unit(cu->addr_lu, start_addrx); + Assert(start < max_U64); + + range = rng_1u64(start, start + length); + } else { + Assert(!".debug_addr section is missing -- unable to interpret address index"); + } + } break; + case DW_LLE_OffsetPair: { + U64 start = 0; + U64 start_size = str8_deserial_read_uleb128(raw_lle, cursor, &start); + if (start_size == 0) { + keep_parsing = 0; + break; + } + U64 end = 0; + U64 end_size = str8_deserial_read_uleb128(raw_lle, cursor + start_size, &end); + if (end_size == 0) { + keep_parsing = 0; + break; + } + cursor += start_size; + cursor += end_size; + + range = rng_1u64(base_addr + start, base_addr + end); + } break; + case DW_LLE_DefaultLocation: { + // no range + int x = 0; + } break; + case DW_LLE_BaseAddress: { + U64 base_addr_size = str8_deserial_read(raw_lle, cursor, &base_addr, cu->address_size, cu->address_size); + if (base_addr_size == 0) { + keep_parsing = 0; + break; + } + cursor += base_addr_size; + } break; + case DW_LLE_StartEnd: { + U64 start = 0; + U64 start_size = str8_deserial_read(raw_lle, cursor, &start, cu->address_size, cu->address_size); + if (start_size == 0) { + keep_parsing = 0; + break; + } + + U64 end = 0; + U64 end_size = str8_deserial_read(raw_lle, cursor + start_size, &end, cu->address_size, cu->address_size); + if (end_size == 0) { + keep_parsing = 0; + break; + } + cursor += start_size; + cursor += end_size; + + range = rng_1u64(start, end); + } break; + case DW_LLE_StartLength: { + U64 start = 0; + U64 start_size = str8_deserial_read(raw_lle, cursor, &start, cu->address_size, cu->address_size); + if (start_size == 0) { + keep_parsing = 0; + break; + } + U64 length = 0; + U64 length_size = str8_deserial_read_uleb128(raw_lle, cursor + start_size, &length); + if (length_size == 0) { + keep_parsing = 0; + break; + } + cursor += start_size; + cursor += length_size; + range = rng_1u64(start, start + length); - } else { - Assert(!".debug_addr section is missing -- unable to interpret address index"); - } - } break; - case DW_LLE_OffsetPair: { - U64 start = 0; - U64 start_size = str8_deserial_read_uleb128(raw_lle, cursor, &start); - if (start_size == 0) { - keep_parsing = 0; - break; - } - U64 end = 0; - U64 end_size = str8_deserial_read_uleb128(raw_lle, cursor + start_size, &end); - if (end_size == 0) { - keep_parsing = 0; - break; - } - cursor += start_size; - cursor += end_size; - - range = rng_1u64(base_addr + start, base_addr + end); - } break; - case DW_LLE_DefaultLocation: { - // no range - int x = 0; - } break; - case DW_LLE_BaseAddress: { - U64 base_addr_size = str8_deserial_read(raw_lle, cursor, &base_addr, cu->address_size, cu->address_size); - if (base_addr_size == 0) { - keep_parsing = 0; - break; - } - cursor += base_addr_size; - } break; - case DW_LLE_StartEnd: { - U64 start = 0; - U64 start_size = str8_deserial_read(raw_lle, cursor, &start, cu->address_size, cu->address_size); - if (start_size == 0) { - keep_parsing = 0; - break; - } - - U64 end = 0; - U64 end_size = str8_deserial_read(raw_lle, cursor + start_size, &end, cu->address_size, cu->address_size); - if (end_size == 0) { - keep_parsing = 0; - break; - } - cursor += start_size; - cursor += end_size; - - range = rng_1u64(start, end); - } break; - case DW_LLE_StartLength: { - U64 start = 0; - U64 start_size = str8_deserial_read(raw_lle, cursor, &start, cu->address_size, cu->address_size); - if (start_size == 0) { - keep_parsing = 0; - break; - } - U64 length = 0; - U64 length_size = str8_deserial_read_uleb128(raw_lle, cursor + start_size, &length); - if (length_size == 0) { - keep_parsing = 0; - break; - } - cursor += start_size; - cursor += length_size; - - range = rng_1u64(start, start + length); - } break; + } break; } - + B32 has_expr = keep_parsing && kind != DW_LLE_BaseAddressx && kind != DW_LLE_BaseAddress; if (has_expr) { U64 expr_size = 0; @@ -1403,27 +1403,27 @@ dw_interp_loclist(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind fo keep_parsing = 0; break; } - + String8 expr = {0}; U64 expr_read_size = str8_deserial_read_block(raw_lle, cursor + expr_size_size, expr_size, &expr); if (expr_read_size != expr_size) { keep_parsing = 0; break; } - + cursor += expr_size_size; cursor += expr_size; - + DW_LocNode *loc_n = push_array(arena, DW_LocNode, 1); loc_n->v.range = range; loc_n->v.expr = expr; - + SLLQueuePush(loclist.first, loclist.last, loc_n); ++loclist.count; } } } - + return loclist; } @@ -1443,7 +1443,7 @@ internal Rng1U64List dw_interp_rnglist(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind form_kind, DW_Form form) { Rng1U64List rnglist = {0}; - + if (cu->version < DW_Version_5) { // decode section offset U64 sec_offset = max_U64; @@ -1457,7 +1457,7 @@ dw_interp_rnglist(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind fo } else if (form_kind != DW_Form_Null) { Assert(!"unexpected form"); } - + String8 sec = str8_skip(input->sec[DW_Section_Ranges].data, sec_offset); U64 base_addr = cu->low_pc; U64 base_sel = DW_SentinelFromSize(cu->address_size); @@ -1475,7 +1475,7 @@ dw_interp_rnglist(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind fo break; } cursor += cu->address_size * 2; - + // series terminator if (range_min == 0 && range_max == 0) { break; @@ -1503,130 +1503,130 @@ dw_interp_rnglist(Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_FormKind fo } else if (form_kind != DW_Form_Null) { AssertAlways(!"unexpected form"); } - + U64 rle_invalid_value = DW_SentinelFromSize(cu->address_size); U64 base_addr = cu->low_pc; for (U64 cursor = 0, keep_parsing = 1; cursor < raw_rle.size && keep_parsing; ) { DW_RLE kind = DW_RLE_EndOfList; cursor += str8_deserial_read_struct(raw_rle, cursor, &kind); - + Rng1U64 range = rng_1u64(rle_invalid_value, rle_invalid_value); switch (kind) { - default: - case DW_RLE_EndOfList: { - keep_parsing = 0; - } break; - case DW_RLE_BaseAddressx: { - U64 addrx = 0; - U64 addrx_size = str8_deserial_read_uleb128(raw_rle, cursor, &addrx); - if (addrx_size == 0) { + default: + case DW_RLE_EndOfList: { keep_parsing = 0; - break; - } - if (cu->addr_lu == 0) { - keep_parsing = 0; - break; - } - U64 base_addr_new = dw_addr_from_list_unit(cu->addr_lu, addrx); - if (base_addr_new < max_U64) { - base_addr = base_addr_new; - cursor += addrx_size; - } else { - keep_parsing = 0; - Assert(!"invalid addrx"); - } - } break; - case DW_RLE_StartxLength: { - U64 start_addrx = 0; - U64 start_addrx_size = str8_deserial_read_uleb128(raw_rle, cursor, &start_addrx); - if (start_addrx_size == 0) { - keep_parsing = 0; - break; - } - U64 length = 0; - U64 length_size = str8_deserial_read_uleb128(raw_rle, cursor + start_addrx_size, &length); - if (length_size == 0) { - keep_parsing = 0; - break; - } - cursor += start_addrx_size; - cursor += length_size; - - if (cu->addr_lu) { - U64 start = dw_addr_from_list_unit(cu->addr_lu, start_addrx); - AssertAlways(start < max_U64); + } break; + case DW_RLE_BaseAddressx: { + U64 addrx = 0; + U64 addrx_size = str8_deserial_read_uleb128(raw_rle, cursor, &addrx); + if (addrx_size == 0) { + keep_parsing = 0; + break; + } + if (cu->addr_lu == 0) { + keep_parsing = 0; + break; + } + U64 base_addr_new = dw_addr_from_list_unit(cu->addr_lu, addrx); + if (base_addr_new < max_U64) { + base_addr = base_addr_new; + cursor += addrx_size; + } else { + keep_parsing = 0; + Assert(!"invalid addrx"); + } + } break; + case DW_RLE_StartxLength: { + U64 start_addrx = 0; + U64 start_addrx_size = str8_deserial_read_uleb128(raw_rle, cursor, &start_addrx); + if (start_addrx_size == 0) { + keep_parsing = 0; + break; + } + U64 length = 0; + U64 length_size = str8_deserial_read_uleb128(raw_rle, cursor + start_addrx_size, &length); + if (length_size == 0) { + keep_parsing = 0; + break; + } + cursor += start_addrx_size; + cursor += length_size; + + if (cu->addr_lu) { + U64 start = dw_addr_from_list_unit(cu->addr_lu, start_addrx); + AssertAlways(start < max_U64); + range = rng_1u64(start, start + length); + } + } break; + case DW_RLE_OffsetPair: { + U64 offset_start, offset_end = 0; + U64 offset_start_size = str8_deserial_read_uleb128(raw_rle, cursor, &offset_start); + if (offset_start_size == 0) { + keep_parsing = 0; + break; + } + U64 offset_end_size = str8_deserial_read_uleb128(raw_rle, cursor + offset_start_size, &offset_end); + if (offset_end_size == 0) { + keep_parsing = 0; + break; + } + cursor += offset_start_size; + cursor += offset_end_size; + + range = rng_1u64(base_addr + offset_start, base_addr + offset_end); + } break; + case DW_RLE_BaseAddress: { + U64 base_addr_size = str8_deserial_read(raw_rle, cursor, &base_addr, cu->address_size, cu->address_size); + if (base_addr_size == 0) { + keep_parsing = 0; + break; + } + cursor += base_addr_size; + } break; + case DW_RLE_StartEnd: { + U64 start = 0, end = 0; + + U64 start_size = str8_deserial_read(raw_rle, cursor, &start, cu->address_size, cu->address_size); + if (start_size == 0) { + keep_parsing = 0; + break; + } + U64 end_size = str8_deserial_read(raw_rle, cursor + start_size, &end, cu->address_size, cu->address_size); + if (end_size == 0) { + keep_parsing = 0; + break; + } + cursor += start_size; + cursor += end_size; + + range = rng_1u64(start, end); + } break; + case DW_RLE_StartLength: { + U64 start = 0, length = 0; + + U64 start_size = str8_deserial_read(raw_rle, cursor, &start, cu->address_size, cu->address_size); + if (start_size == 0) { + keep_parsing = 0; + break; + } + U64 length_size = str8_deserial_read_uleb128(raw_rle, cursor + start_size, &length); + if (length_size == 0) { + keep_parsing = 0; + break; + } + cursor += start_size; + cursor += length_size; + range = rng_1u64(start, start + length); - } - } break; - case DW_RLE_OffsetPair: { - U64 offset_start, offset_end = 0; - U64 offset_start_size = str8_deserial_read_uleb128(raw_rle, cursor, &offset_start); - if (offset_start_size == 0) { - keep_parsing = 0; - break; - } - U64 offset_end_size = str8_deserial_read_uleb128(raw_rle, cursor + offset_start_size, &offset_end); - if (offset_end_size == 0) { - keep_parsing = 0; - break; - } - cursor += offset_start_size; - cursor += offset_end_size; - - range = rng_1u64(base_addr + offset_start, base_addr + offset_end); - } break; - case DW_RLE_BaseAddress: { - U64 base_addr_size = str8_deserial_read(raw_rle, cursor, &base_addr, cu->address_size, cu->address_size); - if (base_addr_size == 0) { - keep_parsing = 0; - break; - } - cursor += base_addr_size; - } break; - case DW_RLE_StartEnd: { - U64 start = 0, end = 0; - - U64 start_size = str8_deserial_read(raw_rle, cursor, &start, cu->address_size, cu->address_size); - if (start_size == 0) { - keep_parsing = 0; - break; - } - U64 end_size = str8_deserial_read(raw_rle, cursor + start_size, &end, cu->address_size, cu->address_size); - if (end_size == 0) { - keep_parsing = 0; - break; - } - cursor += start_size; - cursor += end_size; - - range = rng_1u64(start, end); - } break; - case DW_RLE_StartLength: { - U64 start = 0, length = 0; - - U64 start_size = str8_deserial_read(raw_rle, cursor, &start, cu->address_size, cu->address_size); - if (start_size == 0) { - keep_parsing = 0; - break; - } - U64 length_size = str8_deserial_read_uleb128(raw_rle, cursor + start_size, &length); - if (length_size == 0) { - keep_parsing = 0; - break; - } - cursor += start_size; - cursor += length_size; - - range = rng_1u64(start, start + length); - } break; + } break; } - + if (range.min != rle_invalid_value) { rng1u64_list_push(arena, &rnglist, range); } } } - + return rnglist; } @@ -1740,15 +1740,15 @@ dw_address_from_attrib_ptr(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib) DW_FormKind form_kind = attrib->form_kind; DW_Form form = attrib->form; if (value_class == DW_AttribClass_AddrPtr) { - + if (attrib->form_kind == DW_Form_SecOffset) { - + } else { AssertAlways(!"unexpected form"); } - - + + form_kind = DW_Form_Addr; form.addr = dw_interp_addrptr(input, attrib->form_kind, attrib->form); } @@ -1836,7 +1836,7 @@ internal DW_Attrib * dw_attrib_from_tag(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { DW_Attrib *attrib = dw_attrib_from_tag_(tag, kind); - + if (attrib->attrib_kind == DW_Attrib_Null) { if (cu && cu->tag_ht) { DW_Attrib *ao_attrib = dw_attrib_from_tag_(tag, DW_Attrib_AbstractOrigin); @@ -1847,7 +1847,7 @@ dw_attrib_from_tag(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind k } } } - + return attrib; } @@ -1942,11 +1942,11 @@ dw_try_byte_size_from_tag(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, U64 *byt { 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 ); - + 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); return 1; @@ -1955,7 +1955,7 @@ dw_try_byte_size_from_tag(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, U64 *byt *byte_size_out = bit_size / 8; return 1; } - + return 0; } @@ -2011,24 +2011,24 @@ internal DW_CompUnit dw_cu_from_info_off(Arena *arena, DW_Input *input, DW_ListUnitInput lu_input, U64 offset, B32 relaxed) { DW_CompUnit cu = {0}; - + String8 info_data = input->sec[DW_Section_Info].data; - + // read unit size in bytes U64 length = 0; U64 length_size = str8_deserial_read_dwarf_packed_size(info_data, offset, &length); - + if (length_size) { // compute unit range Rng1U64 range = rng_1u64(offset, offset + length_size + length); String8 data = str8_substr(info_data, range); U64 cursor = length_size; - + // read version DW_Version version = 0; U64 version_size = str8_deserial_read_struct(data, cursor, &version); cursor += version_size; - + if (version_size) { DW_Format format = DW_FormatFromSize(length); B32 is_header_ok = 0; @@ -2036,123 +2036,123 @@ dw_cu_from_info_off(Arena *arena, DW_Input *input, DW_ListUnitInput lu_input, U6 U8 address_size = 0; DW_CompUnitKind unit_kind = DW_CompUnitKind_Reserved; U64 spec_dwo_id = max_U64; - + switch (version) { - default: - case DW_Version_Null: - case DW_Version_1: + default: + case DW_Version_Null: + case DW_Version_1: break; - case DW_Version_2: { - U32 abbrev_base32 = 0; - U64 abbrev_base_off = cursor; - U64 abbrev_base_size = str8_deserial_read_struct(data, abbrev_base_off, &abbrev_base32); - if (!abbrev_base_size) { - break; - } - - U64 address_size_off = abbrev_base_off + abbrev_base_size; - U64 address_size_size = str8_deserial_read_struct(data, address_size_off, &address_size); - if (!address_size_size) { - break; - } - - abbrev_base = abbrev_base32; - cursor = address_size_off + address_size_size; - is_header_ok = 1; - } break; - case DW_Version_3: - case DW_Version_4: { - U64 abbrev_base_off = cursor; - U64 abbrev_base_size = str8_deserial_read_dwarf_uint(data, abbrev_base_off, format, &abbrev_base); - if (!abbrev_base_size) { - break; - } - - U64 address_size_off = abbrev_base_off + abbrev_base_size; - U64 address_size_size = str8_deserial_read_struct(data, address_size_off, &address_size); - if (!address_size_size) { - break; - } - - cursor = address_size_off + address_size_size; - is_header_ok = 1; - } break; - case DW_Version_5: { - U64 unit_kind_off = cursor; - U64 unit_kind_size = str8_deserial_read_struct(data, unit_kind_off, &unit_kind); - if (unit_kind_size == 0) { - break; - } - - U64 address_size_off = unit_kind_off + unit_kind_size; - U64 address_size_size = str8_deserial_read_struct(data, address_size_off, &address_size); - if (!address_size_size) { - break; - } - - U64 abbrev_base_off = address_size_off + address_size_size; - U64 abbrev_base_size = str8_deserial_read_dwarf_uint(data, abbrev_base_off, format, &abbrev_base); - if (!abbrev_base_size) { - break; - } - - U64 spec_dwo_id_off = abbrev_base_off + abbrev_base_size; - U64 spec_dwo_id_size = 0; - if (unit_kind == DW_CompUnitKind_Skeleton || input->sec[DW_Section_Info].is_dwo) { - spec_dwo_id_size = str8_deserial_read_struct(data, spec_dwo_id_off, &spec_dwo_id); - if (!spec_dwo_id_size) { + case DW_Version_2: { + U32 abbrev_base32 = 0; + U64 abbrev_base_off = cursor; + U64 abbrev_base_size = str8_deserial_read_struct(data, abbrev_base_off, &abbrev_base32); + if (!abbrev_base_size) { break; } - } - - cursor = spec_dwo_id_off + spec_dwo_id_size; - is_header_ok = 1; - } break; + + U64 address_size_off = abbrev_base_off + abbrev_base_size; + U64 address_size_size = str8_deserial_read_struct(data, address_size_off, &address_size); + if (!address_size_size) { + break; + } + + abbrev_base = abbrev_base32; + cursor = address_size_off + address_size_size; + is_header_ok = 1; + } break; + case DW_Version_3: + case DW_Version_4: { + U64 abbrev_base_off = cursor; + U64 abbrev_base_size = str8_deserial_read_dwarf_uint(data, abbrev_base_off, format, &abbrev_base); + if (!abbrev_base_size) { + break; + } + + U64 address_size_off = abbrev_base_off + abbrev_base_size; + U64 address_size_size = str8_deserial_read_struct(data, address_size_off, &address_size); + if (!address_size_size) { + break; + } + + cursor = address_size_off + address_size_size; + is_header_ok = 1; + } break; + case DW_Version_5: { + U64 unit_kind_off = cursor; + U64 unit_kind_size = str8_deserial_read_struct(data, unit_kind_off, &unit_kind); + if (unit_kind_size == 0) { + break; + } + + U64 address_size_off = unit_kind_off + unit_kind_size; + U64 address_size_size = str8_deserial_read_struct(data, address_size_off, &address_size); + if (!address_size_size) { + break; + } + + U64 abbrev_base_off = address_size_off + address_size_size; + U64 abbrev_base_size = str8_deserial_read_dwarf_uint(data, abbrev_base_off, format, &abbrev_base); + if (!abbrev_base_size) { + break; + } + + U64 spec_dwo_id_off = abbrev_base_off + abbrev_base_size; + U64 spec_dwo_id_size = 0; + if (unit_kind == DW_CompUnitKind_Skeleton || input->sec[DW_Section_Info].is_dwo) { + spec_dwo_id_size = str8_deserial_read_struct(data, spec_dwo_id_off, &spec_dwo_id); + if (!spec_dwo_id_size) { + break; + } + } + + cursor = spec_dwo_id_off + spec_dwo_id_size; + is_header_ok = 1; + } break; } - + if (is_header_ok) { Temp temp = temp_begin(arena); - + // TODO: cache abbrev tables with identical offsets String8 abbrev_data = input->sec[DW_Section_Abbrev].data; DW_AbbrevTable abbrev_table = dw_make_abbrev_table(arena, abbrev_data, abbrev_base); - + DW_Tag cu_tag = {0}; 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); - + if (cu_tag.kind == DW_Tag_CompileUnit || cu_tag.kind == DW_Tag_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 ); - + // interp attribs as section offsets U64 addr_sec_off = dw_interp_sec_offset(addr_base_attrib->form_kind, addr_base_attrib->form ); U64 str_offsets_sec_off = dw_interp_sec_offset(str_offsets_base_attrib->form_kind, str_offsets_base_attrib->form); U64 rnglists_sec_off = dw_interp_sec_offset(rnglists_base_attrib->form_kind, rnglists_base_attrib->form ); U64 loclists_sec_off = dw_interp_sec_offset(loclists_base_attrib->form_kind, loclists_base_attrib->form ); - + // map section offset to unit index U64 addr_lu_idx = rng_1u64_array_bsearch(lu_input.addr_ranges, addr_sec_off ); U64 str_offsets_lu_idx = rng_1u64_array_bsearch(lu_input.str_offset_ranges, str_offsets_sec_off); U64 rnglists_lu_idx = rng_1u64_array_bsearch(lu_input.rnglist_ranges, rnglists_sec_off ); U64 loclists_lu_idx = rng_1u64_array_bsearch(lu_input.loclist_ranges, loclists_sec_off ); - + // map index to unit DW_ListUnit *addr_lu = addr_lu_idx < lu_input.addr_count ? &lu_input.addrs[addr_lu_idx] : 0; DW_ListUnit *str_offsets_lu = str_offsets_lu_idx < lu_input.str_offset_count ? &lu_input.str_offsets[str_offsets_lu_idx] : 0; DW_ListUnit *rnglists_lu = rnglists_lu_idx < lu_input.rnglist_count ? &lu_input.rnglists[rnglists_lu_idx] : 0; 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); 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 cu.relaxed = relaxed; cu.ext = DW_Ext_All; @@ -2178,7 +2178,7 @@ dw_cu_from_info_off(Arena *arena, DW_Input *input, DW_ListUnitInput lu_input, U6 } } } - + return cu; } @@ -2193,21 +2193,21 @@ dw_tag_tree_from_data(Arena *arena, String8 info_data, String8 abbrev_data, DW_C break; } *cursor += tag_size; - + // is this sentinel tag? if (tag.kind == DW_Tag_Null) { break; } - + // normal tag DW_TagNode *tag_n = push_array(arena, DW_TagNode, 1); tag_n->tag = tag; - + SLLQueuePush_N(parent->first_child, parent->last_child, tag_n, sibling); - + // update tag count *tag_count += 1; - + if (tag.has_children) { dw_tag_tree_from_data(arena, info_data, abbrev_data, cu, tag_n, cursor, tag_count); } @@ -2223,11 +2223,11 @@ dw_tag_tree_from_cu(Arena *arena, DW_Input *input, DW_CompUnit *cu) U64 cursor = cu->first_tag_info_off; U64 tag_count = 0; dw_tag_tree_from_data(arena, info_data, abbrev_data, cu, &root, &cursor, &tag_count); - + DW_TagTree result = {0}; result.root = root.first_child; result.tag_count = tag_count; - + return result; } @@ -2235,22 +2235,22 @@ internal HashTable * dw_make_tag_hash_table(Arena *arena, DW_TagTree tag_tree) { Temp scratch = scratch_begin(&arena, 1); - + struct Frame { struct Frame *next; DW_TagNode *node; }; - + struct Frame *free_frames = 0; struct Frame *stack = push_array(scratch.arena, struct Frame, 1); stack->node = tag_tree.root; - + HashTable *ht = hash_table_init(arena, (U64)((F64)tag_tree.tag_count * 1.3)); - + while (stack) { while (stack->node) { hash_table_push_u64_raw(arena, ht, stack->node->tag.info_off, stack->node); - + if (stack->node->first_child) { struct Frame *frame = free_frames; if (frame) { @@ -2265,17 +2265,17 @@ dw_make_tag_hash_table(Arena *arena, DW_TagTree tag_tree) stack->node = stack->node->sibling; } } - + // recycle free frame struct Frame *frame = stack; SLLStackPop(stack); SLLStackPush(free_frames, frame); - + if (stack) { stack->node = stack->node->sibling; } } - + scratch_end(scratch); return ht; } @@ -2293,7 +2293,7 @@ dw_line_vm_file_array_from_list(Arena *arena, DW_LineVMFileList list) DW_LineVMFileArray result = {0}; result.count = 0; result.v = push_array(arena, DW_LineFile, list.node_count); - + for (DW_LineVMFileNode *src = list.first; src != 0; src = src->next) { DW_LineFile *dst = &result.v[result.count++]; dst->file_name = push_str8_copy(arena, src->file.file_name); @@ -2301,7 +2301,7 @@ dw_line_vm_file_array_from_list(Arena *arena, DW_LineVMFileList list) dst->modify_time = src->file.modify_time; dst->file_size = src->file.file_size; } - + return result; } @@ -2326,38 +2326,38 @@ dw_read_line_file(String8 data, DW_Form form = {0}; U64 bytes_read; switch (lnct) { - case DW_LNCT_Path: { - bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); - line_file_out->file_name = dw_interp_string(input, format, str_offsets, form_kind, form); - } break; - case DW_LNCT_DirectoryIndex: { - bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); - line_file_out->dir_idx = dw_interp_const_u64(form_kind, form); - } break; - case DW_LNCT_TimeStamp: { - bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); - line_file_out->modify_time = dw_interp_const_u64(form_kind, form); - } break; - case DW_LNCT_Size: { - bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); - line_file_out->file_size = dw_interp_const_u64(form_kind, form); - } break; - case DW_LNCT_MD5: { - bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); - line_file_out->md5_digest = dw_interp_const_u128(form_kind, form); - } break; - case DW_LNCT_LLVM_Source: { - if (ext & DW_Ext_LLVM) { + case DW_LNCT_Path: { bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); - line_file_out->source = dw_interp_string(input, format, str_offsets, form_kind, form); - } else { - Assert(!"extension not supported"); - } - } break; - default: { - bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); - Assert(!"unexpected LNTC encoding"); - } break; + line_file_out->file_name = dw_interp_string(input, format, str_offsets, form_kind, form); + } break; + case DW_LNCT_DirectoryIndex: { + bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); + line_file_out->dir_idx = dw_interp_const_u64(form_kind, form); + } break; + case DW_LNCT_TimeStamp: { + bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); + line_file_out->modify_time = dw_interp_const_u64(form_kind, form); + } break; + case DW_LNCT_Size: { + bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); + line_file_out->file_size = dw_interp_const_u64(form_kind, form); + } break; + case DW_LNCT_MD5: { + bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); + line_file_out->md5_digest = dw_interp_const_u128(form_kind, form); + } break; + case DW_LNCT_LLVM_Source: { + if (ext & DW_Ext_LLVM) { + bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); + line_file_out->source = dw_interp_string(input, format, str_offsets, form_kind, form); + } else { + Assert(!"extension not supported"); + } + } break; + default: { + bytes_read = dw_read_form(data, cursor, version, format, address_size, form_kind, max_U64, &form); + Assert(!"unexpected LNTC encoding"); + } break; } Assert(bytes_read); cursor += bytes_read; @@ -2382,10 +2382,10 @@ dw_read_line_file_array(Arena *arena, DW_LineVMFileArray *table_out) { Temp temp = temp_begin(arena); - + table_out->count = table_count; table_out->v = push_array(arena, DW_LineFile, table_count); - + U64 i, cursor; for (i = 0, cursor = off; i < table_count; ++i) { U64 bytes_read = dw_read_line_file(data, @@ -2404,7 +2404,7 @@ dw_read_line_file_array(Arena *arena, } cursor += bytes_read; } - + U64 bytes_read = 0; if (i == table_count) { bytes_read = cursor - off; @@ -2413,7 +2413,7 @@ dw_read_line_file_array(Arena *arena, table_out->count = 0; table_out->v = 0; } - + return bytes_read; } @@ -2429,19 +2429,19 @@ dw_read_line_vm_header(Arena *arena, DW_LineVMHeader *header_out) { Temp scratch = scratch_begin(&arena, 1); - + U64 bytes_read = 0; // read unit length U64 unit_length = 0; U64 unit_length_size = str8_deserial_read_dwarf_packed_size(line_data, line_off, &unit_length); - + U64 unit_opl = line_off + unit_length_size + unit_length; Rng1U64 unit_range = rng_1u64(line_off, unit_opl); DW_Format format = DW_FormatFromSize(unit_length); U64 unit_cursor = unit_length_size; String8 unit_data = str8_substr(line_data, unit_range); - + // read unit version DW_Version version = DW_Version_Null; U64 version_size = str8_deserial_read_struct(unit_data, unit_cursor, &version); @@ -2459,7 +2459,7 @@ dw_read_line_vm_header(Arena *arena, goto exit; } unit_cursor += address_size_size; - + U64 segsel_size_size = str8_deserial_read_struct(unit_data, unit_cursor, &segsel_size); if (segsel_size_size == 0) { goto exit; @@ -2476,7 +2476,7 @@ dw_read_line_vm_header(Arena *arena, goto exit; } unit_cursor += header_length_size; - + // read min instruction length U8 min_inst_len = 0; U64 min_inst_len_size = str8_deserial_read_struct(unit_data, unit_cursor, &min_inst_len); @@ -2484,7 +2484,7 @@ dw_read_line_vm_header(Arena *arena, goto exit; } unit_cursor += min_inst_len_size; - + // read max operands for instruction U8 max_ops_for_inst = 1; if (version > DW_Version_3) { @@ -2502,35 +2502,35 @@ dw_read_line_vm_header(Arena *arena, goto exit; } unit_cursor += default_is_stmt_size; - + S8 line_base = 0; U64 line_base_size = str8_deserial_read_struct(unit_data, unit_cursor, &line_base); if (line_base_size == 0) { goto exit; } unit_cursor += line_base_size; - + U8 line_range = 0; U64 line_range_size = str8_deserial_read_struct(unit_data, unit_cursor, &line_range); if (line_range_size == 0) { goto exit; } unit_cursor += line_range_size; - + U8 opcode_base = 0; U64 opcode_base_size = str8_deserial_read_struct(unit_data, unit_cursor, &opcode_base); if (opcode_base_size == 0) { goto exit; } unit_cursor += opcode_base_size; - + U64 num_opcode_lens = opcode_base > 0 ? opcode_base - 1 : 0; U8 *opcode_lens = str8_deserial_get_raw_ptr(unit_data, unit_cursor, num_opcode_lens * sizeof(opcode_lens[0])); if (opcode_lens == 0) { goto exit; } unit_cursor += num_opcode_lens * sizeof(opcode_lens[0]); - + DW_LineVMFileArray dir_table = {0}; DW_LineVMFileArray file_table = {0}; if (version < DW_Version_5) { @@ -2543,7 +2543,7 @@ dw_read_line_vm_header(Arena *arena, SLLQueuePush(dir_list.first, dir_list.last, node); ++dir_list.node_count; } - + // parse additional directories for (; unit_cursor < unit_data.size; ) { String8 dir = {0}; @@ -2551,7 +2551,7 @@ dw_read_line_vm_header(Arena *arena, if (dir.size == 0) { break; } - + DW_LineVMFileNode *node = push_array(scratch.arena, DW_LineVMFileNode, 1); node->file.file_name = dir; SLLQueuePush(dir_list.first, dir_list.last, node); @@ -2575,21 +2575,21 @@ dw_read_line_vm_header(Arena *arena, if (file_name.size == 0) { break; } - + U64 dir_index = 0; U64 dir_index_size = str8_deserial_read_uleb128(unit_data, unit_cursor, &dir_index); if (dir_index_size == 0) { goto exit; } unit_cursor += dir_index_size; - + U64 modify_time = 0; U64 modify_time_size = str8_deserial_read_uleb128(unit_data, unit_cursor, &modify_time); if (modify_time_size == 0) { goto exit; } unit_cursor += modify_time_size; - + U64 file_size = 0; U64 file_size_size = str8_deserial_read_uleb128(unit_data, unit_cursor, &file_size); if (file_size_size == 0) { @@ -2602,12 +2602,12 @@ dw_read_line_vm_header(Arena *arena, node->file.dir_idx = dir_index; node->file.modify_time = modify_time; node->file.file_size = file_size; - + SLLQueuePush(file_list.first, file_list.last, node); ++file_list.node_count; } } - + // list -> array dir_table = dw_line_vm_file_array_from_list(arena, dir_list); file_table = dw_line_vm_file_array_from_list(arena, file_list); @@ -2623,7 +2623,7 @@ dw_read_line_vm_header(Arena *arena, goto exit; } unit_cursor += enc_count_size; - + // read table entry encodings U64 *enc_arr = 0; U64 enc_arr_size = str8_deserial_read_uleb128_array(scratch.arena, unit_data, unit_cursor, enc_count*2, &enc_arr); @@ -2631,7 +2631,7 @@ dw_read_line_vm_header(Arena *arena, goto exit; } unit_cursor += enc_arr_size; - + // read table count U64 table_count = 0; U64 table_count_size = str8_deserial_read_uleb128(unit_data, unit_cursor, &table_count); @@ -2639,7 +2639,7 @@ dw_read_line_vm_header(Arena *arena, goto exit; } unit_cursor += table_count_size; - + // read table U64 table_size = dw_read_line_file_array(arena, unit_data, @@ -2659,7 +2659,7 @@ dw_read_line_vm_header(Arena *arena, } unit_cursor += table_size; } - + // file table { // read table entry encoding count @@ -2669,7 +2669,7 @@ dw_read_line_vm_header(Arena *arena, goto exit; } unit_cursor += enc_count_size; - + // read table entry encodings U64 *enc_arr = 0; U64 enc_arr_size = str8_deserial_read_uleb128_array(scratch.arena, unit_data, unit_cursor, enc_count*2, &enc_arr); @@ -2677,7 +2677,7 @@ dw_read_line_vm_header(Arena *arena, goto exit; } unit_cursor += enc_arr_size; - + // read table count U64 table_count = 0; U64 table_count_size = str8_deserial_read_uleb128(unit_data, unit_cursor, &table_count); @@ -2685,7 +2685,7 @@ dw_read_line_vm_header(Arena *arena, goto exit; } unit_cursor += table_count_size; - + // read table U64 file_table_size = dw_read_line_file_array(arena, unit_data, @@ -2706,7 +2706,7 @@ dw_read_line_vm_header(Arena *arena, unit_cursor += file_table_size; } } - + if (header_out) { header_out->unit_range = unit_range; header_out->version = version; @@ -2724,10 +2724,10 @@ dw_read_line_vm_header(Arena *arena, header_out->dir_table = dir_table; header_out->file_table = file_table; } - + bytes_read = unit_cursor; - -exit:; + + exit:; scratch_end(scratch); return bytes_read; } @@ -2773,13 +2773,13 @@ dw_push_line(Arena *arena, DW_LineTableParseResult *tbl, DW_LineVMState *vm_stat { seq = dw_push_line_seq(arena, tbl); } - + DW_LineNode *n = push_array(arena, DW_LineNode, 1); n->v.file_index = vm_state->file_index; n->v.line = vm_state->line; n->v.column = vm_state->column; n->v.address = vm_state->address; - + SLLQueuePush(seq->first, seq->last, n); seq->count += 1; return n; @@ -2794,23 +2794,23 @@ dw_path_from_file(Arena *arena, DW_LineVMHeader *vm, DW_LineFile *file) if (style == PathStyle_Null || style == PathStyle_Relative) { style = path_style_from_str8(file->file_name); } - + String8List path_list = {0}; - + if (str8_match_lit("..", dir, StringMatchFlag_RightSideSloppy)) { String8List comp_dir_list = str8_split_path(scratch.arena, vm->dir_table.v[0].file_name); str8_list_concat_in_place(&path_list, &comp_dir_list); } - + String8List dir_list = str8_split_path(scratch.arena, dir); str8_list_concat_in_place(&path_list, &dir_list); - + str8_list_push(scratch.arena, &path_list, file->file_name); - + str8_path_list_resolve_dots_in_place(&path_list, style); - + String8 path = str8_path_list_join_by_style(arena, &path_list, style); - + scratch_end(scratch); return path; } @@ -2832,7 +2832,7 @@ dw_parsed_line_table_from_data(Arena *arena, { DW_LineVMHeader vm_header = {0}; U64 vm_header_size = dw_read_line_vm_header(arena, unit_data, 0, input, cu_dir, cu_name, cu_address_size, cu_str_offsets, &vm_header); - + U64 unit_cursor = vm_header_size; //- rjf: prep state for VM @@ -2850,188 +2850,188 @@ dw_parsed_line_table_from_data(Arena *arena, //- rjf: do opcode action switch (opcode) { - default: { - //- rjf: special opcode case - if (opcode >= vm_header.opcode_base) { - U32 adjusted_opcode = (U32)(opcode - vm_header.opcode_base); - U32 op_advance = adjusted_opcode / vm_header.line_range; - S32 line_inc = (S32)vm_header.line_base + ((S32)adjusted_opcode) % (S32)vm_header.line_range; - // TODO: can we just call dw_advance_line_vm_state_pc - U64 addr_inc = vm_header.min_inst_len * ((vm_state.op_index+op_advance) / vm_header.max_ops_for_inst); - - vm_state.address += addr_inc; - vm_state.op_index = (vm_state.op_index + op_advance) % vm_header.max_ops_for_inst; - vm_state.line = (U32)((S32)vm_state.line + line_inc); - vm_state.basic_block = 0; - vm_state.prologue_end = 0; - vm_state.epilogue_begin = 0; - vm_state.discriminator = 0; - + default: { + //- rjf: special opcode case + if (opcode >= vm_header.opcode_base) { + U32 adjusted_opcode = (U32)(opcode - vm_header.opcode_base); + U32 op_advance = adjusted_opcode / vm_header.line_range; + S32 line_inc = (S32)vm_header.line_base + ((S32)adjusted_opcode) % (S32)vm_header.line_range; + // TODO: can we just call dw_advance_line_vm_state_pc + U64 addr_inc = vm_header.min_inst_len * ((vm_state.op_index+op_advance) / vm_header.max_ops_for_inst); + + vm_state.address += addr_inc; + vm_state.op_index = (vm_state.op_index + op_advance) % vm_header.max_ops_for_inst; + vm_state.line = (U32)((S32)vm_state.line + line_inc); + vm_state.basic_block = 0; + vm_state.prologue_end = 0; + vm_state.epilogue_begin = 0; + vm_state.discriminator = 0; + + if(vm_state.is_stmt) + { + dw_push_line(arena, &result, &vm_state, end_of_seq); + } + end_of_seq = 0; + +#if 0 + // NOTE(rjf): DWARF has dummy lines at the end of groups of line ranges, where we'd like + // to break line info into sequences. + if(vm_state.line == 0) + { + end_of_seq = 1; + } +#endif + } + // Skipping unknown opcode. This is a valid case and + // it works because compiler stores operand lengths. + else { + if (0 < opcode && opcode <= vm_header.num_opcode_lens) { + U8 num_operands = vm_header.opcode_lens[opcode - 1]; + for (U8 i = 0; i < num_operands; ++i) { + U64 operand = 0; + unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &operand); + } + } else { + error = 1; + goto exit; + } + } + } break; + + //- Standard opcodes + + case DW_StdOpcode_Copy: { if(vm_state.is_stmt) { dw_push_line(arena, &result, &vm_state, end_of_seq); } end_of_seq = 0; - -#if 0 - // NOTE(rjf): DWARF has dummy lines at the end of groups of line ranges, where we'd like - // to break line info into sequences. - if(vm_state.line == 0) - { - end_of_seq = 1; - } -#endif - } - // Skipping unknown opcode. This is a valid case and - // it works because compiler stores operand lengths. - else { - if (0 < opcode && opcode <= vm_header.num_opcode_lens) { - U8 num_operands = vm_header.opcode_lens[opcode - 1]; - for (U8 i = 0; i < num_operands; ++i) { - U64 operand = 0; - unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &operand); - } - } else { - error = 1; - goto exit; - } - } - } break; - - //- Standard opcodes - - case DW_StdOpcode_Copy: { - if(vm_state.is_stmt) - { - dw_push_line(arena, &result, &vm_state, end_of_seq); - } - end_of_seq = 0; - vm_state.discriminator = 0; - vm_state.basic_block = 0; - vm_state.prologue_end = 0; - vm_state.epilogue_begin = 0; - } break; - - case DW_StdOpcode_AdvancePc: { - U64 advance = 0; - unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &advance); - dw_line_vm_advance(&vm_state, advance, vm_header.min_inst_len, vm_header.max_ops_for_inst); - } break; - - case DW_StdOpcode_AdvanceLine: { - S64 s = 0; - unit_cursor += str8_deserial_read_sleb128(unit_data, unit_cursor, &s); - vm_state.line += s; - } break; - - case DW_StdOpcode_SetFile: { - U64 file_index = 0; - unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &file_index); - vm_state.file_index = file_index; - } break; - - case DW_StdOpcode_SetColumn: { - U64 column = 0; - unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &column); - vm_state.column = column; - } break; - - case DW_StdOpcode_NegateStmt: { - vm_state.is_stmt = !vm_state.is_stmt; - } break; - - case DW_StdOpcode_SetBasicBlock: { - vm_state.basic_block = 1; - } break; - - case DW_StdOpcode_ConstAddPc: { - U64 advance = (0xffu - vm_header.opcode_base) / vm_header.line_range; - dw_line_vm_advance(&vm_state, advance, vm_header.min_inst_len, vm_header.max_ops_for_inst); - } break; - - case DW_StdOpcode_FixedAdvancePc: { - U16 operand = 0; - unit_cursor += str8_deserial_read_struct(unit_data, unit_cursor, &operand); - vm_state.address += operand; - vm_state.op_index = 0; - } break; - - case DW_StdOpcode_SetPrologueEnd: { - vm_state.prologue_end = 1; - } break; - - case DW_StdOpcode_SetEpilogueBegin: { - vm_state.epilogue_begin = 1; - } break; - - case DW_StdOpcode_SetIsa: { - U64 v = 0; - unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &v); - vm_state.isa = v; - } break; - - //- Extended opcodes - case DW_StdOpcode_ExtendedOpcode: { - U64 length = 0; - unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &length); - - U64 extended_opl = unit_cursor + length; - U8 extended_opcode = 0; - unit_cursor += str8_deserial_read_struct(unit_data, unit_cursor, &extended_opcode); - - switch (extended_opcode) { - case DW_ExtOpcode_EndSequence: { - vm_state.end_sequence = 1; - if(vm_state.is_stmt) - { - dw_push_line(arena, &result, &vm_state, 0); - } - dw_line_vm_reset(&vm_state, vm_header.default_is_stmt); - end_of_seq = 1; + vm_state.discriminator = 0; + vm_state.basic_block = 0; + vm_state.prologue_end = 0; + vm_state.epilogue_begin = 0; } break; - case DW_ExtOpcode_SetAddress: { - U64 address = 0; - unit_cursor += str8_deserial_read(unit_data, unit_cursor, &address, vm_header.address_size, vm_header.address_size); - vm_state.address = address; - vm_state.op_index = 0; + case DW_StdOpcode_AdvancePc: { + U64 advance = 0; + unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &advance); + dw_line_vm_advance(&vm_state, advance, vm_header.min_inst_len, vm_header.max_ops_for_inst); } break; - case DW_ExtOpcode_DefineFile: { - String8 file_name = {0}; - U64 dir_index = 0; - U64 modify_time = 0; - U64 file_size = 0; - - unit_cursor += str8_deserial_read_cstr(unit_data, unit_cursor, &file_name); - unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &dir_index); - unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &modify_time); - unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &file_size); - - // TODO(rjf): Not fully implemented. By the DWARF V4 spec, the above is - // all that needs to be parsed, but the rest of the work that needs to - // happen here---allowing this file to be used by further opcodes---is - // not implemented. - // - // See the DWARF V4 spec (June 10, 2010), page 122. - error = 1; - AssertAlways(!"UNHANDLED DEFINE FILE!!!"); + case DW_StdOpcode_AdvanceLine: { + S64 s = 0; + unit_cursor += str8_deserial_read_sleb128(unit_data, unit_cursor, &s); + vm_state.line += s; } break; - case DW_ExtOpcode_SetDiscriminator: { + case DW_StdOpcode_SetFile: { + U64 file_index = 0; + unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &file_index); + vm_state.file_index = file_index; + } break; + + case DW_StdOpcode_SetColumn: { + U64 column = 0; + unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &column); + vm_state.column = column; + } break; + + case DW_StdOpcode_NegateStmt: { + vm_state.is_stmt = !vm_state.is_stmt; + } break; + + case DW_StdOpcode_SetBasicBlock: { + vm_state.basic_block = 1; + } break; + + case DW_StdOpcode_ConstAddPc: { + U64 advance = (0xffu - vm_header.opcode_base) / vm_header.line_range; + dw_line_vm_advance(&vm_state, advance, vm_header.min_inst_len, vm_header.max_ops_for_inst); + } break; + + case DW_StdOpcode_FixedAdvancePc: { + U16 operand = 0; + unit_cursor += str8_deserial_read_struct(unit_data, unit_cursor, &operand); + vm_state.address += operand; + vm_state.op_index = 0; + } break; + + case DW_StdOpcode_SetPrologueEnd: { + vm_state.prologue_end = 1; + } break; + + case DW_StdOpcode_SetEpilogueBegin: { + vm_state.epilogue_begin = 1; + } break; + + case DW_StdOpcode_SetIsa: { U64 v = 0; unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &v); - vm_state.discriminator = v; + vm_state.isa = v; } break; - default: break; - } - - unit_cursor = extended_opl; - } break; + //- Extended opcodes + case DW_StdOpcode_ExtendedOpcode: { + U64 length = 0; + unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &length); + + U64 extended_opl = unit_cursor + length; + U8 extended_opcode = 0; + unit_cursor += str8_deserial_read_struct(unit_data, unit_cursor, &extended_opcode); + + switch (extended_opcode) { + case DW_ExtOpcode_EndSequence: { + vm_state.end_sequence = 1; + if(vm_state.is_stmt) + { + dw_push_line(arena, &result, &vm_state, 0); + } + dw_line_vm_reset(&vm_state, vm_header.default_is_stmt); + end_of_seq = 1; + } break; + + case DW_ExtOpcode_SetAddress: { + U64 address = 0; + unit_cursor += str8_deserial_read(unit_data, unit_cursor, &address, vm_header.address_size, vm_header.address_size); + vm_state.address = address; + vm_state.op_index = 0; + } break; + + case DW_ExtOpcode_DefineFile: { + String8 file_name = {0}; + U64 dir_index = 0; + U64 modify_time = 0; + U64 file_size = 0; + + unit_cursor += str8_deserial_read_cstr(unit_data, unit_cursor, &file_name); + unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &dir_index); + unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &modify_time); + unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &file_size); + + // TODO(rjf): Not fully implemented. By the DWARF V4 spec, the above is + // all that needs to be parsed, but the rest of the work that needs to + // happen here---allowing this file to be used by further opcodes---is + // not implemented. + // + // See the DWARF V4 spec (June 10, 2010), page 122. + error = 1; + AssertAlways(!"UNHANDLED DEFINE FILE!!!"); + } break; + + case DW_ExtOpcode_SetDiscriminator: { + U64 v = 0; + unit_cursor += str8_deserial_read_uleb128(unit_data, unit_cursor, &v); + vm_state.discriminator = v; + } break; + + default: break; + } + + unit_cursor = extended_opl; + } break; } } - + exit:; return result; @@ -3041,59 +3041,59 @@ internal DW_PubStringsTable dw_v4_pub_strings_table_from_section_kind(Arena *arena, DW_Input *input, DW_SectionKind section_kind) { Temp scratch = scratch_begin(&arena, 1); - + DW_PubStringsTable names_table = {0}; names_table.size = 16384; names_table.buckets = push_array(arena, DW_PubStringsBucket*, names_table.size); String8 section_data = input->sec[section_kind].data; for(U64 cursor = 0; cursor < section_data.size; ) { - + U64 unit_length = 0; U64 unit_length_size = str8_deserial_read_dwarf_packed_size(section_data, cursor, &unit_length); if (unit_length_size == 0) { break; } cursor += unit_length_size; - + U64 cursor_opl = Min(cursor + unit_length, section_data.size); if (cursor >= cursor_opl) { break; } - + DW_Version unit_version = 0; cursor += str8_deserial_read_struct(section_data, cursor, &unit_version); if (cursor >= cursor_opl) { break; } - + DW_Format format = DW_FormatFromSize(unit_length); - + U64 debug_info_off = 0; cursor += str8_deserial_read_dwarf_uint(section_data, cursor, format, &debug_info_off); if (cursor >= cursor_opl) { break; } - + U64 debug_info_length = 0; cursor += str8_deserial_read_dwarf_packed_size(section_data, cursor, &debug_info_length); if (cursor >= cursor_opl) { break; } - + U64 off_size = dw_size_from_format(format); for (; (cursor + off_size) <= cursor_opl;) { U64 info_off = 0; U64 info_off_size = str8_deserial_read_dwarf_uint(section_data, cursor, format, &info_off); cursor += info_off_size; - + if (info_off_size == 0 || info_off == 0) { break; } String8 string = {0}; cursor += str8_deserial_read_cstr(section_data, cursor, &string); - + U64 hash = dw_hash_from_string(string); U64 bucket_idx = hash % names_table.size; diff --git a/src/dwarf/dwarf_parse.h b/src/dwarf/dwarf_parse.h index 99a589d6..b89e45be 100644 --- a/src/dwarf/dwarf_parse.h +++ b/src/dwarf/dwarf_parse.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_PARSE_H diff --git a/src/dwarf/dwarf_unwind.c b/src/dwarf/dwarf_unwind.c index 81cc93de..e3540442 100644 --- a/src/dwarf/dwarf_unwind.c +++ b/src/dwarf/dwarf_unwind.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U64 dw_based_range_read(void *base, Rng1U64 range, U64 off, U64 size, void *out) { return 0; } @@ -25,9 +25,9 @@ dw_unwind_x64(String8 raw_text, { // TODO: What if ELF has two sections with instructions and pointer is ecnoded relative to .text2? Temp scratch = scratch_begin(0, 0); - + DW_UnwindResult result = {0}; - + dw_unwind_init_x64(); // rebase @@ -46,7 +46,7 @@ dw_unwind_x64(String8 raw_text, //- get frame info range void *frame_base = raw_eh_frame.str; Rng1U64 frame_range = rng_1u64(0, raw_eh_frame.size); - + //- section vaddrs U64 text_base_vaddr = text_vrange.min + rebase_voff_to_vaddr; U64 frame_base_voff = text_vrange.min; @@ -113,7 +113,7 @@ dw_unwind_x64(String8 raw_text, result.is_invalid = 1; } } - + // apply main row to modify the registers if (main_row != 0) { result = dw_unwind_x64__apply_frame_rules(raw_eh_frame, main_row, text_base_vaddr, read_memory, read_memory_ud, stack_pointer, regs); @@ -133,7 +133,7 @@ dw_unwind_x64__apply_frame_rules(String8 raw_eh_frame, DW_RegsX64 *regs) { DW_UnwindResult result = {0}; - + U64 missed_read_addr = 0; //- setup a dwarf expression machine @@ -375,7 +375,7 @@ dw_unwind_parse_pointer_x64(void *frame_base, Rng1U64 frame_range, DW_EhPtrCtx * case DW_EhPtrEnc_SLEB128: { U64 size = dw_based_range_read_sleb128(frame_base, frame_range, pointer_off, - (S64*)&raw_pointer); + (S64*)&raw_pointer); after_pointer_off = pointer_off + size; } break; } @@ -588,7 +588,7 @@ internal DW_CFIRecords dw_unwind_eh_frame_cfi_from_ip_slow_x64(String8 raw_eh_frame, DW_EhPtrCtx *ptr_ctx, U64 ip_voff) { Temp scratch = scratch_begin(0, 0); - + DW_CFIRecords result = {0}; DW_CIEUnpackedNode *cie_first = 0; @@ -622,7 +622,7 @@ dw_unwind_eh_frame_cfi_from_ip_slow_x64(String8 raw_eh_frame, DW_EhPtrCtx *ptr_c Rng1U64 rec_range = rng_1u64(rec_off, rec_opl); String8 raw_rec = str8_substr(raw_eh_frame, rec_range); - + // discriminator U64 discrim_off = after_rec_size_off; U32 discrim = 0; @@ -839,7 +839,7 @@ internal B32 dw_unwind_machine_run_to_ip_x64(void *base, Rng1U64 range, DW_CFIMachine *machine, U64 target_ip, DW_CFIRow *row) { Temp scratch = scratch_begin(0, 0); - + B32 result = 0; // pull out machine's equipment diff --git a/src/dwarf/dwarf_unwind.h b/src/dwarf/dwarf_unwind.h index 8a0018e6..f2e6d2c1 100644 --- a/src/dwarf/dwarf_unwind.h +++ b/src/dwarf/dwarf_unwind.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef DWARF_UNWIND_H diff --git a/src/eval/eval.mdesk b/src/eval/eval.mdesk index f7f382ed..34c570bb 100644 --- a/src/eval/eval.mdesk +++ b/src/eval/eval.mdesk @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) @table(name) diff --git a/src/eval/eval_core.c b/src/eval/eval_core.c index 158dc310..fa02c57e 100644 --- a/src/eval/eval_core.c +++ b/src/eval/eval_core.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -189,6 +189,13 @@ e_space_make(E_SpaceKind kind) return space; } +internal B32 +e_space_match(E_Space a, E_Space b) +{ + B32 result = MemoryMatchStruct(&a, &b); + return result; +} + //////////////////////////////// //~ rjf: Map Functions @@ -445,22 +452,61 @@ e_auto_hook_map_insert_new_(Arena *arena, E_AutoHookMap *map, E_AutoHookParams * type_key = e_type_key_from_expr(parse.expr); } - // rjf: get type pattern parts - String8List pattern_parts = {0}; + // rjf: extract type pattern + E_Pattern pattern = {0}; if(e_type_key_match(e_type_key_zero(), type_key)) { - U8 pattern_split = '?'; - pattern_parts = str8_split(arena, params->type_pattern, &pattern_split, 1, StringSplitFlag_KeepEmpties); + U64 start_string_off = 0; + for(U64 off = 0; off <= params->type_pattern.size; off += 1) + { + U8 byte = (off < params->type_pattern.size ? params->type_pattern.str[off] : 0); + if(byte == 0 || byte == '?') + { + String8 new_part = str8_substr(params->type_pattern, r1u64(start_string_off, off)); + if(new_part.size != 0) + { + E_PatternPart *p = push_array(arena, E_PatternPart, 1); + SLLQueuePush(pattern.first_part, pattern.last_part, p); + p->string = new_part; + pattern.count += 1; + } + } + if(byte == '?') + { + E_PatternPart *p = push_array(arena, E_PatternPart, 1); + SLLQueuePush(pattern.first_part, pattern.last_part, p); + pattern.count += 1; + if(off+1 < params->type_pattern.size && params->type_pattern.str[off+1] == '{') + { + off += 2; + String8 wildcard_inst_names_string = str8_skip(params->type_pattern, off); + wildcard_inst_names_string = str8_prefix(wildcard_inst_names_string, str8_find_needle(wildcard_inst_names_string, 0, str8_lit("}"), 0)); + if(wildcard_inst_names_string.size != 0) + { + Temp scratch = scratch_begin(&arena, 1); + U8 wildcard_inst_name_split_char = ','; + String8List wildcard_inst_names = str8_split(scratch.arena, wildcard_inst_names_string, &wildcard_inst_name_split_char, 1, 0); + for(String8Node *n = wildcard_inst_names.first; n != 0; n = n->next) + { + str8_list_push(arena, &p->wildcard_inst_names, str8_skip_chop_whitespace(n->string)); + } + scratch_end(scratch); + off += wildcard_inst_names_string.size; + } + } + start_string_off = off+1; + } + } } // rjf: if the type key is nonzero, *or* we have type patterns, then insert - // into map accordingle + // into map accordingly if(!e_type_key_match(e_type_key_zero(), type_key) || - pattern_parts.node_count != 0) + pattern.count != 0) { E_AutoHookNode *node = push_array(arena, E_AutoHookNode, 1); node->type_string = str8_skip_chop_whitespace(e_type_string_from_key(arena, type_key)); - node->type_pattern_parts = pattern_parts; + node->type_pattern = pattern; node->expr_string = push_str8_copy(arena, params->tag_expr_string); if(!e_type_key_match(e_type_key_zero(), type_key)) { @@ -1037,18 +1083,20 @@ e_value_eval_from_eval(E_Eval eval) //- rjf: type key -> auto hooks -internal E_ExprList -e_auto_hook_exprs_from_type_key(Arena *arena, E_TypeKey type_key) +internal E_AutoHookMatchList +e_push_auto_hook_matches_from_type_key(Arena *arena, E_TypeKey type_key) { ProfBeginFunction(); - E_ExprList exprs = {0}; + E_AutoHookMatchList matches = {0}; if(e_ir_ctx != 0) { Temp scratch = scratch_begin(&arena, 1); E_AutoHookMap *map = e_ir_ctx->auto_hook_map; String8 type_string = str8_skip_chop_whitespace(e_type_string_from_key(scratch.arena, type_key)); + //////////////////////////// //- rjf: gather exact-type-key-matches from the map + // if(map != 0 && map->slots_count != 0) { U64 hash = e_hash_from_string(5381, type_string); @@ -1057,44 +1105,132 @@ e_auto_hook_exprs_from_type_key(Arena *arena, E_TypeKey type_key) { if(str8_match(n->type_string, type_string, 0)) { - E_Expr *expr = e_parse_from_string(n->expr_string).expr; - e_expr_list_push(arena, &exprs, expr); + E_AutoHookMatch *match = push_array(arena, E_AutoHookMatch, 1); + SLLQueuePush(matches.first, matches.last, match); + match->expr = e_parse_from_string(n->expr_string).expr; + matches.count += 1; } } } + //////////////////////////// //- rjf: gather fuzzy matches from all patterns in the map + // if(map != 0 && map->first_pattern != 0) { for(E_AutoHookNode *auto_hook_node = map->first_pattern; auto_hook_node != 0; auto_hook_node = auto_hook_node->pattern_order_next) { + //////////////////////// + //- rjf: determine if this pattern fits this type's string; gather wildcard instances + // + E_AutoHookWildcardInst *first_wildcard_inst = 0; + E_AutoHookWildcardInst *last_wildcard_inst = 0; B32 fits_this_type_string = 1; - U64 scan_pos = 0; - for(String8Node *n = auto_hook_node->type_pattern_parts.first; n != 0; n = n->next) { - if(n->string.size == 0) + U64 scan_pos = 0; + for(E_PatternPart *part = auto_hook_node->type_pattern.first_part; part != 0 && fits_this_type_string; part = part->next) { - continue; + String8 pattern_string = part->string; + + //- rjf: skip whitespace + for(;scan_pos < type_string.size;) + { + if(char_is_space(type_string.str[scan_pos])) + { + scan_pos += 1; + } + else + { + break; + } + } + + //- rjf: no pattern string -> wildcard. skip wildcard portion + if(pattern_string.size == 0) + { + String8 terminator_pattern_string = part->next ? part->next->string : str8_zero(); + U64 brace_nest_depth = 0; + U64 paren_nest_depth = 0; + U64 angle_nest_depth = 0; + U64 brack_nest_depth = 0; + U64 start_inst_off = scan_pos; + String8Node *wildcard_inst_name_node = part->wildcard_inst_names.first; + for(B32 done = 0; !done && scan_pos < type_string.size; scan_pos += 1) + { + if(0){} + else if(type_string.str[scan_pos] == '{') { brace_nest_depth += 1; } + else if(type_string.str[scan_pos] == '(') { paren_nest_depth += 1; } + else if(type_string.str[scan_pos] == '<') { angle_nest_depth += 1; } + else if(type_string.str[scan_pos] == '[') { brack_nest_depth += 1; } + else if(type_string.str[scan_pos] == '}' && brace_nest_depth > 0) { brace_nest_depth -= 1; } + else if(type_string.str[scan_pos] == ')' && paren_nest_depth > 0) { paren_nest_depth -= 1; } + else if(type_string.str[scan_pos] == '>' && angle_nest_depth > 0) { angle_nest_depth -= 1; } + else if(type_string.str[scan_pos] == ']' && brack_nest_depth > 0) { brack_nest_depth -= 1; } + else if(part->next == 0) + { + done = 1; + scan_pos = type_string.size; + } + else if(str8_match(terminator_pattern_string, str8_skip(type_string, scan_pos), StringMatchFlag_RightSideSloppy)) + { + done = 1; + } + if((type_string.str[scan_pos] == ',' || done) && + brace_nest_depth == 0 && + paren_nest_depth == 0 && + angle_nest_depth == 0 && + brack_nest_depth == 0) + { + String8 wildcard_inst_string = str8_skip_chop_whitespace(str8_substr(type_string, r1u64(start_inst_off, scan_pos))); + start_inst_off = scan_pos+1; + E_AutoHookWildcardInst *inst = push_array(arena, E_AutoHookWildcardInst, 1); + SLLQueuePush(first_wildcard_inst, last_wildcard_inst, inst); + inst->name = wildcard_inst_name_node ? wildcard_inst_name_node->string : str8_zero(); + inst->inst_expr = e_parse_from_string(wildcard_inst_string).expr; + if(wildcard_inst_name_node) + { + wildcard_inst_name_node = wildcard_inst_name_node->next; + } + } + if(done) + { + break; + } + } + } + + //- rjf: pattern string -> find next occurrence. + else if(pattern_string.size != 0) + { + if(!str8_match(str8_substr(type_string, r1u64(scan_pos, scan_pos+pattern_string.size)), pattern_string, 0)) + { + fits_this_type_string = 0; + } + else + { + scan_pos += pattern_string.size; + } + } } - U64 pattern_part_pos = str8_find_needle(type_string, scan_pos, n->string, 0); - if(pattern_part_pos > scan_pos && n == auto_hook_node->type_pattern_parts.first) + if(fits_this_type_string && scan_pos < type_string.size) { fits_this_type_string = 0; - break; } - if(pattern_part_pos >= type_string.size) - { - fits_this_type_string = 0; - break; - } - scan_pos = pattern_part_pos + n->string.size; } + + //////////////////////// + //- rjf: push match if this type fits + // if(fits_this_type_string) { - E_Expr *expr = e_parse_from_string(auto_hook_node->expr_string).expr; - e_expr_list_push(arena, &exprs, expr); + E_AutoHookMatch *match = push_array(arena, E_AutoHookMatch, 1); + SLLQueuePush(matches.first, matches.last, match); + match->expr = e_parse_from_string(auto_hook_node->expr_string).expr; + match->first_wildcard_inst = first_wildcard_inst; + match->last_wildcard_inst = last_wildcard_inst; + matches.count += 1; } } } @@ -1102,13 +1238,13 @@ e_auto_hook_exprs_from_type_key(Arena *arena, E_TypeKey type_key) scratch_end(scratch); } ProfEnd(); - return exprs; + return matches; } -internal E_ExprList -e_auto_hook_exprs_from_type_key__cached(E_TypeKey type_key) +internal E_AutoHookMatchList +e_auto_hook_matches_from_type_key(E_TypeKey type_key) { - E_ExprList exprs = {0}; + E_AutoHookMatchList matches = {0}; { U64 hash = e_hash_from_string(5381, str8_struct(&type_key)); U64 slot_idx = hash%e_cache->type_auto_hook_cache_map->slots_count; @@ -1127,11 +1263,11 @@ e_auto_hook_exprs_from_type_key__cached(E_TypeKey type_key) node = push_array(e_cache->arena, E_TypeAutoHookCacheNode, 1); SLLQueuePush(e_cache->type_auto_hook_cache_map->slots[slot_idx].first, e_cache->type_auto_hook_cache_map->slots[slot_idx].last, node); node->key = type_key; - node->exprs = e_auto_hook_exprs_from_type_key(e_cache->arena, type_key); + node->matches = e_push_auto_hook_matches_from_type_key(e_cache->arena, type_key); } - exprs = node->exprs; + matches = node->matches; } - return exprs; + return matches; } //- rjf: string IDs @@ -1233,30 +1369,6 @@ e_range_size_from_eval(E_Eval eval) E_TypeKind type_core_kind = e_type_kind_from_key(type_core); B32 got_size = 0; - // rjf: try getting size from expansions - if(!got_size) - { - E_TypeKey maybe_lens_type_key = e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_Meta); - E_TypeKind maybe_lens_type_kind = e_type_kind_from_key(maybe_lens_type_key); - if(maybe_lens_type_kind == E_TypeKind_Lens) - { - E_TypeExpandRule *expand_rule = e_expand_rule_from_type_key(maybe_lens_type_key); - if(expand_rule->info != 0) - { - Temp scratch = scratch_begin(0, 0); - U64 element_size = e_type_byte_size_from_key(e_type_key_unwrap(type_core, E_TypeUnwrapFlag_All)); - E_TypeExpandInfo expand_info = expand_rule->info(scratch.arena, eval, str8_zero()); - U64 new_result_maybe = expand_info.expr_count * element_size; - if(new_result_maybe != 0) - { - result = new_result_maybe; - got_size = 1; - } - scratch_end(scratch); - } - } - } - // rjf: try getting size from intrinsic type (e.g. arrays/etc.) if(!got_size) { diff --git a/src/eval/eval_core.h b/src/eval/eval_core.h index b88f742b..b3f0f567 100644 --- a/src/eval/eval_core.h +++ b/src/eval/eval_core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_CORE_H @@ -663,13 +663,54 @@ struct E_String2TypeKeyMap //////////////////////////////// //~ rjf: Type Pattern -> Hook Key Data Structure (Type Views) +typedef struct E_PatternPart E_PatternPart; +struct E_PatternPart +{ + E_PatternPart *next; + String8 string; + String8List wildcard_inst_names; +}; + +typedef struct E_Pattern E_Pattern; +struct E_Pattern +{ + E_PatternPart *first_part; + E_PatternPart *last_part; + U64 count; +}; + +typedef struct E_AutoHookWildcardInst E_AutoHookWildcardInst; +struct E_AutoHookWildcardInst +{ + E_AutoHookWildcardInst *next; + String8 name; + E_Expr *inst_expr; +}; + +typedef struct E_AutoHookMatch E_AutoHookMatch; +struct E_AutoHookMatch +{ + E_AutoHookMatch *next; + E_Expr *expr; + E_AutoHookWildcardInst *first_wildcard_inst; + E_AutoHookWildcardInst *last_wildcard_inst; +}; + +typedef struct E_AutoHookMatchList E_AutoHookMatchList; +struct E_AutoHookMatchList +{ + E_AutoHookMatch *first; + E_AutoHookMatch *last; + U64 count; +}; + typedef struct E_AutoHookNode E_AutoHookNode; struct E_AutoHookNode { E_AutoHookNode *hash_next; E_AutoHookNode *pattern_order_next; String8 type_string; - String8List type_pattern_parts; + E_Pattern type_pattern; String8 expr_string; }; @@ -890,7 +931,7 @@ struct E_TypeAutoHookCacheNode { E_TypeAutoHookCacheNode *next; E_TypeKey key; - E_ExprList exprs; + E_AutoHookMatchList matches; }; typedef struct E_TypeAutoHookCacheSlot E_TypeAutoHookCacheSlot; @@ -1042,6 +1083,8 @@ struct E_Cache //- rjf: [ir] ir gen options B32 disallow_autohooks; B32 disallow_chained_fastpaths; + E_AutoHookWildcardInst *first_wildcard_inst; + E_AutoHookWildcardInst *last_wildcard_inst; //- rjf: [ir] ir caches E_UsedExprMap *used_expr_map; @@ -1108,6 +1151,7 @@ internal E_MsgList e_msg_list_copy(Arena *arena, E_MsgList *src); //~ rjf: Space Functions internal E_Space e_space_make(E_SpaceKind kind); +internal B32 e_space_match(E_Space a, E_Space b); //////////////////////////////// //~ rjf: Map Functions @@ -1227,8 +1271,8 @@ internal E_Eval e_value_eval_from_eval(E_Eval eval); #define e_value_from_expr(expr) e_value_eval_from_eval(e_eval_from_expr(expr)).value //- rjf: type key -> auto hooks -internal E_ExprList e_auto_hook_exprs_from_type_key(Arena *arena, E_TypeKey type_key); -internal E_ExprList e_auto_hook_exprs_from_type_key__cached(E_TypeKey type_key); +internal E_AutoHookMatchList e_push_auto_hook_matches_from_type_key(Arena *arena, E_TypeKey type_key); +internal E_AutoHookMatchList e_auto_hook_matches_from_type_key(E_TypeKey type_key); //- rjf: string IDs internal U64 e_id_from_string(String8 string); diff --git a/src/eval/eval_inc.c b/src/eval/eval_inc.c index cdfed3bd..d768f814 100644 --- a/src/eval/eval_inc.c +++ b/src/eval/eval_inc.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "eval/eval_core.c" diff --git a/src/eval/eval_inc.h b/src/eval/eval_inc.h index bb03829f..26d81e6e 100644 --- a/src/eval/eval_inc.h +++ b/src/eval/eval_inc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_INC_H diff --git a/src/eval/eval_interpret.c b/src/eval/eval_interpret.c index 5af37288..842c6945 100644 --- a/src/eval/eval_interpret.c +++ b/src/eval/eval_interpret.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/eval/eval_interpret.h b/src/eval/eval_interpret.h index 61ac98f0..cca6cd97 100644 --- a/src/eval/eval_interpret.h +++ b/src/eval/eval_interpret.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_INTERPRET_H diff --git a/src/eval/eval_ir.c b/src/eval/eval_ir.c index 643946c9..1dd8a8ee 100644 --- a/src/eval/eval_ir.c +++ b/src/eval/eval_ir.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -511,7 +511,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(default) { break; } - else if(l_restype_kind != E_TypeKind_Ptr && l_restype_kind != E_TypeKind_Array) + else if(l_restype_kind != E_TypeKind_Ptr && l_restype_kind != E_TypeKind_Array && l_restype_kind != E_TypeKind_LRef && l_restype_kind != E_TypeKind_RRef) { e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, exprl->range, "Cannot index into this type."); break; @@ -567,7 +567,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(default) // rjf: ops to compute the base offset (resolve to value if addr-of-pointer) E_IRNode *base_tree = l.root; - if(l_restype_kind == E_TypeKind_Ptr && l.mode != E_Mode_Value) + if(e_type_kind_is_pointer_or_ref(l_restype_kind) && l.mode != E_Mode_Value) { base_tree = e_irtree_resolve_to_value(arena, l.mode, base_tree, l_restype); } @@ -607,6 +607,8 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I { Task *next; E_Expr *expr; + E_AutoHookWildcardInst *first_wildcard_inst; + E_AutoHookWildcardInst *last_wildcard_inst; E_IRTreeAndType *overridden; }; Task start_task = {0, root_expr, 0}; @@ -620,6 +622,12 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I //- rjf: poison the expression we are about to use, so we don't recursively use it e_expr_poison(expr); + //- rjf: push stack elements + E_AutoHookWildcardInst *first_wildcard_inst_restore = e_cache->first_wildcard_inst; + E_AutoHookWildcardInst *last_wildcard_inst_restore = e_cache->last_wildcard_inst; + if(t->first_wildcard_inst) { e_cache->first_wildcard_inst = t->first_wildcard_inst; } + if(t->last_wildcard_inst) { e_cache->last_wildcard_inst = t->last_wildcard_inst; } + //- rjf: do expr -> irtree generation for this expression if(expr->kind == E_ExprKind_Ref) { @@ -1588,7 +1596,6 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I case E_ExprKind_LeafIdentifier: { Temp scratch = scratch_begin(&arena, 1); - B32 is_auto_hook = 0; String8 qualifier = expr->qualifier; String8 string = expr->string; String8 string__redirected = string; @@ -1614,6 +1621,21 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I { default:{}break; + //- rjf: try to map name as a wildcard instance + case E_IdentifierResolutionPath_WildcardInst: + if(!generated && qualifier.size == 0 && !string_mapped && e_cache->first_wildcard_inst != 0) + { + for(E_AutoHookWildcardInst *inst = e_cache->first_wildcard_inst; inst != 0; inst = inst->next) + { + if(str8_match(inst->name, string, 0)) + { + generated = 1; + result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, inst->inst_expr); + break; + } + } + }break; + //- rjf: try to map name as parent expression signifier ('$') case E_IdentifierResolutionPath_ParentExpr: if(qualifier.size == 0 && !string_mapped && str8_match(string, str8_lit("$"), 0) && parent != 0 && (parent->root != &e_irnode_nil || parent->msgs.first != 0)) @@ -1629,16 +1651,18 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I } } } - E_OpList oplist = e_oplist_from_irtree(arena, parent_irtree->root); string_mapped = 1; - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = parent_irtree->mode; - mapped_type_key = parent_irtree->type_key; - mapped_user_data = parent_irtree->user_data; - is_auto_hook = parent_irtree->auto_hook; + generated = 1; disallow_autohooks = 1; + E_OpList oplist = e_oplist_from_irtree(scratch.arena, parent_irtree->root); + String8 bytecode = e_bytecode_from_oplist(arena, &oplist); + result.root = e_irtree_bytecode_no_copy(arena, bytecode); + result.type_key = parent_irtree->type_key; + result.mode = parent_irtree->mode; + result.auto_hook = parent_irtree->auto_hook; E_MsgList msgs = e_msg_list_copy(arena, &parent_irtree->msgs); e_msg_list_concat_in_place(&result.msgs, &msgs); + result.prev = parent_irtree->prev; } break; @@ -1715,10 +1739,11 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I } }break; - //- rjf: globals / procedures / types + //- rjf: globals / procedures / types / constants case E_IdentifierResolutionPath_Globals: case E_IdentifierResolutionPath_Procedures: case E_IdentifierResolutionPath_ThreadLocals: + case E_IdentifierResolutionPath_Constants: { //- rjf: form namespaceified fallback versions of this lookup string if(!string_mapped) @@ -1824,6 +1849,75 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I } } + //- 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) + { + 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)module_idx); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Value; + mapped_bytecode_space = module->space; + break; + } + } + } + } + } + //- rjf: try procedures if(path == E_IdentifierResolutionPath_Procedures && !string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("procedure"), 0))) { @@ -1915,27 +2009,6 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I } }break; - //- rjf: try basic constants - case E_IdentifierResolutionPath_Constants: - if(!string_mapped && 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; - } - if(!string_mapped && 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; - }break; - //- rjf: try macros case E_IdentifierResolutionPath_Macros: { @@ -2073,10 +2146,6 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I result = e_push_irtree_and_type_from_expr(arena, parent, &e_default_identifier_resolution_rule, disallow_autohooks, 1, access); } - //- rjf: mark if auto hook, equip user data - result.auto_hook = is_auto_hook; - result.user_data = mapped_user_data; - //- rjf: error on failure-to-generate if(!generated && !str8_match(string, str8_lit("$"), 0)) { @@ -2357,10 +2426,27 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I } //- rjf: equip previous task's irtree - if(parent != 0) + if(parent != 0 && parent->root != &e_irnode_nil) { - result.prev = push_array(arena, E_IRTreeAndType, 1); - result.prev[0] = *parent; + E_IRTreeAndType *new_chain = push_array(arena, E_IRTreeAndType, 1); + MemoryCopyStruct(new_chain, parent); + E_IRTreeAndType *first_chain = 0; + E_IRTreeAndType *last_chain = 0; + if(result.prev) + { + for(E_IRTreeAndType *p = result.prev; p != 0; p = p->prev) + { + E_IRTreeAndType *p_copy = push_array(arena, E_IRTreeAndType, 1); + MemoryCopyStruct(p_copy, p); + SLLQueuePush_N(first_chain, last_chain, p_copy, prev); + } + SLLQueuePushFront_N(first_chain, last_chain, new_chain, prev); + result.prev = first_chain; + } + else + { + result.prev = new_chain; + } } //- rjf: mark this result as an auto-hook, if we have an override @@ -2369,24 +2455,27 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I result.auto_hook = 1; } + //- rjf: restore stack elements + e_cache->first_wildcard_inst = first_wildcard_inst_restore; + e_cache->last_wildcard_inst = last_wildcard_inst_restore; + //- rjf: find any auto hooks according to this generation's type if(!disallow_autohooks && result.mode != E_Mode_Null) { - E_ExprList exprs = e_auto_hook_exprs_from_type_key__cached(result.type_key); - for(E_ExprNode *n = exprs.first; n != 0; n = n->next) + E_AutoHookMatchList matches = e_auto_hook_matches_from_type_key(result.type_key); + for(E_AutoHookMatch *match = matches.first; match != 0; match = match->next) { - for(E_Expr *e = n->v; e != &e_expr_nil; e = e->next) + B32 e_is_poisoned = e_expr_is_poisoned(match->expr); + if(!e_is_poisoned) { - B32 e_is_poisoned = e_expr_is_poisoned(e); - if(!e_is_poisoned) - { - Task *task = push_array(scratch.arena, Task, 1); - SLLQueuePush(first_task, last_task, task); - task->expr = e; - task->overridden = push_array(scratch.arena, E_IRTreeAndType, 1); - task->overridden[0] = result; - goto end_autohook_find; - } + Task *task = push_array(scratch.arena, Task, 1); + SLLQueuePush(first_task, last_task, task); + task->expr = match->expr; + task->first_wildcard_inst = match->first_wildcard_inst; + task->last_wildcard_inst = match->last_wildcard_inst; + task->overridden = push_array(scratch.arena, E_IRTreeAndType, 1); + task->overridden[0] = result; + goto end_autohook_find; } } end_autohook_find:; diff --git a/src/eval/eval_ir.h b/src/eval/eval_ir.h index c7b9e338..105250ae 100644 --- a/src/eval/eval_ir.h +++ b/src/eval/eval_ir.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_IR_H @@ -9,17 +9,18 @@ typedef enum E_IdentifierResolutionPath { + E_IdentifierResolutionPath_WildcardInst, E_IdentifierResolutionPath_ParentExpr, 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_Registers, E_IdentifierResolutionPath_RegisterAliases, - E_IdentifierResolutionPath_Constants, E_IdentifierResolutionPath_Macros, } E_IdentifierResolutionPath; @@ -81,17 +82,18 @@ struct E_IRState E_IdentifierResolutionPath e_default_identifier_resolution_paths[] = { + E_IdentifierResolutionPath_WildcardInst, E_IdentifierResolutionPath_ParentExpr, 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_Registers, E_IdentifierResolutionPath_RegisterAliases, - E_IdentifierResolutionPath_Constants, E_IdentifierResolutionPath_Macros, }; E_IdentifierResolutionRule e_default_identifier_resolution_rule = @@ -103,17 +105,18 @@ E_IdentifierResolutionRule e_default_identifier_resolution_rule = E_IdentifierResolutionPath e_callable_identifier_resolution_paths[] = { E_IdentifierResolutionPath_Macros, + E_IdentifierResolutionPath_WildcardInst, E_IdentifierResolutionPath_ParentExpr, 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_Registers, E_IdentifierResolutionPath_RegisterAliases, - E_IdentifierResolutionPath_Constants, }; E_IdentifierResolutionRule e_callable_identifier_resolution_rule = { diff --git a/src/eval/eval_parse.c b/src/eval/eval_parse.c index a82b01db..937ce6c5 100644 --- a/src/eval/eval_parse.c +++ b/src/eval/eval_parse.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -57,6 +57,7 @@ e_token_array_from_chunk_list(Arena *arena, E_TokenChunkList *list) for(E_TokenChunkNode *node = list->first; node != 0; node = node->next) { MemoryCopy(array.v+idx, node->v, sizeof(E_Token)*node->count); + idx += node->count; } return array; } diff --git a/src/eval/eval_parse.h b/src/eval/eval_parse.h index c8e91b4b..d3021dcc 100644 --- a/src/eval/eval_parse.h +++ b/src/eval/eval_parse.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_PARSE_H diff --git a/src/eval/eval_types.c b/src/eval/eval_types.c index 4db6fab9..b1f22135 100644 --- a/src/eval/eval_types.c +++ b/src/eval/eval_types.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -1309,6 +1309,7 @@ e_type_data_members_from_key(Arena *arena, E_TypeKey key) SLLQueuePush(members_list.first, members_list.last, n); members_list.count += 1; members_need_offset_sort = members_need_offset_sort || (type->members[member_idx].kind == E_MemberKind_DataField && n->v.off < last_member_off); + members_need_offset_sort = members_need_offset_sort || (type->members[member_idx].kind != E_MemberKind_DataField); last_member_off = n->v.off; } else if(type->members[member_idx].kind == E_MemberKind_Base) @@ -2307,7 +2308,9 @@ E_TYPE_EXPAND_INFO_FUNCTION_DEF(default) { E_TypeKind array_type_kind = e_type_kind_from_key(expand_type_key); if(array_type_kind == E_TypeKind_Array || - array_type_kind == E_TypeKind_Ptr) + array_type_kind == E_TypeKind_Ptr || + array_type_kind == E_TypeKind_RRef || + array_type_kind == E_TypeKind_LRef) { E_Type *array_type = e_type_from_key(expand_type_key); result.expr_count = array_type->count; @@ -2383,6 +2386,8 @@ E_TYPE_EXPAND_RANGE_FUNCTION_DEF(default) //- rjf: ptr case -> the lookup-range will return a range of dereferences else if(expand_type_kind == E_TypeKind_Ptr || + expand_type_kind == E_TypeKind_LRef || + expand_type_kind == E_TypeKind_RRef || expand_type_kind == E_TypeKind_Array || expand_type_kind == E_TypeKind_Set) { @@ -2536,7 +2541,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(eval.parent_key) + if(type->args != 0 && type->count > 0) E_ParentKey(e_key_match(e_key_zero(), eval.parent_key) ? eval.key : eval.parent_key) { E_Key count_key = e_key_from_expr(type->args[0]); E_Value count_value = e_value_from_key(count_key); diff --git a/src/eval/eval_types.h b/src/eval/eval_types.h index 1e771975..b8274315 100644 --- a/src/eval/eval_types.h +++ b/src/eval/eval_types.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_TYPES_H diff --git a/src/eval/generated/eval.meta.c b/src/eval/generated/eval.meta.c index a1305840..c4be0989 100644 --- a/src/eval/generated/eval.meta.c +++ b/src/eval/generated/eval.meta.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/eval/generated/eval.meta.h b/src/eval/generated/eval.meta.h index e85f1b0f..178dec89 100644 --- a/src/eval/generated/eval.meta.h +++ b/src/eval/generated/eval.meta.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/eval_visualization/eval_visualization_core.c b/src/eval_visualization/eval_visualization_core.c index 84778d07..c6bbab59 100644 --- a/src/eval_visualization/eval_visualization_core.c +++ b/src/eval_visualization/eval_visualization_core.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/eval_visualization/eval_visualization_core.h b/src/eval_visualization/eval_visualization_core.h index 5f5a8d9d..daf46c2e 100644 --- a/src/eval_visualization/eval_visualization_core.h +++ b/src/eval_visualization/eval_visualization_core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_VISUALIZATION_CORE_H diff --git a/src/eval_visualization/eval_visualization_inc.c b/src/eval_visualization/eval_visualization_inc.c index d944d937..012e8c7b 100644 --- a/src/eval_visualization/eval_visualization_inc.c +++ b/src/eval_visualization/eval_visualization_inc.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "eval_visualization_core.c" diff --git a/src/eval_visualization/eval_visualization_inc.h b/src/eval_visualization/eval_visualization_inc.h index 11c9b212..22d4aa63 100644 --- a/src/eval_visualization/eval_visualization_inc.h +++ b/src/eval_visualization/eval_visualization_inc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef EVAL_VISUALIZATION_INC_H diff --git a/src/file_stream/file_stream.c b/src/file_stream/file_stream.c index feb6d815..959ce166 100644 --- a/src/file_stream/file_stream.c +++ b/src/file_stream/file_stream.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR diff --git a/src/file_stream/file_stream.h b/src/file_stream/file_stream.h index a0ede57c..e4c06ba6 100644 --- a/src/file_stream/file_stream.h +++ b/src/file_stream/file_stream.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef FILE_STREAM_H diff --git a/src/font_cache/font_cache.c b/src/font_cache/font_cache.c index 44fea4d1..330e03bc 100644 --- a/src/font_cache/font_cache.c +++ b/src/font_cache/font_cache.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/font_cache/font_cache.h b/src/font_cache/font_cache.h index 4bc6b0b7..647cfaf4 100644 --- a/src/font_cache/font_cache.h +++ b/src/font_cache/font_cache.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef FONT_CACHE_H diff --git a/src/font_provider/dwrite/font_provider_dwrite.c b/src/font_provider/dwrite/font_provider_dwrite.c index 003fd299..66c4a235 100644 --- a/src/font_provider/dwrite/font_provider_dwrite.c +++ b/src/font_provider/dwrite/font_provider_dwrite.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/font_provider/dwrite/font_provider_dwrite.h b/src/font_provider/dwrite/font_provider_dwrite.h index f4533c7a..80c8b32f 100644 --- a/src/font_provider/dwrite/font_provider_dwrite.h +++ b/src/font_provider/dwrite/font_provider_dwrite.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef FONT_PROVIDER_DWRITE_H diff --git a/src/font_provider/font_provider.c b/src/font_provider/font_provider.c index 4b5298a6..cabfda88 100644 --- a/src/font_provider/font_provider.c +++ b/src/font_provider/font_provider.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/font_provider/font_provider.h b/src/font_provider/font_provider.h index f836aa19..80fd608d 100644 --- a/src/font_provider/font_provider.h +++ b/src/font_provider/font_provider.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef FONT_PROVIDER_H diff --git a/src/font_provider/font_provider_inc.c b/src/font_provider/font_provider_inc.c index c589b27a..7b10141b 100644 --- a/src/font_provider/font_provider_inc.c +++ b/src/font_provider/font_provider_inc.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "font_provider.c" diff --git a/src/font_provider/font_provider_inc.h b/src/font_provider/font_provider_inc.h index c3001d25..a2844ac0 100644 --- a/src/font_provider/font_provider_inc.h +++ b/src/font_provider/font_provider_inc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef FONT_PROVIDER_INC_H diff --git a/src/font_provider/freetype/font_provider_freetype.c b/src/font_provider/freetype/font_provider_freetype.c index b98735b8..338efdbb 100644 --- a/src/font_provider/freetype/font_provider_freetype.c +++ b/src/font_provider/freetype/font_provider_freetype.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/font_provider/freetype/font_provider_freetype.h b/src/font_provider/freetype/font_provider_freetype.h index b1e37c2f..d18f440d 100644 --- a/src/font_provider/freetype/font_provider_freetype.h +++ b/src/font_provider/freetype/font_provider_freetype.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef FONT_PROVIDER_FREETYPE_H diff --git a/src/geo_cache/geo_cache.c b/src/geo_cache/geo_cache.c index dd7fa2e0..298888b7 100644 --- a/src/geo_cache/geo_cache.c +++ b/src/geo_cache/geo_cache.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR diff --git a/src/geo_cache/geo_cache.h b/src/geo_cache/geo_cache.h index d343be8e..7ba1cc99 100644 --- a/src/geo_cache/geo_cache.h +++ b/src/geo_cache/geo_cache.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef GEO_CACHE_H diff --git a/src/hash_store/hash_store.c b/src/hash_store/hash_store.c index f7b819e9..16b64186 100644 --- a/src/hash_store/hash_store.c +++ b/src/hash_store/hash_store.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR @@ -114,7 +114,7 @@ hs_root_alloc(void) { HS_Root root = {0}; root.u64[0] = ins_atomic_u64_inc_eval(&hs_shared->root_id_gen); - U64 slot_idx = root.u64[1]%hs_shared->root_slots_count; + U64 slot_idx = root.u64[0]%hs_shared->root_slots_count; U64 stripe_idx = slot_idx%hs_shared->root_stripes_count; HS_RootSlot *slot = &hs_shared->root_slots[slot_idx]; HS_Stripe *stripe = &hs_shared->root_stripes[stripe_idx]; @@ -140,7 +140,7 @@ internal void hs_root_release(HS_Root root) { //- rjf: unpack root - U64 slot_idx = root.u64[1]%hs_shared->root_slots_count; + U64 slot_idx = root.u64[0]%hs_shared->root_slots_count; U64 stripe_idx = slot_idx%hs_shared->root_stripes_count; HS_RootSlot *slot = &hs_shared->root_slots[slot_idx]; HS_Stripe *stripe = &hs_shared->root_stripes[stripe_idx]; diff --git a/src/hash_store/hash_store.h b/src/hash_store/hash_store.h index 8141eeb9..f193b3b1 100644 --- a/src/hash_store/hash_store.h +++ b/src/hash_store/hash_store.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef HASH_STORE_H diff --git a/src/lib_raddbg_markup/raddbg_markup.h b/src/lib_raddbg_markup/raddbg_markup.h index e1257cf4..fce7545b 100644 --- a/src/lib_raddbg_markup/raddbg_markup.h +++ b/src/lib_raddbg_markup/raddbg_markup.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDBG_MARKUP_H @@ -37,6 +37,7 @@ # define raddbg_type_view(type, ...) raddbg_exe_data char raddbg_gen_data_id()[] = ("type_view: {type: ```" #type "```, expr: ```" #__VA_ARGS__ "```}") # define raddbg_add_breakpoint(ptr, size, r, w, x) raddbg_add_or_remove_breakpoint__impl((ptr), (1), (size), (r), (w), (x)) # define raddbg_remove_breakpoint(ptr, size, r, w, x) raddbg_add_or_remove_breakpoint__impl((ptr), (0), (size), (r), (w), (x)) +# define raddbg_annotate_vaddr_range(ptr, size, ...) raddbg_annotate_vaddr_range__impl((ptr), (size), __VA_ARGS__) #else # define raddbg_is_attached(...) (0) # define raddbg_thread_id(...) ((void)0) @@ -55,6 +56,7 @@ # define raddbg_type_view(type, ...) struct raddbg_gen_data_id(){int __unused__;} # define raddbg_add_breakpoint(ptr, size, r, w, x) ((void)0) # define raddbg_remove_breakpoint(ptr, size, r, w, x) ((void)0) +# define raddbg_annotate_vaddr_range(ptr, size, ...) ((void)0) #endif //////////////////////////////// @@ -64,23 +66,39 @@ #define raddbg_glue(a, b) raddbg_glue_(a, b) #define raddbg_gen_data_id() raddbg_glue(raddbg_data__, __COUNTER__) +//////////////////////////////// +//~ Global Symbols + +#if !defined(RADDBG_MARKUP_STUBS) +int raddbg_is_attached__impl(void); +int raddbg_thread_id__impl(void); +void raddbg_thread_name__impl(int id, char *fmt, ...); +void raddbg_thread_color__impl(int id, unsigned int hexcode); +void raddbg_watch__impl(char *fmt, ...); +void raddbg_log__impl(char *fmt, ...); +void raddbg_add_or_remove_breakpoint__impl(void *ptr, int set, int size, int r, int w, int x); +void raddbg_annotate_vaddr_range__impl(void *ptr, unsigned __int64 size, char *fmt, ...); +#endif + //////////////////////////////// //~ Win32 Implementations -#if defined(RADDBG_MARKUP_IMPLEMENTATION) && !defined(RADDBG_MARKUP_STUBS) -#if defined(_WIN32) +#if defined(_WIN32) && !defined(RADDBG_MARKUP_STUBS) + +//- section allocating +#pragma section(".raddbg", read, write) +#define raddbg_exe_data __declspec(allocate(".raddbg")) + +//- one-time implementations +#if defined(RADDBG_MARKUP_IMPLEMENTATION) //- default includes #if RADDBG_MARKUP_DEFAULT_VSNPRINTF #include #endif -//- section allocating -#pragma section(".raddbg", read, write) -#define raddbg_exe_data __declspec(allocate(".raddbg")) - //- first byte of exe data section -> is attached -raddbg_exe_data unsigned char raddbg_is_attached_byte_marker[1]; +static raddbg_exe_data unsigned char raddbg_is_attached_byte_marker[1]; //- types @@ -135,7 +153,7 @@ struct RADDBG_MARKUP_UnicodeDecode }; static __int8 raddbg_utf8_class[32] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,2,2,2,2,3,3,4,5}; -static inline RADDBG_MARKUP_UnicodeDecode +static RADDBG_MARKUP_UnicodeDecode raddbg_decode_utf8(char *str, unsigned __int64 max) { RADDBG_MARKUP_UnicodeDecode result = {1, 0xffffffff}; @@ -190,7 +208,7 @@ raddbg_decode_utf8(char *str, unsigned __int64 max) return result; } -static inline unsigned __int32 +static unsigned __int32 raddbg_encode_utf16(wchar_t *str, unsigned __int32 codepoint) { unsigned __int32 inc = 1; @@ -214,20 +232,20 @@ raddbg_encode_utf16(wchar_t *str, unsigned __int32 codepoint) //- implementations -static inline int +int raddbg_is_attached__impl(void) { return !!raddbg_is_attached_byte_marker[0]; } -static inline int +int raddbg_thread_id__impl(void) { DWORD result = GetCurrentThreadId(); return result; } -static inline void +void raddbg_thread_name__impl(int id, char *fmt, ...) { // rjf: resolve variadic arguments @@ -307,7 +325,7 @@ raddbg_thread_name__impl(int id, char *fmt, ...) } } -static inline void +void raddbg_thread_color__impl(int id, unsigned int hexcode) { if(raddbg_is_attached()) @@ -340,13 +358,13 @@ raddbg_thread_color__impl(int id, unsigned int hexcode) #define raddbg_break__impl() (__debugbreak()) -static inline void +void raddbg_watch__impl(char *fmt, ...) { // TODO(rjf) } -static inline void +void raddbg_log__impl(char *fmt, ...) { // rjf: resolve variadic arguments @@ -362,7 +380,7 @@ raddbg_log__impl(char *fmt, ...) OutputDebugStringA(buffer); } -static inline void +void raddbg_add_or_remove_breakpoint__impl(void *ptr, int set, int size, int r, int w, int x) { if(raddbg_is_attached()) @@ -399,8 +417,52 @@ raddbg_add_or_remove_breakpoint__impl(void *ptr, int set, int size, int r, int w } } -#endif // defined(_WIN32) +void +raddbg_annotate_vaddr_range__impl(void *ptr, unsigned __int64 size, char *fmt, ...) +{ + if(raddbg_is_attached()) + { + // rjf: resolve variadic arguments + char buffer[4096]; + int buffer_size = 0; + { + va_list args; + va_start(args, fmt); + buffer_size = RADDBG_MARKUP_VSNPRINTF(buffer, sizeof(buffer), fmt, args); + va_end(args); + } + + // rjf: send annotation info via exception +#pragma pack(push, 8) + typedef struct RADDBG_VaddrRangeAnnotationInfo RADDBG_VaddrRangeAnnotationInfo; + struct RADDBG_VaddrRangeAnnotationInfo + { + unsigned __int64 vaddr; + unsigned __int64 size; + void *name; + unsigned __int64 name_size; + }; +#pragma pack(pop) + RADDBG_VaddrRangeAnnotationInfo info; + info.vaddr = (unsigned __int64)ptr; + info.size = size; + info.name = buffer; + info.name_size = buffer_size; +#pragma warning(push) +#pragma warning(disable: 6320 6322) + __try + { + RaiseException(0x00524156u, 0, sizeof(info) / sizeof(void *), (const ULONG_PTR *)&info); + } + __except(1) + { + } +#pragma warning(pop) + } +} + #endif // defined(RADDBG_MARKUP_IMPLEMENTATION) +#endif // defined(_WIN32) && !defined(RADDBG_MARKUP_STUBS) //////////////////////////////// //~ Win32 STL Type Views diff --git a/src/lib_rdi_format/rdi_format.c b/src/lib_rdi_format/rdi_format.c index 57f02162..5d301b95 100644 --- a/src/lib_rdi_format/rdi_format.c +++ b/src/lib_rdi_format/rdi_format.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////////////////////////////////////// @@ -10,7 +10,7 @@ #ifndef RDI_FORMAT_C #define RDI_FORMAT_C -RDI_U16 rdi_section_element_size_table[37] = +RDI_U16 rdi_section_element_size_table[40] = { sizeof(RDI_U8), sizeof(RDI_TopLevelInfo), @@ -37,6 +37,7 @@ sizeof(RDI_EnumMember), sizeof(RDI_GlobalVariable), sizeof(RDI_VMapEntry), sizeof(RDI_ThreadVariable), +sizeof(RDI_Constant), sizeof(RDI_Procedure), sizeof(RDI_Scope), sizeof(RDI_U64), @@ -45,13 +46,15 @@ sizeof(RDI_InlineSite), sizeof(RDI_Local), sizeof(RDI_LocationBlock), sizeof(RDI_U8), +sizeof(RDI_U8), +sizeof(RDI_U32), sizeof(RDI_NameMap), sizeof(RDI_NameMapBucket), sizeof(RDI_NameMapNode), sizeof(RDI_U8), }; -RDI_U8 rdi_section_is_required_table[37] = +RDI_U8 rdi_section_is_required_table[40] = { 0, 0, @@ -90,6 +93,9 @@ RDI_U8 rdi_section_is_required_table[37] = 0, 0, 0, +0, +0, +0, }; RDI_U16 rdi_eval_op_ctrlbits_table[52] = diff --git a/src/lib_rdi_format/rdi_format.h b/src/lib_rdi_format/rdi_format.h index 23149735..4127f15b 100644 --- a/src/lib_rdi_format/rdi_format.h +++ b/src/lib_rdi_format/rdi_format.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////////////////////////////////////// @@ -52,7 +52,7 @@ typedef int64_t RDI_S64; // "raddbg\0\0" #define RDI_MAGIC_CONSTANT 0x0000676264646172 -#define RDI_ENCODING_VERSION 11 +#define RDI_ENCODING_VERSION 12 //////////////////////////////////////////////////////////////// //~ Format Types & Functions @@ -85,18 +85,21 @@ RDI_SectionKind_EnumMembers = 0x0015, RDI_SectionKind_GlobalVariables = 0x0016, RDI_SectionKind_GlobalVMap = 0x0017, RDI_SectionKind_ThreadVariables = 0x0018, -RDI_SectionKind_Procedures = 0x0019, -RDI_SectionKind_Scopes = 0x001A, -RDI_SectionKind_ScopeVOffData = 0x001B, -RDI_SectionKind_ScopeVMap = 0x001C, -RDI_SectionKind_InlineSites = 0x001D, -RDI_SectionKind_Locals = 0x001E, -RDI_SectionKind_LocationBlocks = 0x001F, -RDI_SectionKind_LocationData = 0x0020, -RDI_SectionKind_NameMaps = 0x0021, -RDI_SectionKind_NameMapBuckets = 0x0022, -RDI_SectionKind_NameMapNodes = 0x0023, -RDI_SectionKind_COUNT = 0x0024, +RDI_SectionKind_Constants = 0x0019, +RDI_SectionKind_Procedures = 0x001A, +RDI_SectionKind_Scopes = 0x001B, +RDI_SectionKind_ScopeVOffData = 0x001C, +RDI_SectionKind_ScopeVMap = 0x001D, +RDI_SectionKind_InlineSites = 0x001E, +RDI_SectionKind_Locals = 0x001F, +RDI_SectionKind_LocationBlocks = 0x0020, +RDI_SectionKind_LocationData = 0x0021, +RDI_SectionKind_ConstantValueData = 0x0022, +RDI_SectionKind_ConstantValueTable = 0x0023, +RDI_SectionKind_NameMaps = 0x0024, +RDI_SectionKind_NameMapBuckets = 0x0025, +RDI_SectionKind_NameMapNodes = 0x0026, +RDI_SectionKind_COUNT = 0x0027, } RDI_SectionKindEnum; typedef RDI_U32 RDI_SectionEncoding; @@ -522,11 +525,12 @@ typedef enum RDI_NameMapKindEnum RDI_NameMapKind_NULL = 0, RDI_NameMapKind_GlobalVariables = 1, RDI_NameMapKind_ThreadVariables = 2, -RDI_NameMapKind_Procedures = 3, -RDI_NameMapKind_Types = 4, -RDI_NameMapKind_LinkNameProcedures = 5, -RDI_NameMapKind_NormalSourcePaths = 6, -RDI_NameMapKind_COUNT = 7, +RDI_NameMapKind_Constants = 3, +RDI_NameMapKind_Procedures = 4, +RDI_NameMapKind_Types = 5, +RDI_NameMapKind_LinkNameProcedures = 6, +RDI_NameMapKind_NormalSourcePaths = 7, +RDI_NameMapKind_COUNT = 8, } RDI_NameMapKindEnum; #define RDI_Header_XList \ @@ -561,6 +565,7 @@ X(EnumMembers, enum_members, RDI_EnumMember)\ X(GlobalVariables, global_variables, RDI_GlobalVariable)\ X(GlobalVMap, global_vmap, RDI_VMapEntry)\ X(ThreadVariables, thread_variables, RDI_ThreadVariable)\ +X(Constants, constants, RDI_Constant)\ X(Procedures, procedures, RDI_Procedure)\ X(Scopes, scopes, RDI_Scope)\ X(ScopeVOffData, scope_voff_data, RDI_U64)\ @@ -569,6 +574,8 @@ X(InlineSites, inline_sites, RDI_InlineSite)\ X(Locals, locals, RDI_Local)\ X(LocationBlocks, location_blocks, RDI_LocationBlock)\ X(LocationData, location_data, RDI_U8)\ +X(ConstantValueData, constant_value_data, RDI_U8)\ +X(ConstantValueTable, constant_value_table, RDI_U32)\ X(NameMaps, name_maps, RDI_NameMap)\ X(NameMapBuckets, name_map_buckets, RDI_NameMapBucket)\ X(NameMapNodes, name_map_nodes, RDI_NameMapNode)\ @@ -1091,6 +1098,7 @@ X(FromOther)\ X(NULL)\ X(GlobalVariables)\ X(ThreadVariables)\ +X(Constants)\ X(Procedures)\ X(Types)\ X(LinkNameProcedures)\ @@ -1132,6 +1140,7 @@ typedef struct RDI_U32_Members { RDI_U32 v; } RDI_U32_Member typedef struct RDI_U32_EnumMembers { RDI_U32 v; } RDI_U32_EnumMembers; typedef struct RDI_U32_GlobalVariables { RDI_U32 v; } RDI_U32_GlobalVariables; typedef struct RDI_U32_ThreadVariables { RDI_U32 v; } RDI_U32_ThreadVariables; +typedef struct RDI_U32_Constants { RDI_U32 v; } RDI_U32_Constants; typedef struct RDI_U32_Procedures { RDI_U32 v; } RDI_U32_Procedures; typedef struct RDI_U32_Scopes { RDI_U32 v; } RDI_U32_Scopes; typedef struct RDI_U32_ScopeVOffData { RDI_U32 v; } RDI_U32_ScopeVOffData; @@ -1139,6 +1148,8 @@ typedef struct RDI_U32_InlineSites { RDI_U32 v; } RDI_U32_Inline typedef struct RDI_U32_Locals { RDI_U32 v; } RDI_U32_Locals; typedef struct RDI_U32_LocationBlocks { RDI_U32 v; } RDI_U32_LocationBlocks; typedef struct RDI_U32_LocationData { RDI_U32 v; } RDI_U32_LocationData; +typedef struct RDI_U32_ConstantValueData { RDI_U32 v; } RDI_U32_ConstantValueData; +typedef struct RDI_U32_ConstantValueTable { RDI_U32 v; } RDI_U32_ConstantValueTable; typedef struct RDI_U32_NameMaps { RDI_U32 v; } RDI_U32_NameMaps; typedef struct RDI_U32_NameMapBuckets { RDI_U32 v; } RDI_U32_NameMapBuckets; typedef struct RDI_U32_NameMapNodes { RDI_U32 v; } RDI_U32_NameMapNodes; @@ -1165,6 +1176,7 @@ typedef RDI_U32_Table RDI_U32_Members; typedef RDI_U32_Table RDI_U32_EnumMembers; typedef RDI_U32_Table RDI_U32_GlobalVariables; typedef RDI_U32_Table RDI_U32_ThreadVariables; +typedef RDI_U32_Table RDI_U32_Constants; typedef RDI_U32_Table RDI_U32_Procedures; typedef RDI_U32_Table RDI_U32_Scopes; typedef RDI_U32_Table RDI_U32_ScopeVOffData; @@ -1172,6 +1184,8 @@ typedef RDI_U32_Table RDI_U32_InlineSites; typedef RDI_U32_Table RDI_U32_Locals; typedef RDI_U32_Table RDI_U32_LocationBlocks; typedef RDI_U32_Table RDI_U32_LocationData; +typedef RDI_U32_Table RDI_U32_ConstantValueData; +typedef RDI_U32_Table RDI_U32_ConstantValueTable; typedef RDI_U32_Table RDI_U32_NameMaps; typedef RDI_U32_Table RDI_U32_NameMapBuckets; typedef RDI_U32_Table RDI_U32_NameMapNodes; @@ -1396,6 +1410,14 @@ RDI_U32 type_idx; RDI_U32 container_idx; }; +typedef struct RDI_Constant RDI_Constant; +struct RDI_Constant +{ +RDI_U32 name_string_idx; +RDI_U32 type_idx; +RDI_U32 constant_value_idx; +}; + typedef struct RDI_Procedure RDI_Procedure; struct RDI_Procedure { @@ -1522,6 +1544,7 @@ typedef RDI_EnumMember RDI_SectionElementType_EnumMembers; typedef RDI_GlobalVariable RDI_SectionElementType_GlobalVariables; typedef RDI_VMapEntry RDI_SectionElementType_GlobalVMap; typedef RDI_ThreadVariable RDI_SectionElementType_ThreadVariables; +typedef RDI_Constant RDI_SectionElementType_Constants; typedef RDI_Procedure RDI_SectionElementType_Procedures; typedef RDI_Scope RDI_SectionElementType_Scopes; typedef RDI_U64 RDI_SectionElementType_ScopeVOffData; @@ -1530,20 +1553,22 @@ typedef RDI_InlineSite RDI_SectionElementType_InlineSites; typedef RDI_Local RDI_SectionElementType_Locals; typedef RDI_LocationBlock RDI_SectionElementType_LocationBlocks; typedef RDI_U8 RDI_SectionElementType_LocationData; +typedef RDI_U8 RDI_SectionElementType_ConstantValueData; +typedef RDI_U32 RDI_SectionElementType_ConstantValueTable; typedef RDI_NameMap RDI_SectionElementType_NameMaps; typedef RDI_NameMapBucket RDI_SectionElementType_NameMapBuckets; typedef RDI_NameMapNode RDI_SectionElementType_NameMapNodes; RDI_PROC RDI_U64 rdi_hash(RDI_U8 *ptr, RDI_U64 size); +RDI_PROC RDI_U8 *rdi_string_from_type_kind(RDI_TypeKind kind, RDI_U64 *size_out); RDI_PROC RDI_U32 rdi_size_from_basic_type_kind(RDI_TypeKind kind); RDI_PROC RDI_U32 rdi_addr_size_from_arch(RDI_Arch arch); RDI_PROC RDI_EvalConversionKind rdi_eval_conversion_kind_from_typegroups(RDI_EvalTypeGroup in, RDI_EvalTypeGroup out); RDI_PROC RDI_S32 rdi_eval_op_typegroup_are_compatible(RDI_EvalOp op, RDI_EvalTypeGroup group); RDI_PROC RDI_U8 *rdi_explanation_string_from_eval_conversion_kind(RDI_EvalConversionKind kind, RDI_U64 *size_out); -RDI_PROC RDI_U8 *rdi_string_from_type_kind(RDI_TypeKind kind, RDI_U64 *size_out); -extern RDI_U16 rdi_section_element_size_table[37]; -extern RDI_U8 rdi_section_is_required_table[37]; +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 diff --git a/src/lib_rdi_format/rdi_format_parse.c b/src/lib_rdi_format/rdi_format_parse.c index 3439589e..7b7db4b9 100644 --- a/src/lib_rdi_format/rdi_format_parse.c +++ b/src/lib_rdi_format/rdi_format_parse.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -647,8 +647,12 @@ 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_U64 *voffs = rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_opl); - RDI_U64 result = *voffs; + 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; } diff --git a/src/lib_rdi_format/rdi_format_parse.h b/src/lib_rdi_format/rdi_format_parse.h index 4d3e40b4..f8b7e096 100644 --- a/src/lib_rdi_format/rdi_format_parse.h +++ b/src/lib_rdi_format/rdi_format_parse.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////////////////////////////////////// @@ -146,8 +146,8 @@ RDI_PROC RDI_ParseStatus rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out); 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)) +#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); diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index afc1ef9f..4af2d48c 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -294,7 +294,7 @@ rdim_sort_key_array(RDIM_Arena *arena, RDIM_SortKey *keys, RDI_U64 count) // generate an ordered range node RDIM_OrderedRange *new_range = rdim_push_array(rdim_temp_arena(scratch), RDIM_OrderedRange, 1); - SLLQueuePush(ranges_first, ranges_last, new_range); + RDIM_SLLQueuePush(ranges_first, ranges_last, new_range); range_count += 1; new_range->first = first; new_range->opl = opl; @@ -330,7 +330,7 @@ rdim_sort_key_array(RDIM_Arena *arena, RDIM_SortKey *keys, RDI_U64 count) // get first range RDIM_OrderedRange *range1 = src_ranges; - SLLStackPop(src_ranges); + RDIM_SLLStackPop(src_ranges); // if this range is the whole array, we are done if(range1->first == 0 && range1->opl == count) @@ -344,15 +344,16 @@ rdim_sort_key_array(RDIM_Arena *arena, RDIM_SortKey *keys, RDI_U64 count) { RDI_U64 first = range1->first; rdim_memcpy(dst + first, src + first, sizeof(*src)*(range1->opl - first)); - SLLQueuePush(dst_ranges, dst_ranges_last, range1); + RDIM_SLLQueuePush(dst_ranges, dst_ranges_last, range1); break; } // get second range RDIM_OrderedRange *range2 = src_ranges; - SLLStackPop(src_ranges); - + RDIM_SLLStackPop(src_ranges); +#if 0 rdim_assert(range1->opl == range2->first); +#endif // merge these ranges RDI_U64 jd = range1->first; @@ -419,7 +420,7 @@ rdim_sort_key_array(RDIM_Arena *arena, RDIM_SortKey *keys, RDI_U64 count) } #endif - scratch_end(scratch); + rdim_scratch_end(scratch); return result; } @@ -438,6 +439,27 @@ rdim_rng1u64_list_push(RDIM_Arena *arena, RDIM_Rng1U64List *list, RDIM_Rng1U64 r } } +RDI_PROC void +rdim_rng1u64_chunk_list_push(RDIM_Arena *arena, RDIM_Rng1U64ChunkList *list, RDI_U64 chunk_cap, RDIM_Rng1U64 r) +{ + RDIM_Rng1U64ChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_Rng1U64ChunkNode, 1); + RDIM_SLLQueuePush(list->first, list->last, n); + n->cap = chunk_cap; + n->v = rdim_push_array_no_zero(arena, RDIM_Rng1U64, n->cap); + list->chunk_count += 1; + } + n->v[n->count] = r; + n->count += 1; + list->total_count += 1; + if(list->total_count == 1 || r.min < list->min) + { + list->min = r.min; + } +} + //////////////////////////////// //~ Data Model @@ -645,6 +667,8 @@ rdim_src_file_chunk_list_concat_in_place(RDIM_SrcFileChunkList *dst, RDIM_SrcFil dst->last = to_push->last; dst->chunk_count += to_push->chunk_count; dst->total_count += to_push->total_count; + dst->source_line_map_count += to_push->source_line_map_count; + dst->total_line_count += to_push->total_line_count; } else if(dst->first == 0) { @@ -713,7 +737,9 @@ rdim_line_table_chunk_list_concat_in_place(RDIM_LineTableChunkList *dst, RDIM_Li dst->last = to_push->last; dst->chunk_count += to_push->chunk_count; dst->total_count += to_push->total_count; + dst->total_seq_count += to_push->total_seq_count; dst->total_line_count += to_push->total_line_count; + dst->total_col_count += to_push->total_col_count; } else if(dst->first == 0) { @@ -994,6 +1020,7 @@ rdim_symbol_chunk_list_concat_in_place(RDIM_SymbolChunkList *dst, RDIM_SymbolChu dst->last = to_push->last; dst->chunk_count += to_push->chunk_count; dst->total_count += to_push->total_count; + dst->total_value_data_size += to_push->total_value_data_size; } else if(dst->first == 0) { @@ -1002,6 +1029,13 @@ rdim_symbol_chunk_list_concat_in_place(RDIM_SymbolChunkList *dst, RDIM_SymbolChu rdim_memzero_struct(to_push); } +internal void +rdim_symbol_push_value_data(RDIM_Arena *arena, RDIM_SymbolChunkList *list, RDIM_Symbol *symbol, RDIM_String8 data) +{ + symbol->value_data = rdim_str8_copy(arena, data); + list->total_value_data_size += data.size; +} + //////////////////////////////// //~ rjf: [Building] Inline Site Info Building @@ -1279,7 +1313,7 @@ rdim_location_set_push_case(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM scopes->location_count +=1; } -//- 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) @@ -2341,6 +2375,19 @@ rdim_bake_name_map_from_kind_params(RDIM_Arena *arena, RDI_NameMapKind kind, RDI } } }break; + case RDI_NameMapKind_Constants: + { + map->slots_count = params->constants.total_count*2; + map->slots = rdim_push_array(arena, RDIM_BakeNameMapNode *, map->slots_count); + for(RDIM_SymbolChunkNode *n = params->constants.first; n != 0; n = n->next) + { + for(RDI_U64 idx = 0; idx < n->count; idx += 1) + { + RDI_U32 symbol_idx = (RDI_U32)rdim_idx_from_symbol(&n->v[idx]); // TODO(rjf): @u64_to_u32 + rdim_bake_name_map_push(arena, map, n->v[idx].name, symbol_idx); + } + } + }break; case RDI_NameMapKind_Procedures: { map->slots_count = params->procedures.total_count*2; @@ -2741,7 +2788,7 @@ rdim_bake_unit_vmap(RDIM_Arena *arena, RDIM_UnitChunkList *units) for(RDI_U64 idx = 0; idx < n->count; idx += 1) { RDIM_Unit *unit = &n->v[idx]; - voff_range_count += unit->voff_ranges.count; + voff_range_count += unit->voff_ranges.total_count; } } @@ -2762,24 +2809,27 @@ rdim_bake_unit_vmap(RDIM_Arena *arena, RDIM_UnitChunkList *units) for(RDI_U64 idx = 0; idx < unit_chunk_n->count; idx += 1) { RDIM_Unit *unit = &unit_chunk_n->v[idx]; - for(RDIM_Rng1U64Node *n = unit->voff_ranges.first; n != 0; n = n->next) + for(RDIM_Rng1U64ChunkNode *n = unit->voff_ranges.first; n != 0; n = n->next) { - RDIM_Rng1U64 range = n->v; - if(range.min < range.max) + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) { - key_ptr->key = range.min; - key_ptr->val = marker_ptr; - marker_ptr->idx = unit_idx; - marker_ptr->begin_range = 1; - key_ptr += 1; - marker_ptr += 1; - - key_ptr->key = range.max; - key_ptr->val = marker_ptr; - marker_ptr->idx = unit_idx; - marker_ptr->begin_range = 0; - key_ptr += 1; - marker_ptr += 1; + RDIM_Rng1U64 range = n->v[chunk_idx]; + if(range.min < range.max) + { + key_ptr->key = range.min; + key_ptr->val = marker_ptr; + marker_ptr->idx = unit_idx; + marker_ptr->begin_range = 1; + key_ptr += 1; + marker_ptr += 1; + + key_ptr->key = range.max; + key_ptr->val = marker_ptr; + marker_ptr->idx = unit_idx; + marker_ptr->begin_range = 0; + key_ptr += 1; + marker_ptr += 1; + } } } unit_idx += 1; @@ -3497,6 +3547,40 @@ rdim_bake_thread_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, return result; } +RDI_PROC RDIM_ConstantsBakeResult +rdim_bake_constants(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src) +{ + RDI_Constant *constants = push_array(arena, RDI_Constant, src->total_count+1); + RDI_U32 *constant_values = push_array(arena, RDI_U32, src->total_count+2); + RDI_U8 *constant_value_data = push_array(arena, RDI_U8, src->total_value_data_size+1); + RDI_U32 dst_idx = 1; + RDI_U64 dst_constant_value_data_off = 1; + for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + { + RDIM_Symbol *src = &n->v[chunk_idx]; + RDI_Constant *dst = &constants[dst_idx]; + RDI_U32 *dst_value_idx = &constant_values[dst_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 + dst->constant_value_idx = dst_idx; + dst_value_idx[0] = dst_constant_value_data_off; + rdim_memcpy(constant_value_data + dst_constant_value_data_off, src->value_data.str, src->value_data.size); + dst_constant_value_data_off += src->value_data.size; + } + } + constant_values[dst_idx] = dst_constant_value_data_off; + RDIM_ConstantsBakeResult result = {0}; + result.constants = constants; + result.constants_count = src->total_count+1; + result.constant_values = constant_values; + result.constant_values_count = src->total_count+1; + result.constant_value_data = constant_value_data; + result.constant_value_data_size = dst_constant_value_data_off; + return result; +} + RDI_PROC U64 rdim_bake_location(RDIM_Arena *arena, RDIM_String8List *location_data_blobs, RDIM_Location *src_location) { @@ -3970,6 +4054,7 @@ rdim_serialized_section_bundle_from_bake_results(RDIM_BakeResults *results) bundle.sections[RDI_SectionKind_GlobalVariables] = rdim_serialized_section_make_unpacked_array(results->global_variables.global_variables, results->global_variables.global_variables_count); bundle.sections[RDI_SectionKind_GlobalVMap] = rdim_serialized_section_make_unpacked_array(results->global_vmap.vmap.vmap, results->global_vmap.vmap.count+1); bundle.sections[RDI_SectionKind_ThreadVariables] = rdim_serialized_section_make_unpacked_array(results->thread_variables.thread_variables, results->thread_variables.thread_variables_count); + bundle.sections[RDI_SectionKind_Constants] = rdim_serialized_section_make_unpacked_array(results->constants.constants, results->constants.constants_count); bundle.sections[RDI_SectionKind_Procedures] = rdim_serialized_section_make_unpacked_array(results->procedures.procedures, results->procedures.procedures_count); bundle.sections[RDI_SectionKind_Scopes] = rdim_serialized_section_make_unpacked_array(results->scopes.scopes, results->scopes.scopes_count); bundle.sections[RDI_SectionKind_ScopeVOffData] = rdim_serialized_section_make_unpacked_array(results->scopes.scope_voffs, results->scopes.scope_voffs_count); @@ -3978,6 +4063,8 @@ rdim_serialized_section_bundle_from_bake_results(RDIM_BakeResults *results) bundle.sections[RDI_SectionKind_Locals] = rdim_serialized_section_make_unpacked_array(results->scopes.locals, results->scopes.locals_count); bundle.sections[RDI_SectionKind_LocationBlocks] = rdim_serialized_section_make_unpacked_array(results->location_blocks.str, results->location_blocks.size); bundle.sections[RDI_SectionKind_LocationData] = rdim_serialized_section_make_unpacked_array(results->location_data.str, results->location_data.size); + bundle.sections[RDI_SectionKind_ConstantValueData] = rdim_serialized_section_make_unpacked_array(results->constants.constant_value_data, results->constants.constant_value_data_size); + bundle.sections[RDI_SectionKind_ConstantValueTable] = rdim_serialized_section_make_unpacked_array(results->constants.constant_values, results->constants.constant_values_count); bundle.sections[RDI_SectionKind_NameMaps] = rdim_serialized_section_make_unpacked_array(results->top_level_name_maps.name_maps, results->top_level_name_maps.name_maps_count); bundle.sections[RDI_SectionKind_NameMapBuckets] = rdim_serialized_section_make_unpacked_array(results->name_maps.buckets, results->name_maps.buckets_count); bundle.sections[RDI_SectionKind_NameMapNodes] = rdim_serialized_section_make_unpacked_array(results->name_maps.nodes, results->name_maps.nodes_count); diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index 74024ff2..a798af08 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////////////////////////////////////// @@ -309,6 +309,46 @@ RDIM_CheckNil(nil,p) ? \ #endif #define rdim_noop ((void)0) +//////////////////////////////// +//~ rjf: RDI Subsets + +#define RDIM_Subset_XList \ +X(BinarySections, binary_sections)\ +X(Units, units)\ +X(Procedures, procedures)\ +X(GlobalVariables, global_variables)\ +X(ThreadVariables, thread_variables)\ +X(Scopes, scopes)\ +X(Locals, locals)\ +X(Types, types)\ +X(UDTs, udts)\ +X(LineInfo, line_info)\ +X(InlineLineInfo, inline_line_info)\ +X(GlobalVariableNameMap, global_variable_name_map)\ +X(ThreadVariableNameMap, thread_variable_name_map)\ +X(ProcedureNameMap, procedure_name_map)\ +X(ConstantNameMap, constant_name_map)\ +X(TypeNameMap, type_name_map)\ +X(LinkNameProcedureNameMap, link_name_procedure_name_map)\ +X(NormalSourcePathNameMap, normal_source_path_name_map)\ + +typedef enum RDIM_Subset +{ +#define X(name, name_lower) RDIM_Subset_##name, + RDIM_Subset_XList +#undef X +} +RDIM_Subset; + +typedef U32 RDIM_SubsetFlags; +enum +{ +#define X(name, name_lower) RDIM_SubsetFlag_##name = (1< pointer map typedef struct RDIM_U64ToPtrNode RDIM_U64ToPtrNode; @@ -570,7 +629,7 @@ struct RDIM_Unit RDIM_String8 build_path; RDI_Language language; RDIM_LineTable *line_table; - RDIM_Rng1U64List voff_ranges; + RDIM_Rng1U64ChunkList voff_ranges; }; typedef struct RDIM_UnitChunkNode RDIM_UnitChunkNode; @@ -763,16 +822,6 @@ struct RDIM_LocationSet //////////////////////////////// //~ rjf: Symbol Info Types -typedef enum RDIM_SymbolKind -{ - RDIM_SymbolKind_NULL, - RDIM_SymbolKind_GlobalVariable, - RDIM_SymbolKind_ThreadVariable, - RDIM_SymbolKind_Procedure, - RDIM_SymbolKind_COUNT -} -RDIM_SymbolKind; - typedef struct RDIM_Symbol RDIM_Symbol; struct RDIM_Symbol { @@ -786,6 +835,7 @@ struct RDIM_Symbol RDIM_Type *container_type; struct RDIM_Scope *root_scope; RDIM_LocationSet frame_base; + RDIM_String8 value_data; }; typedef struct RDIM_SymbolChunkNode RDIM_SymbolChunkNode; @@ -805,6 +855,7 @@ struct RDIM_SymbolChunkList RDIM_SymbolChunkNode *last; RDI_U64 chunk_count; RDI_U64 total_count; + RDI_U64 total_value_data_size; }; //////////////////////////////// @@ -907,6 +958,7 @@ struct RDIM_BakeParams RDIM_LineTableChunkList line_tables; RDIM_SymbolChunkList global_variables; RDIM_SymbolChunkList thread_variables; + RDIM_SymbolChunkList constants; RDIM_SymbolChunkList procedures; RDIM_ScopeChunkList scopes; RDIM_InlineSiteChunkList inline_sites; @@ -1192,6 +1244,17 @@ struct RDIM_ThreadVariableBakeResult RDI_U64 thread_variables_count; }; +typedef struct RDIM_ConstantsBakeResult RDIM_ConstantsBakeResult; +struct RDIM_ConstantsBakeResult +{ + RDI_Constant *constants; + RDI_U64 constants_count; + RDI_U32 *constant_values; + RDI_U64 constant_values_count; + RDI_U8 *constant_value_data; + RDI_U64 constant_value_data_size; +}; + typedef struct RDIM_ProcedureBakeResult RDIM_ProcedureBakeResult; struct RDIM_ProcedureBakeResult { @@ -1276,6 +1339,7 @@ struct RDIM_BakeResults RDIM_GlobalVariableBakeResult global_variables; RDIM_GlobalVMapBakeResult global_vmap; RDIM_ThreadVariableBakeResult thread_variables; + RDIM_ConstantsBakeResult constants; RDIM_ProcedureBakeResult procedures; RDIM_ScopeBakeResult scopes; RDIM_InlineSiteBakeResult inline_sites; @@ -1357,8 +1421,9 @@ RDI_PROC RDIM_String8 rdim_str8_list_join(RDIM_Arena *arena, RDIM_String8List *l //- rjf: sortable range sorting RDI_PROC RDIM_SortKey *rdim_sort_key_array(RDIM_Arena *arena, RDIM_SortKey *keys, RDI_U64 count); -//- rjf: rng1u64 list +//- rjf: rng1u64 lists RDI_PROC void rdim_rng1u64_list_push(RDIM_Arena *arena, RDIM_Rng1U64List *list, RDIM_Rng1U64 r); +RDI_PROC void rdim_rng1u64_chunk_list_push(RDIM_Arena *arena, RDIM_Rng1U64ChunkList *list, RDI_U64 chunk_cap, RDIM_Rng1U64 r); //////////////////////////////// //~ Data Model @@ -1419,6 +1484,7 @@ RDI_PROC RDIM_UDTEnumVal *rdim_udt_push_enum_val(RDIM_Arena *arena, RDIM_UDTChun RDI_PROC RDIM_Symbol *rdim_symbol_chunk_list_push(RDIM_Arena *arena, RDIM_SymbolChunkList *list, RDI_U64 cap); RDI_PROC RDI_U64 rdim_idx_from_symbol(RDIM_Symbol *symbol); RDI_PROC void rdim_symbol_chunk_list_concat_in_place(RDIM_SymbolChunkList *dst, RDIM_SymbolChunkList *to_push); +internal void rdim_symbol_push_value_data(RDIM_Arena *arena, RDIM_SymbolChunkList *list, RDIM_Symbol *symbol, RDIM_String8 data); //////////////////////////////// //~ rjf: [Building] Inline Site Info Building @@ -1453,9 +1519,8 @@ 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); -//- location block chunk list - -RDI_PROC RDI_LocationBlock * rdim_location_block_chunk_list_push_array(RDIM_Arena *arena, RDIM_String8List *list, RDI_U32 count); +//- 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); //////////////////////////////// @@ -1562,6 +1627,7 @@ RDI_PROC RDIM_UDTBakeResult rdim_bake_udts(RDIM_Arena *arena, RDIM_B RDI_PROC RDIM_GlobalVariableBakeResult rdim_bake_global_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src); RDI_PROC RDIM_GlobalVMapBakeResult rdim_bake_global_vmap(RDIM_Arena *arena, RDIM_SymbolChunkList *src); RDI_PROC RDIM_ThreadVariableBakeResult rdim_bake_thread_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src); +RDI_PROC RDIM_ConstantsBakeResult rdim_bake_constants(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src); RDI_PROC RDIM_ProcedureBakeResult rdim_bake_procedures(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_String8List *location_blocks, RDIM_String8List *location_data_blobs, RDIM_SymbolChunkList *src); RDI_PROC RDIM_ScopeBakeResult rdim_bake_scopes(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_String8List *location_blocks, RDIM_String8List *location_data_blobs, RDIM_ScopeChunkList *src); RDI_PROC RDIM_ScopeVMapBakeResult rdim_bake_scope_vmap(RDIM_Arena *arena, RDIM_ScopeChunkList *src); diff --git a/src/linker/hash_table.c b/src/linker/hash_table.c index 1f1ed5ec..c38e224f 100644 --- a/src/linker/hash_table.c +++ b/src/linker/hash_table.c @@ -26,6 +26,10 @@ bucket_list_pop(BucketList *list) //////////////////////////////// +#define XXH_STATIC_LINKING_ONLY +#include "third_party/xxHash/xxhash.c" +#include "third_party/xxHash/xxhash.h" + internal U64 hash_table_hasher(String8 string) { @@ -47,7 +51,7 @@ hash_table_purge(HashTable *ht) { // reset key count ht->count = 0; - + // concat buckets for (U64 ibucket = 0; ibucket < ht->cap; ++ibucket) { bucket_list_concat_in_place(&ht->free_buckets, &ht->buckets[ibucket]); @@ -323,6 +327,8 @@ key_value_pairs_from_hash_table(Arena *arena, HashTable *ht) return pairs; } +#include "third_party/radsort/radsort.h" + internal void sort_key_value_pairs_as_u32(KeyValuePair *pairs, U64 count) { @@ -339,20 +345,20 @@ internal U64Array remove_duplicates_u64_array(Arena *arena, U64Array arr) { Temp scratch = scratch_begin(&arena, 1); - + HashTable *ht = hash_table_init(scratch.arena, ((U64)(F64)arr.count * 0.5)); - + for (U64 i = 0; i < arr.count; ++i) { KeyValuePair *is_present = hash_table_search_u64(ht, arr.v[i]); if (!is_present) { hash_table_push_u64_raw(scratch.arena, ht, arr.v[i], 0); } } - + U64Array result = {0}; result.count = ht->count; result.v = keys_from_hash_table_u64(arena, ht); - + scratch_end(scratch); return result; } @@ -361,10 +367,10 @@ internal String8List remove_duplicates_str8_list(Arena *arena, String8List list) { Temp scratch = scratch_begin(&arena, 1); - + String8List result = {0}; HashTable *ht = hash_table_init(scratch.arena, list.node_count); - + for (String8Node *node = list.first; node != 0; node = node->next) { KeyValuePair *is_present = hash_table_search_string(ht, node->string); if (!is_present) { @@ -372,7 +378,7 @@ remove_duplicates_str8_list(Arena *arena, String8List list) str8_list_push(arena, &result, node->string); } } - + scratch_end(scratch); return result; } diff --git a/src/linker/rdi/rdi.c b/src/linker/rdi/rdi.c index dafd09bf..8b137891 100644 --- a/src/linker/rdi/rdi.c +++ b/src/linker/rdi/rdi.c @@ -1,15 +1 @@ -internal String8 -rdi_string_from_name_map_kind(RDI_NameMapKind kind) -{ - switch (kind) { - case RDI_NameMapKind_NULL : return str8_lit("NULL"); - case RDI_NameMapKind_GlobalVariables : return str8_lit("GlobalVariables"); - case RDI_NameMapKind_ThreadVariables : return str8_lit("ThreadVariables"); - case RDI_NameMapKind_Procedures : return str8_lit("Procedures"); - case RDI_NameMapKind_Types : return str8_lit("Types"); - case RDI_NameMapKind_LinkNameProcedures: return str8_lit("LinkNameProcedures"); - case RDI_NameMapKind_NormalSourcePaths : return str8_lit("NormalSourcePaths"); - } - return str8_lit(""); -} diff --git a/src/linker/rdi/rdi.h b/src/linker/rdi/rdi.h index b5d7e894..531a62b0 100644 --- a/src/linker/rdi/rdi.h +++ b/src/linker/rdi/rdi.h @@ -1,5 +1,4 @@ #pragma once -internal String8 rdi_string_from_name_map_kind(RDI_NameMapKind kind); diff --git a/src/mdesk/mdesk.c b/src/mdesk/mdesk.c index 1b6e2f51..efe2a52f 100644 --- a/src/mdesk/mdesk.c +++ b/src/mdesk/mdesk.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/mdesk/mdesk.h b/src/mdesk/mdesk.h index 455cb268..e7a55473 100644 --- a/src/mdesk/mdesk.h +++ b/src/mdesk/mdesk.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef MDESK_H diff --git a/src/metagen/metagen.c b/src/metagen/metagen.c index 33c4daa7..2bce9e88 100644 --- a/src/metagen/metagen.c +++ b/src/metagen/metagen.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/metagen/metagen.h b/src/metagen/metagen.h index 6280cbed..851fc027 100644 --- a/src/metagen/metagen.h +++ b/src/metagen/metagen.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef METAGEN_H diff --git a/src/metagen/metagen_main.c b/src/metagen/metagen_main.c index 24c645b1..1c19ac5d 100644 --- a/src/metagen/metagen_main.c +++ b/src/metagen/metagen_main.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -536,7 +536,7 @@ entry_point(CmdLine *cmdline) } { FILE *h = fopen((char *)h_path.str, "w"); - fprintf(h, "// Copyright (c) 2024 Epic Games Tools\n"); + fprintf(h, "// Copyright (c) Epic Games Tools\n"); fprintf(h, "// Licensed under the MIT license (https://opensource.org/license/mit/)\n\n"); if(layer->h_header.first == 0) { @@ -592,7 +592,7 @@ entry_point(CmdLine *cmdline) } { FILE *c = fopen((char *)c_path.str, "w"); - fprintf(c, "// Copyright (c) 2024 Epic Games Tools\n"); + fprintf(c, "// Copyright (c) Epic Games Tools\n"); fprintf(c, "// Licensed under the MIT license (https://opensource.org/license/mit/)\n\n"); if(layer->c_header.first == 0) { diff --git a/src/msf/msf.c b/src/msf/msf.c index 116918c8..ad0d59ca 100644 --- a/src/msf/msf.c +++ b/src/msf/msf.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal B32 diff --git a/src/msf/msf.h b/src/msf/msf.h index 34bc9960..46503306 100644 --- a/src/msf/msf.h +++ b/src/msf/msf.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef MSF_H diff --git a/src/msf/msf_parse.c b/src/msf/msf_parse.c index 941f5d40..aa64411f 100644 --- a/src/msf/msf_parse.c +++ b/src/msf/msf_parse.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -8,7 +8,7 @@ internal MSF_RawStreamTable * msf_raw_stream_table_from_data(Arena *arena, String8 msf_data) { Temp scratch = scratch_begin(&arena, 1); - + MSF_RawStreamTable *result = 0; //- determine msf type @@ -25,7 +25,7 @@ msf_raw_stream_table_from_data(Arena *arena, String8 msf_data) U32 whole_file_page_count_raw = 0; U32 directory_size_raw = 0; U32 directory_super_map_raw = 0; - + if (index_size == 2) { MSF_Header20 *header = (MSF_Header20 *) msf_data.str; page_size_raw = header->page_size; @@ -231,7 +231,7 @@ internal String8 msf_data_from_stream_number(Arena *arena, String8 msf_data, MSF_RawStreamTable *st, MSF_StreamNumber sn) { MSF_RawStream stream = st->streams[sn]; - + U8 *stream_buf = push_array_no_zero(arena, U8, stream.size); U8 *stream_out_ptr = stream_buf; for (U32 i = 0; i < stream.page_count; ++i) { @@ -241,12 +241,12 @@ msf_data_from_stream_number(Arena *arena, String8 msf_data, MSF_RawStreamTable * } else { page_idx = stream.u.page_indices_u16[i]; } - + U64 stream_page_off = (U64)page_idx * st->page_size; if (stream_page_off + st->page_size > msf_data.size) { break; } - + U8 *stream_page_base = msf_data.str + stream_page_off; // clamp copy size by end of stream @@ -258,12 +258,12 @@ msf_data_from_stream_number(Arena *arena, String8 msf_data, MSF_RawStreamTable * MemoryCopy(stream_out_ptr, stream_page_base, copy_size); stream_out_ptr += copy_size; } - + U64 copy_size = (U64)(stream_out_ptr - stream_buf); - + U64 unused_buf_size = stream.size - copy_size; arena_pop(arena, unused_buf_size); - + String8 result = str8(stream_buf, copy_size); return result; } @@ -272,16 +272,16 @@ internal MSF_Parsed * msf_parsed_from_data(Arena *arena, String8 msf_data) { Temp scratch = scratch_begin(&arena, 1); - + MSF_Parsed *result = 0; - + MSF_RawStreamTable *st = msf_raw_stream_table_from_data(scratch.arena, msf_data); if (st) { String8 *streams = push_array_no_zero(arena, String8, st->stream_count); for (MSF_StreamNumber sn = 0; sn < st->stream_count; ++sn) { streams[sn] = msf_data_from_stream_number(arena, msf_data, st, sn); } - + result = push_array_no_zero(arena, MSF_Parsed, 1); result->streams = streams; result->stream_count = st->stream_count; diff --git a/src/msf/msf_parse.h b/src/msf/msf_parse.h index c055df79..df4afb85 100644 --- a/src/msf/msf_parse.h +++ b/src/msf/msf_parse.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef MSF_PARSE_H diff --git a/src/msvc_crt/msvc_crt.c b/src/msvc_crt/msvc_crt.c index fda085a4..6ea33e51 100644 --- a/src/msvc_crt/msvc_crt.c +++ b/src/msvc_crt/msvc_crt.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U64 @@ -10,37 +10,37 @@ mscrt_parse_func_info(Arena *arena, MSCRT_FuncInfo *func_info) { U64 cursor = off; - + U32 handler_data_voff = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &handler_data_voff); - + // TODO: what is this? padding? U32 unknown = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &unknown); - + // read function info U64 handler_data_foff = coff_foff_from_voff(sections, section_count, handler_data_voff); - + MSCRT_FuncInfo32 func_info32 = {0}; str8_deserial_read_struct(raw_data, handler_data_foff, &func_info32); - + // unwind map MSCRT_UnwindMap32 *unwind_map = push_array(arena, MSCRT_UnwindMap32, func_info32.max_state); U64 unwind_map_foff = coff_foff_from_voff(sections, section_count, func_info32.unwind_map_voff); cursor += str8_deserial_read_array(raw_data, unwind_map_foff, &unwind_map[0], func_info32.max_state); - + // read ip states MSCRT_IPState32 *ip_map = push_array(arena, MSCRT_IPState32, func_info32.ip_map_count); U64 ip_map_foff = coff_foff_from_voff(sections, section_count, func_info32.ip_map_voff); str8_deserial_read_array(raw_data, ip_map_foff, &ip_map[0], func_info32.ip_map_count); - + // read try map MSCRT_TryMapBlock *try_block_map = push_array(arena, MSCRT_TryMapBlock, func_info32.try_block_map_count); U64 try_map_foff = coff_foff_from_voff(sections, section_count, func_info32.try_block_map_voff); for (U32 imap = 0; imap < func_info32.try_block_map_count; ++imap) { MSCRT_TryMapBlock32 map32 = {0}; str8_deserial_read_struct(raw_data, try_map_foff + imap*sizeof(map32), &map32); - + // convert try map to in-memory version MSCRT_TryMapBlock *map = &try_block_map[imap]; map->try_low = map32.try_low; @@ -48,26 +48,26 @@ mscrt_parse_func_info(Arena *arena, map->catch_high = map32.catch_high; map->catch_handlers_count = map32.catch_handlers_count; map->catch_handlers = push_array(arena, MSCRT_EhHandlerType32, map32.catch_handlers_count); - + // read handlers U64 catch_handlers_foff = coff_foff_from_voff(sections, section_count, map32.catch_handlers_voff); str8_deserial_read_array(raw_data, catch_handlers_foff, &map->catch_handlers[0], map->catch_handlers_count); } - + // read exception spec list MSCRT_ExceptionSpecTypeList es_type_list = {0}; if (func_info32.es_type_list_voff) { MSCRT_ExceptionSpecTypeList32 es_list32 = {0}; U64 es_list_foff = coff_foff_from_voff(sections, section_count, func_info32.es_type_list_voff); str8_deserial_read_struct(raw_data, es_list_foff, &es_list32); - + es_type_list.count = es_list32.count; es_type_list.handlers = push_array(arena, MSCRT_EhHandlerType32, es_list32.count); - + U64 handlers_foff = coff_foff_from_voff(sections, section_count, es_list32.handlers_voff); str8_deserial_read_array(raw_data, handlers_foff, &es_type_list.handlers[0], es_type_list.count); } - + // pack result func_info->magic = func_info32.magic; func_info->max_state = func_info32.max_state; @@ -79,7 +79,7 @@ mscrt_parse_func_info(Arena *arena, func_info->frame_offset_unwind_helper = func_info32.frame_offset_unwind_helper; func_info->es_type_list = es_type_list; func_info->eh_flags = func_info32.eh_flags; - + U64 parse_size = (cursor - off); return parse_size; } @@ -90,10 +90,10 @@ internal U64 mscrt_v4_parse_u32(String8 raw_data, U64 offset, U32 *uint_out) { U64 cursor = offset; - + U8 one = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &one); - + if ((one & 0xF) == 15) { U8 two = 0, three = 0, four = 0, five = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &two); @@ -119,7 +119,7 @@ mscrt_v4_parse_u32(String8 raw_data, U64 offset, U32 *uint_out) } else { *uint_out = one >> 1; } - + U64 read_size = cursor - offset; return read_size; } @@ -134,7 +134,7 @@ internal U64 mscrt_parse_handler_type_v4(String8 raw_data, U64 offset, U64 func_voff, MSCRT_EhHandlerTypeV4 *handler) { U64 cursor = offset; - + cursor += str8_deserial_read_struct(raw_data, cursor, &handler->flags); if (handler->flags & MSCRT_EhHandlerV4Flag_Adjectives) { cursor += mscrt_v4_parse_u32(raw_data, cursor, &handler->adjectives); @@ -146,47 +146,47 @@ mscrt_parse_handler_type_v4(String8 raw_data, U64 offset, U64 func_voff, MSCRT_E cursor += mscrt_v4_parse_u32(raw_data, cursor, &handler->catch_obj_voff); } cursor += mscrt_v4_parse_s32(raw_data, cursor, &handler->catch_code_voff); - + U32 cont_type = (handler->flags & MSCRT_EhHandlerV4Flag_ContVOffMask) >> MSCRT_EhHandlerV4Flag_ContVOffShift; if (handler->flags & MSCRT_EhHandlerV4Flag_ContIsVOff) { switch (cont_type) { - case MSCRT_ContV4Type_NoMetadata: break; - case MSCRT_ContV4Type_OneFuncRelAddr: { - S32 v = 0; - cursor += mscrt_v4_parse_s32(raw_data, cursor, &v); - handler->catch_funclet_cont_addr[0] = (U64)v; - handler->catch_funclet_cont_addr_count = 1; - } break; - case MSCRT_ContV4Type_TwoFuncRelAddr: { - S32 v1 = 0, v2 = 0; - cursor += mscrt_v4_parse_s32(raw_data, cursor, &v1); - cursor += mscrt_v4_parse_s32(raw_data, cursor, &v2); - handler->catch_funclet_cont_addr[0] = (U64)v1; - handler->catch_funclet_cont_addr[1] = (U64)v2; - handler->catch_funclet_cont_addr_count = 2; - } break; + case MSCRT_ContV4Type_NoMetadata: break; + case MSCRT_ContV4Type_OneFuncRelAddr: { + S32 v = 0; + cursor += mscrt_v4_parse_s32(raw_data, cursor, &v); + handler->catch_funclet_cont_addr[0] = (U64)v; + handler->catch_funclet_cont_addr_count = 1; + } break; + case MSCRT_ContV4Type_TwoFuncRelAddr: { + S32 v1 = 0, v2 = 0; + cursor += mscrt_v4_parse_s32(raw_data, cursor, &v1); + cursor += mscrt_v4_parse_s32(raw_data, cursor, &v2); + handler->catch_funclet_cont_addr[0] = (U64)v1; + handler->catch_funclet_cont_addr[1] = (U64)v2; + handler->catch_funclet_cont_addr_count = 2; + } break; } } else { switch (cont_type) { - case MSCRT_ContV4Type_NoMetadata: { - } break; - case MSCRT_ContV4Type_OneFuncRelAddr: { - U32 v = 0; - cursor += mscrt_v4_parse_u32(raw_data, cursor, &v); - handler->catch_funclet_cont_addr[0] = func_voff + (U64)v; - handler->catch_funclet_cont_addr_count = 1; - } break; - case MSCRT_ContV4Type_TwoFuncRelAddr: { - U32 v1 = 0, v2 = 0; - cursor += mscrt_v4_parse_u32(raw_data, cursor, &v1); - cursor += mscrt_v4_parse_u32(raw_data, cursor, &v2); - handler->catch_funclet_cont_addr[0] = func_voff + (U64)v1; - handler->catch_funclet_cont_addr[1] = func_voff + (U64)v2; - handler->catch_funclet_cont_addr_count = 2; - } break; + case MSCRT_ContV4Type_NoMetadata: { + } break; + case MSCRT_ContV4Type_OneFuncRelAddr: { + U32 v = 0; + cursor += mscrt_v4_parse_u32(raw_data, cursor, &v); + handler->catch_funclet_cont_addr[0] = func_voff + (U64)v; + handler->catch_funclet_cont_addr_count = 1; + } break; + case MSCRT_ContV4Type_TwoFuncRelAddr: { + U32 v1 = 0, v2 = 0; + cursor += mscrt_v4_parse_u32(raw_data, cursor, &v1); + cursor += mscrt_v4_parse_u32(raw_data, cursor, &v2); + handler->catch_funclet_cont_addr[0] = func_voff + (U64)v1; + handler->catch_funclet_cont_addr[1] = func_voff + (U64)v2; + handler->catch_funclet_cont_addr_count = 2; + } break; } } - + U64 read_size = cursor - offset; return read_size; } @@ -201,7 +201,7 @@ mscrt_parse_handler_type_v4_array(Arena *arena, U64 cursor = offset; U32 count = 0; cursor += mscrt_v4_parse_u32(raw_data, cursor, &count); - + MSCRT_EhHandlerTypeV4 *handlers = 0; if (count) { handlers = push_array(arena, MSCRT_EhHandlerTypeV4, count); @@ -209,10 +209,10 @@ mscrt_parse_handler_type_v4_array(Arena *arena, cursor += mscrt_parse_handler_type_v4(raw_data, cursor, func_voff, &handlers[i]); } } - + array_out->count = count; array_out->v = handlers; - + U64 read_size = cursor - offset; return read_size; } @@ -221,30 +221,30 @@ internal U64 mscrt_parse_unwind_v4_entry(String8 raw_data, U64 offset, MSCRT_UnwindEntryV4 *entry_out) { U64 cursor = offset; - + U32 type_and_next_off = 0; cursor += mscrt_v4_parse_u32(raw_data, cursor, &type_and_next_off); - + entry_out->type = type_and_next_off & 0x3; entry_out->next_off = type_and_next_off >> 2; - + switch (entry_out->type) { - case MSCRT_UnwindMapV4Type_DtorWithObj: - case MSCRT_UnwindMapV4Type_DtorWithPtrToObj: { - cursor += mscrt_v4_parse_s32(raw_data, cursor, &entry_out->action); - cursor += mscrt_v4_parse_u32(raw_data, cursor, &entry_out->object); - } break; - case MSCRT_UnwindMapV4Type_VOFF: { - cursor += mscrt_v4_parse_s32(raw_data, cursor, &entry_out->action); - } break; - case MSCRT_UnwindMapV4Type_NoUW: { - // no action and/or object is associated with this type - } break; - default: { - Assert(!"unknown unwind entry type"); - } break; + case MSCRT_UnwindMapV4Type_DtorWithObj: + case MSCRT_UnwindMapV4Type_DtorWithPtrToObj: { + cursor += mscrt_v4_parse_s32(raw_data, cursor, &entry_out->action); + cursor += mscrt_v4_parse_u32(raw_data, cursor, &entry_out->object); + } break; + case MSCRT_UnwindMapV4Type_VOFF: { + cursor += mscrt_v4_parse_s32(raw_data, cursor, &entry_out->action); + } break; + case MSCRT_UnwindMapV4Type_NoUW: { + // no action and/or object is associated with this type + } break; + default: { + Assert(!"unknown unwind entry type"); + } break; } - + U64 read_size = cursor - offset; return read_size; } @@ -272,27 +272,27 @@ mscrt_parse_try_block_map_array_v4(Arena *arena, MSCRT_TryBlockMapV4Array *map_out) { U64 cursor = off; - + U32 try_block_map_count = 0; cursor += mscrt_v4_parse_u32(raw_data, cursor, &try_block_map_count); - + MSCRT_TryBlockMapV4 *try_block_map = push_array(arena, MSCRT_TryBlockMapV4, try_block_map_count); for (U32 itry = 0; itry < try_block_map_count; ++itry) { MSCRT_TryBlockMapV4 *try_block = &try_block_map[itry]; cursor += mscrt_v4_parse_u32(raw_data, cursor, &try_block->try_low); cursor += mscrt_v4_parse_u32(raw_data, cursor, &try_block->try_high); cursor += mscrt_v4_parse_u32(raw_data, cursor, &try_block->catch_high); - + S32 handler_array_voff = 0; cursor += mscrt_v4_parse_s32(raw_data, cursor, &handler_array_voff); - + U64 handler_array_foff = coff_foff_from_voff(sections, section_count, (U32)handler_array_voff); mscrt_parse_handler_type_v4_array(arena, raw_data, handler_array_foff, func_voff, &try_block->handlers); } - + map_out->count = try_block_map_count; map_out->v = try_block_map; - + U64 read_size = cursor - off; return read_size; } @@ -305,45 +305,45 @@ mscrt_parse_ip2state_map_v4(Arena *arena, MSCRT_IP2State32V4 *ip2state_map_out) { U64 cursor = off; - + U32 count = 0; cursor += mscrt_v4_parse_u32(raw_data, cursor, &count); - + U32 *voffs = push_array(arena, U32, count); S32 *states = push_array(arena, S32, count); - + U32 prev_voff = func_voff; for (U32 i = 0; i < count; ++i) { // virtual offsets are encoded as deltas cursor += mscrt_v4_parse_u32(raw_data, cursor, &voffs[i]); voffs[i] += prev_voff; prev_voff = voffs[i]; - + // states are encoded with +1 to avoid encoding negative integers U32 encoded_state = 0; cursor += mscrt_v4_parse_u32(raw_data, cursor, &encoded_state); states[i] = (S32)encoded_state - 1; } - + ip2state_map_out->count = count; ip2state_map_out->voffs = voffs; ip2state_map_out->states = states; - + U64 read_size = cursor - off; return read_size; } internal U64 mscrt_parse_func_info_v4(Arena *arena, - String8 raw_data, - U64 section_count, - COFF_SectionHeader *sections, - U64 off, - U64 func_voff, - MSCRT_ParsedFuncInfoV4 *func_info_out) + String8 raw_data, + U64 section_count, + COFF_SectionHeader *sections, + U64 off, + U64 func_voff, + MSCRT_ParsedFuncInfoV4 *func_info_out) { U64 cursor = off; - + MSCRT_FuncInfo32V4 func_info = {0}; cursor += str8_deserial_read_struct(raw_data, cursor, &func_info.header); if (func_info.header & MSCRT_FuncInfoV4Flag_IsBBT) { @@ -364,19 +364,19 @@ mscrt_parse_func_info_v4(Arena *arena, if (func_info.header & MSCRT_FuncInfoV4Flag_IsCatch) { cursor += mscrt_v4_parse_s32(raw_data, cursor, &func_info.wrt_frame_establisher_voff); } - + MSCRT_UnwindMapV4 unwind_map = {0}; if (func_info.header & MSCRT_FuncInfoV4Flag_UnwindMap) { U64 unwind_map_foff = coff_foff_from_voff(sections, section_count, func_info.unwind_map_voff); mscrt_parse_unwind_map_v4(arena, raw_data, unwind_map_foff, &unwind_map); } - + MSCRT_TryBlockMapV4Array try_block_map = {0}; if (func_info.header & MSCRT_FuncInfoV4Flag_TryBlockMap) { U64 try_block_map_foff = coff_foff_from_voff(sections, section_count, func_info.try_block_map_voff); mscrt_parse_try_block_map_array_v4(arena, raw_data, try_block_map_foff, section_count, sections, func_voff, &try_block_map); } - + MSCRT_IP2State32V4 ip2state_map = {0}; if (func_info.header & MSCRT_FuncInfoV4Flag_IsSeparated) { Assert(!"TODO: separated ip2state map"); @@ -384,13 +384,13 @@ mscrt_parse_func_info_v4(Arena *arena, U64 ip_to_state_map_foff = coff_foff_from_voff(sections, section_count, func_info.ip_to_state_map_voff); mscrt_parse_ip2state_map_v4(arena, raw_data, ip_to_state_map_foff, func_voff, &ip2state_map); } - + func_info_out->header = func_info.header; func_info_out->bbt_flags = func_info.bbt_flags; func_info_out->try_block_map = try_block_map; func_info_out->unwind_map = unwind_map; func_info_out->ip2state_map = ip2state_map; - + U64 read_size = cursor - off; return read_size; } @@ -405,29 +405,29 @@ mscrt_catch_blocks_from_data_x8664(Arena *arena, Rng1U64 except_frange) { Temp scratch = scratch_begin(&arena, 1); - + Rng1U64List result = {0}; - + String8 raw_pdata = str8_substr(raw_data, except_frange); U64 pdata_count = raw_pdata.size / sizeof(PE_IntelPdata); PE_IntelPdata *src_pdata = (PE_IntelPdata *)raw_pdata.str; PE_IntelPdata *opl_pdata = src_pdata + pdata_count; - + for (PE_IntelPdata *pdata = src_pdata; pdata < opl_pdata; ++pdata) { U64 uwinfo_foff = coff_foff_from_voff(sections, section_count, pdata->voff_unwind_info); PE_UnwindInfo *uwinfo = str8_deserial_get_raw_ptr(raw_data, uwinfo_foff, sizeof(*uwinfo)); - + U8 flags = PE_UNWIND_INFO_FLAGS_FROM_HDR(uwinfo->header); B32 is_chained = !!(flags & PE_UnwindInfoFlag_CHAINED); B32 has_handler_data = !is_chained && ((flags & (PE_UnwindInfoFlag_EHANDLER | PE_UnwindInfoFlag_UHANDLER)) != 0); - + if (has_handler_data) { Temp temp = temp_begin(scratch.arena); - + U32 actual_code_count = PE_UNWIND_INFO_GET_CODE_COUNT(uwinfo->codes_num); U64 handler_data_foff = uwinfo_foff + sizeof(PE_UnwindInfo) + actual_code_count * sizeof(PE_UnwindCode); U32 handler_voff = *(U32 *)str8_deserial_get_raw_ptr(raw_data, handler_data_foff, sizeof(handler_voff)); - + String8 handler_name = str8_zero(); /* TODO: { @@ -437,14 +437,14 @@ mscrt_catch_blocks_from_data_x8664(Arena *arena, handler_name = syms_group_symbol_name_from_sid(temp.arena, group, unit, sid); } */ - + B32 is_handler_v3_or_below = str8_match_lit("__CxxFrameHandler3", handler_name, 0) || - str8_match_lit("__GSHandlerCheck_EH", handler_name, 0); + str8_match_lit("__GSHandlerCheck_EH", handler_name, 0); if (is_handler_v3_or_below) { U64 func_info_foff = handler_data_foff + sizeof(handler_voff); MSCRT_FuncInfo func_info = {0}; mscrt_parse_func_info(temp.arena, raw_data, section_count, sections, func_info_foff, &func_info); - + for (U32 itry = 0; itry < func_info.try_block_map_count; ++itry) { MSCRT_TryMapBlock *try_block = &func_info.try_block_map[itry]; for (U32 icatch = 0; icatch < try_block->catch_handlers_count; ++icatch) { @@ -456,15 +456,15 @@ mscrt_catch_blocks_from_data_x8664(Arena *arena, } goto next; } - + B32 is_handler_v4 = str8_match_lit("__CxxFrameHandler4", handler_name, 0) || - str8_match_lit("__GSHandlerCheck_EH4", handler_name, 0); + str8_match_lit("__GSHandlerCheck_EH4", handler_name, 0); if (is_handler_v4) { U32 func_info_voff = *(U32 *)str8_deserial_get_raw_ptr(raw_data, handler_data_foff + sizeof(handler_voff), sizeof(func_info_voff)); U64 func_info_foff = coff_foff_from_voff(sections, section_count, func_info_voff); MSCRT_ParsedFuncInfoV4 func_info = {0}; mscrt_parse_func_info_v4(temp.arena, raw_data, section_count, sections, func_info_foff, pdata->voff_first, &func_info); - + for (U32 itry = 0; itry < func_info.try_block_map.count; ++itry) { MSCRT_TryBlockMapV4 *try_block = &func_info.try_block_map.v[itry]; for (U32 icatch = 0; icatch < try_block->handlers.count; ++icatch) { @@ -476,12 +476,12 @@ mscrt_catch_blocks_from_data_x8664(Arena *arena, } goto next; } - - next:; + + next:; temp_end(temp); } } - + scratch_end(scratch); return result; } diff --git a/src/msvc_crt/msvc_crt.h b/src/msvc_crt/msvc_crt.h index 21106ee0..93599237 100644 --- a/src/msvc_crt/msvc_crt.h +++ b/src/msvc_crt/msvc_crt.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef MSVC_CRT @@ -56,7 +56,7 @@ enum MSCRT_Magic1 = 0x19930520, MSCRT_Magic2 = 0x19930521, MSCRT_Magic3 = 0x19930522, - + // pure magic indicates that exception cannot be caught in native or managed code. MSCRT_PureMagic1 = 0x1994000, }; @@ -224,7 +224,7 @@ enum MSCRT_EhHandlerV4Flag_DispType = (1 << 1), // set if type descriptors are present MSCRT_EhHandlerV4Flag_DispCatchObj = (1 << 2), // set if catch object object is present MSCRT_EhHandlerV4Flag_ContIsVOff = (1 << 3), // continuantion addresses are VOFF rather than function relative - + MSCRT_EhHandlerV4Flag_ContVOffMask = 0x30, MSCRT_EhHandlerV4Flag_ContVOffShift = 4, }; diff --git a/src/msvc_crt/msvc_crt_enum.c b/src/msvc_crt/msvc_crt_enum.c index e70e4ed0..40052496 100644 --- a/src/msvc_crt/msvc_crt_enum.c +++ b/src/msvc_crt/msvc_crt_enum.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal String8 diff --git a/src/msvc_crt/msvc_crt_enum.h b/src/msvc_crt/msvc_crt_enum.h index ac71508d..8bc3440c 100644 --- a/src/msvc_crt/msvc_crt_enum.h +++ b/src/msvc_crt/msvc_crt_enum.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef MSVC_CRT_ENUM_H diff --git a/src/mule/inline_body.cpp b/src/mule/inline_body.cpp index f20fb7b6..4bb6352f 100644 --- a/src/mule/inline_body.cpp +++ b/src/mule/inline_body.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) bias = (bias^x)&7; diff --git a/src/mule/mule_c.c b/src/mule/mule_c.c index 92492aba..e67e42fd 100644 --- a/src/mule/mule_c.c +++ b/src/mule/mule_c.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) /* diff --git a/src/mule/mule_c.h b/src/mule/mule_c.h index 1bf51721..3a41e4bf 100644 --- a/src/mule/mule_c.h +++ b/src/mule/mule_c.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) /* diff --git a/src/mule/mule_inline.cpp b/src/mule/mule_inline.cpp index bb5d82ae..bfac4bf0 100644 --- a/src/mule/mule_inline.cpp +++ b/src/mule/mule_inline.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) /* diff --git a/src/mule/mule_main.cpp b/src/mule/mule_main.cpp index 72136675..24b82025 100644 --- a/src/mule/mule_main.cpp +++ b/src/mule/mule_main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) /* @@ -159,6 +159,22 @@ struct Dynamic_Array }; raddbg_type_view(Dynamic_Array, slice($)); +template +struct TemplatedDynamicArray +{ + T *v; + int count; +}; +raddbg_type_view(TemplatedDynamicArray, rows($, count, array(v, count))); + +template +struct OpaqueTemplatedDynamicArray +{ + void *v; + int count; +}; +raddbg_type_view(OpaqueTemplatedDynamicArray, array(cast(type *)v, count)); + struct Struct_With_Embedded_Arrays { int x; @@ -427,6 +443,18 @@ type_coverage_eval_tests(void) 6 }; + TemplatedDynamicArray templated_dynamic = {dynamic.pairs, dynamic.count}; + TemplatedDynamicArray templated_dynamics[] = + { + {dynamic.pairs, dynamic.count}, + {dynamic.pairs, dynamic.count}, + {dynamic.pairs, dynamic.count}, + {dynamic.pairs, dynamic.count}, + {dynamic.pairs, dynamic.count}, + }; + + OpaqueTemplatedDynamicArray otd = {dynamic.pairs, dynamic.count}; + raddbg_pin(columns(sequence(6), fixed.pairs[$], memory_[$])); raddbg_pin(basics); raddbg_pin(fixed); @@ -586,6 +614,12 @@ type_coverage_eval_tests(void) int_vector.push_back(6); int_vector.push_back(7); + std::vector dynamic_array_vector; + dynamic_array_vector.push_back(dynamic); + dynamic_array_vector.push_back(dynamic); + dynamic_array_vector.push_back(dynamic); + dynamic_array_vector.push_back(dynamic); + int x = (int)(Anonymous_D); } @@ -1846,6 +1880,11 @@ fancy_viz_eval_tests(void) raddbg_pin(text(code_string, lang=c)); raddbg_pin(disasm(fancy_viz_eval_tests)); + //- rjf: programmatic memory annotations + void *some_block_of_memory = malloc(256); + memset(some_block_of_memory, 0x27, 256); + raddbg_annotate_vaddr_range(some_block_of_memory, 256, "test memory annotation"); + //- rjf: half-floats PackedF16 f16s[] = { @@ -2624,6 +2663,56 @@ recursion_stepping_tests(void){ } +//////////////////////////////// +// NOTE(rjf): Thread Stepping + +#if _WIN32 +DWORD thread_step_thread(void *p) +{ + int x = 0; + for(int i = 0; i < 100000; i += 1) + { + x += 1; + x += 1; + x += 1; + x += 1; + x += 1; + x += 1; + x += 1; + x += 1; + x += 1; + x += 1; + x += 1; + x += 1; + x += 1; + x += 1; + } + return 0; +} +#endif + +void thread_stepping_tests(void) +{ +#if _WIN32 + HANDLE h[8] = {0}; + for(int i = 0; i < sizeof(h)/sizeof(h[0]); i += 1) + { + DWORD id = 0; + h[i] = CreateThread(0, 0, thread_step_thread, 0, CREATE_SUSPENDED, &id); + raddbg_thread_id_name(id, "thread_step_thread_%i", i); + raddbg_thread_id_color_u32(id, 0xff9f23ff); + } + for(int i = 0; i < sizeof(h)/sizeof(h[0]); i += 1) + { + ResumeThread(h[i]); + } + for(int i = 0; i < sizeof(h)/sizeof(h[0]); i += 1) + { + WaitForSingleObject(h[i], INFINITE); + } +#endif +} + //////////////////////////////// // NOTE(rjf): Debug Strings @@ -3039,6 +3128,8 @@ mule_main(int argc, char** argv) recursion_stepping_tests(); + thread_stepping_tests(); + debug_string_tests(); thread_name_tests(); diff --git a/src/mule/mule_module.cpp b/src/mule/mule_module.cpp index f07a2fcb..c47f74fa 100644 --- a/src/mule/mule_module.cpp +++ b/src/mule/mule_module.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #if _WIN32 diff --git a/src/mule/mule_o2.cpp b/src/mule/mule_o2.cpp index b9e86d19..e427e82e 100644 --- a/src/mule/mule_o2.cpp +++ b/src/mule/mule_o2.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) static int important_s32 = 0; diff --git a/src/mutable_text/mutable_text.c b/src/mutable_text/mutable_text.c index 94549be7..f53585c7 100644 --- a/src/mutable_text/mutable_text.c +++ b/src/mutable_text/mutable_text.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR diff --git a/src/mutable_text/mutable_text.h b/src/mutable_text/mutable_text.h index 1614ae48..bb6826ac 100644 --- a/src/mutable_text/mutable_text.h +++ b/src/mutable_text/mutable_text.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef MUTABLE_TEXT_H diff --git a/src/os/core/linux/os_core_linux.c b/src/os/core/linux/os_core_linux.c index a44072f7..83921594 100644 --- a/src/os/core/linux/os_core_linux.c +++ b/src/os/core/linux/os_core_linux.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/os/core/linux/os_core_linux.h b/src/os/core/linux/os_core_linux.h index e7d2ba5a..1770d239 100644 --- a/src/os/core/linux/os_core_linux.h +++ b/src/os/core/linux/os_core_linux.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_CORE_LINUX_H diff --git a/src/os/core/linux/os_core_linux_old.c b/src/os/core/linux/os_core_linux_old.c index 247a8248..91a457b0 100644 --- a/src/os/core/linux/os_core_linux_old.c +++ b/src/os/core/linux/os_core_linux_old.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include diff --git a/src/os/core/linux/os_core_linux_old.h b/src/os/core/linux/os_core_linux_old.h index 4b6263d3..efec7159 100644 --- a/src/os/core/linux/os_core_linux_old.h +++ b/src/os/core/linux/os_core_linux_old.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef LINUX_H diff --git a/src/os/core/os_core.c b/src/os/core/os_core.c index 21a0a413..048072e0 100644 --- a/src/os/core/os_core.c +++ b/src/os/core/os_core.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -90,13 +90,40 @@ os_write_data_list_to_file_path(String8 path, String8List list) if(!os_handle_match(file, os_handle_zero())) { good = 1; - U64 off = 0; - for(String8Node *n = list.first; n != 0; n = n->next) + Temp scratch = scratch_begin(0, 0); + U64 write_buffer_size = KB(64); + U8 *write_buffer = push_array_no_zero(scratch.arena, U8, write_buffer_size); + U64 write_buffer_write_pos = 0; + U64 write_buffer_read_pos = 0; + U64 file_off = 0; { - os_file_write(file, r1u64(off, off+n->string.size), n->string.str); - off += n->string.size; + for(String8Node *n = list.first; n != 0; n = n->next) + { + for(U64 n_off = 0; n_off < n->string.size;) + { + U64 write_buffer_unconsumed_size = (write_buffer_write_pos - write_buffer_read_pos); + U64 write_buffer_available_size = (write_buffer_size - write_buffer_unconsumed_size); + if(write_buffer_available_size == 0) + { + os_file_write(file, r1u64(file_off, file_off+write_buffer_size), write_buffer); + file_off += write_buffer_size; + write_buffer_read_pos += write_buffer_size; + } + else + { + U64 bytes_to_copy = Min(write_buffer_available_size, n->string.size - n_off); + write_buffer_write_pos += ring_write(write_buffer, write_buffer_size, write_buffer_write_pos, n->string.str + n_off, bytes_to_copy); + n_off += bytes_to_copy; + } + } + } + if(write_buffer_write_pos > write_buffer_read_pos) + { + os_file_write(file, r1u64(file_off, file_off + (write_buffer_write_pos-write_buffer_read_pos)), write_buffer); + } } os_file_close(file); + scratch_end(scratch); } return good; } @@ -151,6 +178,27 @@ os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range) return result; } +internal String8 +os_file_read_cstring(Arena *arena, OS_Handle file, U64 off) +{ + Temp scratch = scratch_begin(&arena, 1); + String8List block_list = {0}; + for(U64 cursor = off, stride = 256;; cursor += stride) + { + U8 *raw_block = push_array_no_zero(scratch.arena, U8, stride); + U64 read_size = os_file_read(file, r1u64(cursor, cursor + stride), raw_block); + String8 block = str8_cstring_capped(raw_block, raw_block+read_size); + str8_list_push(scratch.arena, &block_list, block); + if(read_size != stride || (block.size+1 <= read_size && block.str[block.size] == 0)) + { + break; + } + } + String8 result = str8_list_join(arena, &block_list, 0); + scratch_end(scratch); + return result; +} + //////////////////////////////// //~ rjf: Process Launcher Helpers diff --git a/src/os/core/os_core.h b/src/os/core/os_core.h index 369070e1..922f793c 100644 --- a/src/os/core/os_core.h +++ b/src/os/core/os_core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_CORE_H @@ -156,6 +156,7 @@ internal B32 os_append_data_to_file_path(String8 path, String8 data); internal OS_FileID os_id_from_file_path(String8 path); internal S64 os_file_id_compare(OS_FileID a, OS_FileID b); internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range); +internal String8 os_file_read_cstring(Arena *arena, OS_Handle file, U64 off); //////////////////////////////// //~ rjf: Process Launcher Helpers diff --git a/src/os/core/win32/os_core_win32.c b/src/os/core/win32/os_core_win32.c index ed69e685..cdb2c2e6 100644 --- a/src/os/core/win32/os_core_win32.c +++ b/src/os/core/win32/os_core_win32.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/os/core/win32/os_core_win32.h b/src/os/core/win32/os_core_win32.h index 9a8f0d12..22a21f80 100644 --- a/src/os/core/win32/os_core_win32.h +++ b/src/os/core/win32/os_core_win32.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_CORE_WIN32_H diff --git a/src/os/gfx/generated/os_gfx.meta.c b/src/os/gfx/generated/os_gfx.meta.c index 1debd74b..b44fa317 100644 --- a/src/os/gfx/generated/os_gfx.meta.c +++ b/src/os/gfx/generated/os_gfx.meta.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/os/gfx/generated/os_gfx.meta.h b/src/os/gfx/generated/os_gfx.meta.h index 46b08d2e..72ccea0c 100644 --- a/src/os/gfx/generated/os_gfx.meta.h +++ b/src/os/gfx/generated/os_gfx.meta.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/os/gfx/linux/os_gfx_linux.c b/src/os/gfx/linux/os_gfx_linux.c index f8d43416..12a9aa56 100644 --- a/src/os/gfx/linux/os_gfx_linux.c +++ b/src/os/gfx/linux/os_gfx_linux.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/os/gfx/linux/os_gfx_linux.h b/src/os/gfx/linux/os_gfx_linux.h index b0e23df2..58e51f27 100644 --- a/src/os/gfx/linux/os_gfx_linux.h +++ b/src/os/gfx/linux/os_gfx_linux.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_GFX_LINUX_H diff --git a/src/os/gfx/os_gfx.c b/src/os/gfx/os_gfx.c index 7523984b..ec0ccade 100644 --- a/src/os/gfx/os_gfx.c +++ b/src/os/gfx/os_gfx.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/os/gfx/os_gfx.h b/src/os/gfx/os_gfx.h index 1058c304..d56a71ca 100644 --- a/src/os/gfx/os_gfx.h +++ b/src/os/gfx/os_gfx.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_GFX_H diff --git a/src/os/gfx/os_gfx.mdesk b/src/os/gfx/os_gfx.mdesk index c86bdea0..fc15a5f2 100644 --- a/src/os/gfx/os_gfx.mdesk +++ b/src/os/gfx/os_gfx.mdesk @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/os/gfx/stub/os_gfx_stub.h b/src/os/gfx/stub/os_gfx_stub.h index e18b6f64..009f9802 100644 --- a/src/os/gfx/stub/os_gfx_stub.h +++ b/src/os/gfx/stub/os_gfx_stub.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_GFX_STUB_H diff --git a/src/os/gfx/win32/os_gfx_win32.c b/src/os/gfx/win32/os_gfx_win32.c index e298c187..93ad7dcf 100644 --- a/src/os/gfx/win32/os_gfx_win32.c +++ b/src/os/gfx/win32/os_gfx_win32.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/os/gfx/win32/os_gfx_win32.h b/src/os/gfx/win32/os_gfx_win32.h index 3ab4de16..8737055d 100644 --- a/src/os/gfx/win32/os_gfx_win32.h +++ b/src/os/gfx/win32/os_gfx_win32.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_GFX_WIN32_H diff --git a/src/os/os_inc.c b/src/os/os_inc.c index d92f9283..37c3e2aa 100644 --- a/src/os/os_inc.c +++ b/src/os/os_inc.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "os/core/os_core.c" diff --git a/src/os/os_inc.h b/src/os/os_inc.h index ce5246a0..d581fe6a 100644 --- a/src/os/os_inc.h +++ b/src/os/os_inc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef OS_INC_H diff --git a/src/path/path.c b/src/path/path.c index 32c928b7..780fe27b 100644 --- a/src/path/path.c +++ b/src/path/path.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/path/path.h b/src/path/path.h index 0aa18ec2..55b626ff 100644 --- a/src/path/path.h +++ b/src/path/path.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef PATH_H diff --git a/src/pdb/pdb.c b/src/pdb/pdb.c index ad2b1e10..035ca375 100644 --- a/src/pdb/pdb.c +++ b/src/pdb/pdb.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal U32 diff --git a/src/pdb/pdb.h b/src/pdb/pdb.h index 4afe71b7..a2988b8e 100644 --- a/src/pdb/pdb.h +++ b/src/pdb/pdb.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef PDB_H diff --git a/src/pdb/pdb_parse.c b/src/pdb/pdb_parse.c index 8d75a0d2..dd4bbd8a 100644 --- a/src/pdb/pdb_parse.c +++ b/src/pdb/pdb_parse.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -76,7 +76,7 @@ pdb_info_from_data(Arena *arena, String8 data){ if (epilogue_base_off <= data.size){ U64 record_off = epilogue_base_off; - + // read table if (hash_table_count > 0) { PDB_InfoNode *first = 0; @@ -103,17 +103,17 @@ pdb_info_from_data(Arena *arena, String8 data){ result->last = last; result->auth_guid = *auth_guid; } - - // read PDB features + + // read PDB features PDB_FeatureFlags features = 0; for (; record_off + sizeof(PDB_FeatureSig) <= data.size; ) { PDB_FeatureSig sig = 0; record_off += str8_deserial_read_struct(data, record_off, &sig); switch (sig) { - case PDB_FeatureSig_NULL: break; - case PDB_FeatureSig_VC140: features |= PDB_FeatureFlag_HAS_ID_STREAM; break; - case PDB_FeatureSig_NO_TYPE_MERGE: features |= PDB_FeatureFlag_NO_TYPE_MERGE; break; - case PDB_FeatureSig_MINIMAL_DEBUG_INFO: features |= PDB_FeatureFlag_MINIMAL_DBG_INFO; break; + case PDB_FeatureSig_NULL: break; + case PDB_FeatureSig_VC140: features |= PDB_FeatureFlag_HAS_ID_STREAM; break; + case PDB_FeatureSig_NO_TYPE_MERGE: features |= PDB_FeatureFlag_NO_TYPE_MERGE; break; + case PDB_FeatureSig_MINIMAL_DEBUG_INFO: features |= PDB_FeatureFlag_MINIMAL_DBG_INFO; break; } } result->features = features; @@ -581,18 +581,18 @@ internal U64 pdb_gsi_symbol_from_string(PDB_GsiParsed *gsi, String8 symbol_data, String8 string) { U64 result = max_U64; - + U32 hash = pdb_hash_v1(string); U32 bucket_idx = hash % ArrayCount(gsi->buckets); PDB_GsiBucket bucket = gsi->buckets[bucket_idx]; - + for(U64 i = 0; i < bucket.count; ++i) { U32 off = bucket.offs[i]; if(off + sizeof(CV_RecHeader) <= symbol_data.size) { CV_RecHeader *sym_header = (CV_RecHeader *)(symbol_data.str + off); - + if(sym_header->size >= sizeof(sym_header->kind)) { U64 opl_off = off + sizeof(sym_header->size) + sym_header->size; @@ -605,7 +605,7 @@ pdb_gsi_symbol_from_string(PDB_GsiParsed *gsi, String8 symbol_data, String8 stri Rng1U64 raw_symbol_range = rng_1u64(off + sizeof(*sym_header), off + (sym_header->size - sizeof(sym_header->kind))); String8 raw_symbol = str8_substr(symbol_data, raw_symbol_range); String8 sym_name = cv_name_from_symbol(sym_header->kind, raw_symbol); - + if(str8_match(sym_name, string, 0)) { result = off; @@ -614,8 +614,8 @@ pdb_gsi_symbol_from_string(PDB_GsiParsed *gsi, String8 symbol_data, String8 stri } } } - -exit:; + + exit:; return result; } @@ -704,8 +704,8 @@ pdb_comp_unit_array_from_data(Arena *arena, String8 data){ } internal PDB_CompUnitContributionArray* -pdb_comp_unit_contribution_array_from_data(Arena *arena, String8 data, - COFF_SectionHeaderArray sections){ +pdb_comp_unit_contribution_array_from_data(Arena *arena, String8 data, COFF_SectionHeaderArray sections) +{ PDB_CompUnitContribution *contributions = 0; U64 count = 0; if (data.size >= sizeof(PDB_DbiSectionContribVersion)){ @@ -1042,28 +1042,28 @@ internal U32 pdb_strtbl_off_from_string(PDB_Strtbl *strtbl, String8 string) { U32 result = max_U32; - + U32 hash = pdb_hash_v1(string); U32 best_bucket_idx = hash % strtbl->bucket_count; U32 bucket_idx = best_bucket_idx; - + do { String8 test_string = pdb_strtbl_string_from_index(strtbl, bucket_idx); - + if(test_string.size == 0) { break; } - + if(str8_match(test_string, string, 0)) { result = bucket_idx; break; } - + bucket_idx = (bucket_idx+1) % strtbl->buckets_max; } while (bucket_idx != best_bucket_idx); - + return result; } diff --git a/src/pdb/pdb_parse.h b/src/pdb/pdb_parse.h index ec827408..6b028ef4 100644 --- a/src/pdb/pdb_parse.h +++ b/src/pdb/pdb_parse.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef PDB_PARSE_H diff --git a/src/pdb/pdb_stringize.c b/src/pdb/pdb_stringize.c index 75716b5e..78ad4bd9 100644 --- a/src/pdb/pdb_stringize.c +++ b/src/pdb/pdb_stringize.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/pdb/pdb_stringize.h b/src/pdb/pdb_stringize.h index 72df9ee2..ec9ca39c 100644 --- a/src/pdb/pdb_stringize.h +++ b/src/pdb/pdb_stringize.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef PDB_STRINGIZE_H diff --git a/src/pe/dos_program.asm b/src/pe/dos_program.asm index 775659d0..3563abed 100644 --- a/src/pe/dos_program.asm +++ b/src/pe/dos_program.asm @@ -1,4 +1,4 @@ -; Copyright (c) 2024 Epic Games Tools +; Copyright (c) Epic Games Tools ; Licensed under the MIT license (https://opensource.org/license/mit/) ; $ c:\devel\projects\bin\win32\nasm src\pe\dos_program.asm -fbin -o dos_program.bin diff --git a/src/pe/pe.c b/src/pe/pe.c index 36c9e423..cf7cedfb 100644 --- a/src/pe/pe.c +++ b/src/pe/pe.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -209,7 +209,7 @@ internal String8 pe_string_from_global_flags(Arena *arena, PE_GlobalFlags flags) { Temp scratch = scratch_begin(&arena, 1); - + String8List l = {0}; if (flags & PE_GlobalFlags_STOP_ON_EXCEPTION) { str8_list_pushf(scratch.arena, &l, "STOP_ON_EXCEPTION"); @@ -304,7 +304,7 @@ pe_string_from_global_flags(Arena *arena, PE_GlobalFlags flags) if (flags & PE_GlobalFlags_DISABLE_PROTDLLS) { str8_list_pushf(scratch.arena, &l, "DISABLE_PROTDLLS"); } - + String8 result = str8_list_join(arena, &l, &(StringJoin){.sep=str8_lit(" ")}); return result; } @@ -345,7 +345,7 @@ pe_string_from_load_config_guard_flags(Arena *arena, PE_LoadConfigGuardFlags fla if (flags & PE_LoadConfigGuardFlags_EH_CONTINUATION_TABLE_PRESENT) { str8_list_pushf(scratch.arena, &l, "EH_CONTINUATION_TABLE_PRESENT"); } - + String8 result = str8_list_join(arena, &l, &(StringJoin){.sep = str8_lit(" ")}); scratch_end(scratch); return result; @@ -543,7 +543,7 @@ pe_bin_info_from_data(Arena *arena, String8 data) data_dir_count = ClampTop(reported_data_dir_count, data_dir_max); // rjf: convert PE directories to ranges - data_dir_franges = push_array(arena, Rng1U64, data_dir_count); + data_dir_franges = push_array(arena, Rng1U64, Max(data_dir_count, PE_DataDirectoryIndex_COUNT)); for(U32 dir_idx = 0; dir_idx < data_dir_count; dir_idx += 1) { U64 dir_offset = optional_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*dir_idx; @@ -615,92 +615,71 @@ pe_bin_info_from_data(Arena *arena, String8 data) info.data_dir_count = data_dir_count; info.tls_header = tls_header; } - + return info; } internal PE_DebugInfoList -pe_parse_debug_directory(Arena *arena, String8 raw_image, String8 raw_debug_dir) +pe_debug_info_list_from_raw_debug_dir(Arena *arena, String8 raw_image, String8 raw_debug_dir) { PE_DebugInfoList result = {0}; - PE_DebugDirectory *debug_entry = str8_deserial_get_raw_ptr(raw_debug_dir, 0, sizeof(*debug_entry)); PE_DebugDirectory *debug_entry_opl = debug_entry + raw_debug_dir.size/sizeof(*debug_entry_opl); - for (PE_DebugDirectory *entry = debug_entry; entry < debug_entry_opl; ++entry) { - switch (entry->type) { - default: { - PE_DebugInfoNode *n = push_array(arena, PE_DebugInfoNode, 1); - n->v.header = *entry; - n->v.u.raw_data = str8_substr(raw_image, rng_1u64(entry->foff, entry->foff + entry->size)); - - SLLQueuePush(result.first, result.last, n); - ++result.count; - } break; - case PE_DebugDirectoryType_CODEVIEW: { - U32 cv_magic = 0; - str8_deserial_read_struct(raw_image, entry->foff, &cv_magic); - - switch (cv_magic) { - case PE_CODEVIEW_PDB20_MAGIC: { + for(PE_DebugDirectory *entry = debug_entry; entry < debug_entry_opl; entry += 1) + { + PE_DebugInfoNode *n = push_array(arena, PE_DebugInfoNode, 1); + SLLQueuePush(result.first, result.last, n); + result.count += 1; + n->v.header = *entry; + switch(entry->type) + { + default:{}break; + case PE_DebugDirectoryType_CODEVIEW: + { + str8_deserial_read_struct(raw_image, entry->foff, &n->v.cv_magic); + switch(n->v.cv_magic) + { + case PE_CODEVIEW_PDB20_MAGIC: + { PE_CvHeaderPDB20 cv = {0}; U64 cv_read_size = str8_deserial_read_struct(raw_image, entry->foff, &cv); - if (cv_read_size == sizeof(cv)) { + if(cv_read_size == sizeof(cv)) + { String8 path = {0}; str8_deserial_read_cstr(raw_image, entry->foff+sizeof(cv), &path); - - PE_DebugInfoNode *n = push_array(arena, PE_DebugInfoNode, 1); - n->v.header = *entry; - n->v.u.codeview.pdb20.header = cv; - n->v.u.codeview.pdb20.path = path; - - SLLQueuePush(result.first, result.last, n); - ++result.count; - } else { - Assert(!"unable to read PE_CvHeaderPDB20"); + n->v.cv_pdb20_header = cv; + n->v.path = path; } - } break; - case PE_CODEVIEW_PDB70_MAGIC: { + }break; + case PE_CODEVIEW_PDB70_MAGIC: + { PE_CvHeaderPDB70 cv = {0}; U64 cv_read_size = str8_deserial_read_struct(raw_image, entry->foff, &cv); - if (cv_read_size == sizeof(cv)) { + if(cv_read_size == sizeof(cv)) + { String8 path = {0}; str8_deserial_read_cstr(raw_image, entry->foff+sizeof(cv), &path); - - PE_DebugInfoNode *n = push_array(arena, PE_DebugInfoNode, 1); - n->v.header = *entry; - n->v.u.codeview.pdb70.header = cv; - n->v.u.codeview.pdb70.path = path; - - SLLQueuePush(result.first, result.last, n); - ++result.count; - } else { - Assert(!"unable to read PE_CvHeaderPDB70"); + n->v.cv_pdb70_header = cv; + n->v.path = path; } - } break; - case PE_CODEVIEW_RDI_MAGIC: { + }break; + case PE_CODEVIEW_RDI_MAGIC: + { PE_CvHeaderRDI cv = {0}; U64 cv_read_size = str8_deserial_read_struct(raw_image, entry->foff, &cv); - if (cv_read_size == sizeof(cv)) { + if(cv_read_size == sizeof(cv)) + { String8 path = {0}; str8_deserial_read_cstr(raw_image, entry->foff+sizeof(cv), &path); - - PE_DebugInfoNode *n = push_array(arena, PE_DebugInfoNode, 1); - n->v.header = *entry; - n->v.u.codeview.rdi.header = cv; - n->v.u.codeview.rdi.path = path; - - SLLQueuePush(result.first, result.last, n); - ++result.count; - } else { - Assert(!"unable to read PE_CvHeaderRDI"); + n->v.cv_rdi_header = cv; + n->v.path = path; } - } break; - default: break; + }break; + default:{}break; } - } break; + }break; } } - return result; } @@ -711,7 +690,7 @@ internal U64 pe_pdata_off_from_voff__binary_search_x8664(String8 raw_pdata, U64 voff) { U64 result = 0; - + if(raw_pdata.size >= sizeof(PE_IntelPdata)) { U64 pdata_count = raw_pdata.size/sizeof(PE_IntelPdata); @@ -747,7 +726,7 @@ pe_pdata_off_from_voff__binary_search_x8664(String8 raw_pdata, U64 voff) break; } } - + // if we are in range fill result { PE_IntelPdata *pdata = pdata_array + index; @@ -758,7 +737,7 @@ pe_pdata_off_from_voff__binary_search_x8664(String8 raw_pdata, U64 voff) } } } - + return result; } @@ -805,7 +784,7 @@ pe_base_reloc_block_list_from_data(Arena *arena, String8 raw_base_relocs) PE_BaseRelocBlockNode *node = push_array(arena, PE_BaseRelocBlockNode, 1); SLLQueuePush(list.first, list.last, node); list.count += 1; - + U64 entries_size = block_size - (sizeof(block_size) + sizeof(page_virt_off)); // rjf: fill block @@ -815,7 +794,7 @@ pe_base_reloc_block_list_from_data(Arena *arena, String8 raw_base_relocs) block->entries = push_array(arena, U16, block->entry_count); U64 entry_read_size = str8_deserial_read_array(raw_base_relocs, off, &block->entries[0], block->entry_count); Assert(entry_read_size == sizeof(block->entries[0]) * block->entry_count); - + off += entry_read_size; } return list; @@ -920,58 +899,58 @@ pe_get_entry_point_names(COFF_MachineType machine, read_only static String8 dll_entry_point_arr[] = { str8_lit_comp("__DllMainCRTStartup@12"), }; - + entry_point_names.v = &dll_entry_point_arr[0]; entry_point_names.count = ArrayCount(dll_entry_point_arr); } else { read_only static String8 dll_entry_point_arr[] = { str8_lit_comp("_DllMainCRTStartup"), }; - + entry_point_names.v = &dll_entry_point_arr[0]; entry_point_names.count = ArrayCount(dll_entry_point_arr); } } else { switch (subsystem) { - case PE_WindowsSubsystem_UNKNOWN: break; - case PE_WindowsSubsystem_WINDOWS_GUI: { - read_only static String8 gui_entry_point_arr[] = { - str8_lit_comp("WinMain"), - str8_lit_comp("wWinMain"), - str8_lit_comp("WinMainCRTStartup"), - str8_lit_comp("wWinMainCRTStartup"), - }; - - entry_point_names.v = &gui_entry_point_arr[0]; - entry_point_names.count = ArrayCount(gui_entry_point_arr); - } break; - case PE_WindowsSubsystem_WINDOWS_CUI: { - read_only static String8 cui_entry_point_arr[] = { - str8_lit_comp("main"), - str8_lit_comp("wmain"), - str8_lit_comp("mainCRTStartup"), - str8_lit_comp("wmainCRTStartup"), - }; - - entry_point_names.v = &cui_entry_point_arr[0]; - entry_point_names.count = ArrayCount(cui_entry_point_arr); - } break; - case PE_WindowsSubsystem_NATIVE: - case PE_WindowsSubsystem_OS2_CUI: - case PE_WindowsSubsystem_POSIX_CUI: - case PE_WindowsSubsystem_NATIVE_WINDOWS: - case PE_WindowsSubsystem_WINDOWS_CE_GUI: - case PE_WindowsSubsystem_EFI_APPLICATION: - case PE_WindowsSubsystem_EFI_BOOT_SERVICE_DRIVER: - case PE_WindowsSubsystem_EFI_RUNTIME_DRIVER: - case PE_WindowsSubsystem_EFI_ROM: - case PE_WindowsSubsystem_XBOX: - case PE_WindowsSubsystem_WINDOWS_BOOT_APPLICATION: { - // TODO - } break; + case PE_WindowsSubsystem_UNKNOWN: break; + case PE_WindowsSubsystem_WINDOWS_GUI: { + read_only static String8 gui_entry_point_arr[] = { + str8_lit_comp("WinMain"), + str8_lit_comp("wWinMain"), + str8_lit_comp("WinMainCRTStartup"), + str8_lit_comp("wWinMainCRTStartup"), + }; + + entry_point_names.v = &gui_entry_point_arr[0]; + entry_point_names.count = ArrayCount(gui_entry_point_arr); + } break; + case PE_WindowsSubsystem_WINDOWS_CUI: { + read_only static String8 cui_entry_point_arr[] = { + str8_lit_comp("main"), + str8_lit_comp("wmain"), + str8_lit_comp("mainCRTStartup"), + str8_lit_comp("wmainCRTStartup"), + }; + + entry_point_names.v = &cui_entry_point_arr[0]; + entry_point_names.count = ArrayCount(cui_entry_point_arr); + } break; + case PE_WindowsSubsystem_NATIVE: + case PE_WindowsSubsystem_OS2_CUI: + case PE_WindowsSubsystem_POSIX_CUI: + case PE_WindowsSubsystem_NATIVE_WINDOWS: + case PE_WindowsSubsystem_WINDOWS_CE_GUI: + case PE_WindowsSubsystem_EFI_APPLICATION: + case PE_WindowsSubsystem_EFI_BOOT_SERVICE_DRIVER: + case PE_WindowsSubsystem_EFI_RUNTIME_DRIVER: + case PE_WindowsSubsystem_EFI_ROM: + case PE_WindowsSubsystem_XBOX: + case PE_WindowsSubsystem_WINDOWS_BOOT_APPLICATION: { + // TODO + } break; } } - + return entry_point_names; } @@ -988,9 +967,9 @@ pe_parsed_imports_from_data(Arena *arena, { PE_ParsedImport *imports = 0; U64 import_count = 0; - + U64 name_table_off = coff_foff_from_voff(sections, section_count, name_table_voff); - + if (is_pe32) { for (;; ++import_count) { U32 raw_entry = 0; @@ -999,18 +978,18 @@ pe_parsed_imports_from_data(Arena *arena, break; } } - + imports = push_array(arena, PE_ParsedImport, import_count); - + for (U64 imp_idx = 0; imp_idx < import_count; ++imp_idx) { U32 raw_entry = 0; str8_deserial_read_struct(raw_data, name_table_off + imp_idx*sizeof(raw_entry), &raw_entry); - + B32 is_ordinal = raw_entry & (1 << 31); - + PE_ParsedImport *imp = imports+imp_idx; ++imp_idx; - + if (is_ordinal) { // fill out ordinal import imp->type = PE_ParsedImport_Ordinal; @@ -1018,13 +997,13 @@ pe_parsed_imports_from_data(Arena *arena, } else { // map voff -> foff U64 off = coff_foff_from_voff(sections, section_count, raw_entry); - + // read hint & name U16 hint = 0; String8 name = str8_zero(); str8_deserial_read_struct(raw_data, off, &hint); str8_deserial_read_cstr(raw_data, off+sizeof(hint), &name); - + // fill out named import imp->type = PE_ParsedImport_Name; imp->u.name.hint = hint; @@ -1039,18 +1018,18 @@ pe_parsed_imports_from_data(Arena *arena, break; } } - + imports = push_array(arena, PE_ParsedImport, import_count); - + for (U64 imp_idx = 0; imp_idx < import_count; ++imp_idx) { U64 raw_entry = 0; str8_deserial_read_struct(raw_data, name_table_off + imp_idx*sizeof(raw_entry), &raw_entry); - + B32 is_ordinal = raw_entry & (1ull << 63); - + PE_ParsedImport *imp = imports+imp_idx; ++imp_idx; - + if (is_ordinal) { // fill out ordinal import imp->type = PE_ParsedImport_Ordinal; @@ -1058,13 +1037,13 @@ pe_parsed_imports_from_data(Arena *arena, } else { // map voff -> foff U64 off = coff_foff_from_voff(sections, section_count, raw_entry); - + // read hint & name U16 hint = 0; String8 name = str8_zero(); str8_deserial_read_struct(raw_data, off, &hint); str8_deserial_read_cstr(raw_data, off + sizeof(hint), &name); - + // fill out named import imp->type = PE_ParsedImport_Name; imp->u.name.hint = hint; @@ -1072,7 +1051,7 @@ pe_parsed_imports_from_data(Arena *arena, } } } - + *import_count_out = import_count; return imports; } @@ -1082,11 +1061,11 @@ pe_array_from_null_term_addr(Arena *arena, B32 is_pe32, String8 raw_data, Rng1U6 { U64 *result = 0; *count_out = 0; - + if (is_pe32) { U32 *src = (U32 *)(raw_data.str + range.min); U32 *opl = (U32 *)(raw_data.str + AlignDownPow2(range.max, sizeof(*opl))); - + // count items U32 *ptr; for (ptr = src; ptr < opl && *ptr != 0; ++ptr); @@ -1094,7 +1073,7 @@ pe_array_from_null_term_addr(Arena *arena, B32 is_pe32, String8 raw_data, Rng1U6 // push output array *count_out = (U64)(ptr - src); result = push_array(arena, U64, *count_out); - + // convert & copy for (U64 i = 0; i < *count_out; ++i) { result[i] = (U64)src[i]; @@ -1102,19 +1081,19 @@ pe_array_from_null_term_addr(Arena *arena, B32 is_pe32, String8 raw_data, Rng1U6 } else { U64 *src = (U64 *)(raw_data.str + range.min); U64 *opl = (U64 *)(raw_data.str + AlignDownPow2(range.max, sizeof(*opl))); - + // count items U64 *ptr; for (ptr = src; ptr < opl && *ptr != 0; ++ptr); - + // push output array *count_out = (U64)(ptr - src); result = push_array(arena, U64, *count_out); - + // copy MemoryCopyTyped(result, src, *count_out); } - + return result; } @@ -1136,17 +1115,17 @@ pe_static_imports_from_data(Arena *arena, break; } } - + PE_ParsedStaticDLLImport *dlls = push_array(arena, PE_ParsedStaticDLLImport, dll_count); - + for (U64 dll_idx = 0; dll_idx < dll_count; ++dll_idx) { PE_ImportEntry *raw_dll = str8_deserial_get_raw_ptr(raw_data, dir_file_range.min+(dll_idx*sizeof(*raw_dll)), sizeof(*raw_dll)); - + // get name U64 name_off = coff_foff_from_voff(sections, section_count, raw_dll->name_voff); String8 name = str8_zero(); str8_deserial_read_cstr(raw_data, name_off, &name); - + U64 import_count = 0; PE_ParsedImport *imports = pe_parsed_imports_from_data(arena, is_pe32, @@ -1155,7 +1134,7 @@ pe_static_imports_from_data(Arena *arena, raw_data, raw_dll->lookup_table_voff, &import_count); - + PE_ParsedStaticDLLImport *dll = dlls+dll_idx; dll->name = name; dll->import_address_table_voff = raw_dll->import_addr_table_voff; @@ -1165,11 +1144,11 @@ pe_static_imports_from_data(Arena *arena, dll->import_count = import_count; dll->imports = imports; } - + PE_ParsedStaticImportTable imptab = {0}; imptab.count = dll_count; imptab.v = dlls; - + return imptab; } @@ -1190,16 +1169,16 @@ pe_delay_imports_from_data(Arena *arena, break; } } - + // parse dll imports PE_ParsedDelayDLLImport *dlls = push_array(arena, PE_ParsedDelayDLLImport, dll_count); for (U64 dll_idx = 0; dll_idx < dll_count; ++dll_idx) { PE_DelayedImportEntry *raw_dll = str8_deserial_get_raw_ptr(raw_data, dir_file_range.min+(dll_idx*sizeof(*raw_dll)), sizeof(*raw_dll)); - + U64 name_off = coff_foff_from_voff(sections, section_count, raw_dll->name_voff); String8 name = str8_zero(); str8_deserial_read_cstr(raw_data, name_off, &name); - + // parse import table U64 import_count = 0; PE_ParsedImport *imports = pe_parsed_imports_from_data(arena, @@ -1209,19 +1188,19 @@ pe_delay_imports_from_data(Arena *arena, raw_data, raw_dll->name_table_voff, &import_count); - + // parse bound table U64 bound_table_foff = coff_foff_from_voff(sections, section_count, raw_dll->bound_table_voff); Rng1U64 bound_table_range = rng_1u64(bound_table_foff, raw_data.size); U64 bound_table_count; U64 * bound_table = pe_array_from_null_term_addr(arena, is_pe32, raw_data, bound_table_range, &bound_table_count); - + // parse unload table U64 unload_table_foff = coff_foff_from_voff(sections, section_count, raw_dll->unload_table_voff); Rng1U64 unload_table_range = rng_1u64(unload_table_foff, raw_data.size); U64 unload_table_count; U64 * unload_table = pe_array_from_null_term_addr(arena, is_pe32, raw_data, unload_table_range, &unload_table_count); - + // fill out DLL PE_ParsedDelayDLLImport *dll = dlls+dll_idx; dll->attributes = raw_dll->attributes; @@ -1239,12 +1218,12 @@ pe_delay_imports_from_data(Arena *arena, dll->import_count = import_count; dll->imports = imports; } - + // fill out result PE_ParsedDelayImportTable imptab = {0}; imptab.count = dll_count; imptab.v = dlls; - + return imptab; } @@ -1252,20 +1231,20 @@ internal PE_ParsedExportTable pe_exports_from_data(Arena *arena, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range, Rng1U64 dir_virt_range) { Temp scratch = scratch_begin(&arena, 1); - + PE_ParsedExportTable exptab = {0}; - + String8 raw_dir = str8_substr(raw_data, dir_file_range); PE_ExportTableHeader *header = str8_deserial_get_raw_ptr(raw_dir, 0, sizeof(*header)); if (header) { U64 name_table_off = coff_foff_from_voff(sections, section_count, header->name_pointer_table_voff); U64 export_table_off = coff_foff_from_voff(sections, section_count, header->export_address_table_voff); U64 ordinal_table_off = coff_foff_from_voff(sections, section_count, header->ordinal_table_voff); - + U32 *name_table = str8_deserial_get_raw_ptr(raw_data, name_table_off, sizeof(*name_table )*header->name_pointer_table_count); U32 *export_table = str8_deserial_get_raw_ptr(raw_data, export_table_off, sizeof(*export_table )*header->export_address_table_count); U16 *ordinal_table = str8_deserial_get_raw_ptr(raw_data, ordinal_table_off, sizeof(*ordinal_table)*header->name_pointer_table_count); - + if (name_table && export_table && ordinal_table) { // Scan export address table to get accruate count of ordinals. // We can't rely on "name_pointer_table_count" becuase it is possible @@ -1276,36 +1255,36 @@ pe_exports_from_data(Arena *arena, U64 section_count, COFF_SectionHeader *sectio ++ordinal_count; } } - + U64 ordinal_max = header->export_address_table_count; B32 *is_ordinal_used = push_array(scratch.arena, B32, ordinal_max); - + PE_ParsedExport *exports = push_array(arena, PE_ParsedExport, ordinal_count); PE_ParsedExport *curr_exp = exports; - + // parse exports with name for (U64 i = 0; i < header->name_pointer_table_count; ++i) { // get name U32 name_voff = name_table[i]; U64 name_foff = coff_foff_from_voff(sections, section_count, name_voff); String8 name = str8_cstring_capped(raw_data.str+name_foff, raw_data.str+raw_data.size); - + // get ordinal U16 ordinal_nb = ordinal_table[i]; - + // mark ordinal Assert(ordinal_nb < ordinal_max); is_ordinal_used[ordinal_nb] = 1; - + // get voff U32 export_voff = 0; if (ordinal_nb < header->export_address_table_count) { export_voff = export_table[ordinal_nb]; } - + // make ordinal U16 ordinal = header->ordinal_base + ordinal_nb; - + String8 forwarder = str8_zero(); { B32 is_forwarder = dir_virt_range.min <= export_voff && export_voff < dir_virt_range.max; @@ -1314,14 +1293,14 @@ pe_exports_from_data(Arena *arena, U64 section_count, COFF_SectionHeader *sectio str8_deserial_read_cstr(raw_data, fwd_name_off, &forwarder); } } - + curr_exp->forwarder = forwarder; curr_exp->name = name; curr_exp->voff = export_voff; curr_exp->ordinal = ordinal; ++curr_exp; } - + // parse exports with ordinal for (U64 ordinal_nb = 0; ordinal_nb < header->export_address_table_count; ++ordinal_nb) { U32 voff = export_table[ordinal_nb]; @@ -1334,7 +1313,7 @@ pe_exports_from_data(Arena *arena, U64 section_count, COFF_SectionHeader *sectio ++curr_exp; } } - + // fill out result exptab.flags = header->flags; exptab.time_stamp = header->time_stamp; @@ -1345,7 +1324,7 @@ pe_exports_from_data(Arena *arena, U64 section_count, COFF_SectionHeader *sectio exptab.exports = exports; } } - + scratch_end(scratch); return exptab; } @@ -1361,32 +1340,32 @@ pe_tls_from_data(Arena *arena, Rng1U64 tls_frange) { String8 raw_tls = str8_substr(raw_data, tls_frange); - + PE_TLSHeader64 header64 = {0}; U64 callback_count = 0; U64 *callback_addrs = 0; - + switch (machine) { case COFF_MachineType_Unknown: break; case COFF_MachineType_X86: { PE_TLSHeader32 header32 = {0}; str8_deserial_read_struct(raw_tls, 0, &header32); - + header64.raw_data_start = header32.raw_data_start; header64.raw_data_end = header32.raw_data_end; header64.index_address = header32.index_address; header64.callbacks_address = header32.callbacks_address; header64.zero_fill_size = header32.zero_fill_size; header64.characteristics = header32.characteristics; - + U64 callbacks_voff = header32.callbacks_address - image_base; U64 callbacks_foff = coff_foff_from_voff(sections, section_count, callbacks_voff); - + U32 *src = (U32 *)(raw_data.str + callbacks_foff); U32 *opl = (U32 *)(raw_data.str + raw_data.size); U32 *ptr = src; for (; ptr < opl && *ptr != 0; ++ptr); - + callback_count = (U64)(ptr-src); callback_addrs = push_array(arena, U64, callback_count); for (U64 i = 0; i < callback_count; ++i) { @@ -1395,27 +1374,27 @@ pe_tls_from_data(Arena *arena, } break; case COFF_MachineType_X64: { str8_deserial_read_struct(raw_tls, 0, &header64); - + U64 callbacks_voff = header64.callbacks_address - image_base; U64 callbacks_foff = coff_foff_from_voff(sections, section_count, callbacks_voff); - + U64 *src = (U64 *)(raw_data.str + callbacks_foff); U64 *opl = (U64 *)(raw_data.str + raw_data.size); U64 *ptr = src; for (; ptr < opl && *ptr != 0; ++ptr); - + callback_count = (U64)(ptr-src); callback_addrs = push_array(arena, U64, callback_count); MemoryCopyTyped(callback_addrs, src, callback_count); } break; default: NotImplemented; } - + PE_ParsedTLS result = {0}; result.header = header64; result.callback_count = callback_count; result.callback_addrs = callback_addrs; - + return result; } @@ -1691,11 +1670,11 @@ pe_make_manifest_resource(Arena *arena, U32 resource_id, String8 manifest_data) COFF_ResourceID type = {0}; type.type = COFF_ResourceIDType_Number; type.u.number = PE_ResourceKind_MANIFEST; - + COFF_ResourceID id = {0}; id.type = COFF_ResourceIDType_Number; id.u.number = resource_id; - + String8 res = coff_write_resource(arena, type, id, 1, 0, 1033, 0, 0, manifest_data); return res; } @@ -1719,7 +1698,7 @@ pe_make_debug_header_pdb70(Arena *arena, Guid guid, U32 age, String8 pdb_path) str8_serial_push_cstr(scratch.arena, &cv_list, pdb_path); String8 cv_data = str8_serial_end(arena, &cv_list); - + scratch_end(scratch); return cv_data; } @@ -1728,18 +1707,18 @@ internal String8 pe_make_debug_header_rdi(Arena *arena, Guid guid, String8 rdi_path) { Temp scratch = scratch_begin(&arena,1); - + PE_CvHeaderRDI header = {0}; header.magic = PE_CODEVIEW_RDI_MAGIC; header.guid = guid; - + String8List list = {0}; str8_serial_begin(scratch.arena, &list); str8_serial_push_struct(scratch.arena, &list, &header); str8_serial_push_cstr(scratch.arena, &list, rdi_path); - + String8 cv_data = str8_serial_end(arena, &list); - + scratch_end(scratch); return cv_data; } diff --git a/src/pe/pe.h b/src/pe/pe.h index 7dadd496..61f6c783 100644 --- a/src/pe/pe.h +++ b/src/pe/pe.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef PE_H @@ -386,14 +386,14 @@ struct PE_LoadConfig32 U32 security_cookie; U32 seh_handler_table; U32 seh_handler_count; - + // msvc 2015 U32 guard_cf_check_func_ptr; U32 guard_cf_dispatch_func_ptr; U32 guard_cf_func_table; U32 guard_cf_func_count; U32 guard_flags; - + // msvc 2017 PE_LoadConfigCodeIntegrity code_integrity; U32 guard_address_taken_iat_entry_table; @@ -409,7 +409,7 @@ struct PE_LoadConfig32 U16 reserved2; U32 guard_rf_verify_stack_pointer_func_ptr; U32 hot_patch_table_offset; - + // msvc 2019 U32 reserved3; U32 enclave_config_ptr; @@ -445,14 +445,14 @@ struct PE_LoadConfig64 U64 security_cookie; U64 seh_handler_table; U64 seh_handler_count; - + // msvc 2015 U64 guard_cf_check_func_ptr; U64 guard_cf_dispatch_func_ptr; U64 guard_cf_func_table; U64 guard_cf_func_count; U32 guard_flags; - + // msvc 2017 PE_LoadConfigCodeIntegrity code_integrity; U64 guard_address_taken_iat_entry_table; @@ -468,7 +468,7 @@ struct PE_LoadConfig64 U16 reserved2; U64 guard_rf_verify_stack_pointer_func_ptr; U32 hot_patch_table_offset; - + // msvc 2019 U32 reserved3; U64 enclave_config_ptr; @@ -1012,30 +1012,13 @@ struct PE_BinInfo typedef struct PE_DebugInfo { PE_DebugDirectory header; - union - { - union - { - U32 magic; - struct - { - PE_CvHeaderPDB20 header; - String8 path; - } pdb20; - struct - { - PE_CvHeaderPDB70 header; - String8 path; - } pdb70; - struct - { - PE_CvHeaderRDI header; - String8 path; - } rdi; - } codeview; - String8 raw_data; - } u; -} PE_DebugInfo; + U32 cv_magic; + PE_CvHeaderPDB20 cv_pdb20_header; + PE_CvHeaderPDB70 cv_pdb70_header; + PE_CvHeaderRDI cv_rdi_header; + String8 path; +} +PE_DebugInfo; typedef struct PE_DebugInfoNode { @@ -1075,7 +1058,7 @@ internal String8 pe_string_from_dll_characteristics(Arena *arena, PE_DllCharacte internal B32 pe_check_magic(String8 data); internal PE_BinInfo pe_bin_info_from_data(Arena *arena, String8 data); -internal PE_DebugInfoList pe_parse_debug_directory(Arena *arena, String8 raw_image, String8 raw_debug_dir); +internal PE_DebugInfoList pe_debug_info_list_from_raw_debug_dir(Arena *arena, String8 raw_image, String8 raw_debug_dir); internal PE_ParsedStaticImportTable pe_static_imports_from_data(Arena *arena, B32 is_pe32, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range); internal PE_ParsedDelayImportTable pe_delay_imports_from_data(Arena *arena, B32 is_pe32, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range); internal PE_ParsedExportTable pe_exports_from_data(Arena *arena, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range, Rng1U64 dir_virt_range); diff --git a/src/ptr_graph_cache/ptr_graph_cache.c b/src/ptr_graph_cache/ptr_graph_cache.c index 9ca8d09d..943f563c 100644 --- a/src/ptr_graph_cache/ptr_graph_cache.c +++ b/src/ptr_graph_cache/ptr_graph_cache.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/ptr_graph_cache/ptr_graph_cache.h b/src/ptr_graph_cache/ptr_graph_cache.h index ff707462..96193eae 100644 --- a/src/ptr_graph_cache/ptr_graph_cache.h +++ b/src/ptr_graph_cache/ptr_graph_cache.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef PTR_GRAPH_CACHE_H diff --git a/src/radbin/generated/radbin.meta.c b/src/radbin/generated/radbin.meta.c new file mode 100644 index 00000000..11d620e7 --- /dev/null +++ b/src/radbin/generated/radbin.meta.c @@ -0,0 +1,22 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//- GENERATED CODE + +C_LINKAGE_BEGIN +String8 rb_file_format_display_name_table[10] = +{ +{0}, +str8_lit_comp("PDB"), +str8_lit_comp("PE"), +str8_lit_comp("COFF (OBJ)"), +str8_lit_comp("COFF (Big OBJ)"), +str8_lit_comp("COFF (Archive)"), +str8_lit_comp("COFF (Thin Archive)"), +str8_lit_comp("ELF32"), +str8_lit_comp("ELF64"), +str8_lit_comp("RDI"), +}; + +C_LINKAGE_END + diff --git a/src/radbin/generated/radbin.meta.h b/src/radbin/generated/radbin.meta.h new file mode 100644 index 00000000..8f8260de --- /dev/null +++ b/src/radbin/generated/radbin.meta.h @@ -0,0 +1,29 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//- GENERATED CODE + +#ifndef RADBIN_META_H +#define RADBIN_META_H + +typedef enum RB_FileFormat +{ +RB_FileFormat_Null, +RB_FileFormat_PDB, +RB_FileFormat_PE, +RB_FileFormat_COFF_OBJ, +RB_FileFormat_COFF_BigOBJ, +RB_FileFormat_COFF_Archive, +RB_FileFormat_COFF_ThinArchive, +RB_FileFormat_ELF32, +RB_FileFormat_ELF64, +RB_FileFormat_RDI, +RB_FileFormat_COUNT, +} RB_FileFormat; + +C_LINKAGE_BEGIN +extern String8 rb_file_format_display_name_table[10]; + +C_LINKAGE_END + +#endif // RADBIN_META_H diff --git a/src/radbin/radbin.c b/src/radbin/radbin.c new file mode 100644 index 00000000..236c1d29 --- /dev/null +++ b/src/radbin/radbin.c @@ -0,0 +1,978 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//////////////////////////////// +//~ rjf: Generated Code + +#include "radbin/generated/radbin.meta.c" + +//////////////////////////////// +//~ rjf: Top-Level Entry Point + +internal void +rb_entry_point(CmdLine *cmdline) +{ + Arena *arena = arena_alloc(); + ASYNC_Root *async_root = async_root_alloc(); + Log *log = log_alloc(); + log_select(log); + log_scope_begin(); + + ////////////////////////////// + //- rjf: analyze & load command line input files + // + RB_FileList input_files = {0}; + { + String8List input_file_path_tasks = str8_list_copy(arena, &cmdline->inputs); + for(String8Node *n = input_file_path_tasks.first; n != 0; n = n->next) + { + ////////////////////////// + //- rjf: do thin analysis of file + // + RB_FileFormat file_format = RB_FileFormat_Null; + RB_FileFormatFlags file_format_flags = 0; + { + OS_Handle file = os_file_open(OS_AccessFlag_Read, n->string); + FileProperties props = os_properties_from_file(file); + + //- rjf: PDB magic -> PDB input + if(file_format == RB_FileFormat_Null) + { + 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_format = RB_FileFormat_PDB; + } + } + if(file_format == RB_FileFormat_Null) + { + 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_format = RB_FileFormat_PDB; + } + } + + //- rjf: PE magic -> PE input + if(file_format == RB_FileFormat_Null) + { + PE_DosHeader dos_header_maybe = {0}; + os_file_read_struct(file, 0, &dos_header_maybe); + if(dos_header_maybe.magic == PE_DOS_MAGIC) + { + U32 pe_magic_maybe = 0; + os_file_read_struct(file, dos_header_maybe.coff_file_offset, &pe_magic_maybe); + if(pe_magic_maybe == PE_MAGIC) + { + file_format = RB_FileFormat_PE; + } + } + } + + //- rjf: COFF archive magic -> COFF archive input + if(file_format == RB_FileFormat_Null) + { + U8 coff_archive_sig_maybe[sizeof(g_coff_archive_sig)] = {0}; + os_file_read(file, r1u64(0, sizeof(coff_archive_sig_maybe)), coff_archive_sig_maybe); + if(MemoryMatch(coff_archive_sig_maybe, g_coff_archive_sig, sizeof(g_coff_archive_sig))) + { + file_format = RB_FileFormat_COFF_Archive; + } + } + if(file_format == RB_FileFormat_Null) + { + U8 coff_thin_archive_sig_maybe[sizeof(g_coff_thin_archive_sig)] = {0}; + os_file_read(file, r1u64(0, sizeof(coff_thin_archive_sig_maybe)), coff_thin_archive_sig_maybe); + if(MemoryMatch(coff_thin_archive_sig_maybe, g_coff_thin_archive_sig, sizeof(g_coff_thin_archive_sig))) + { + file_format = RB_FileFormat_COFF_ThinArchive; + } + } + + //- rjf: COFF obj magic -> COFF obj input + if(file_format == RB_FileFormat_Null) + { + COFF_BigObjHeader header_maybe = {0}; + os_file_read_struct(file, 0, &header_maybe); + if(header_maybe.sig1 == COFF_MachineType_Unknown && + header_maybe.sig2 == max_U16 && + header_maybe.version >= 2 && + MemoryMatch(header_maybe.magic, g_coff_big_header_magic, sizeof(header_maybe.magic))) + { + file_format = RB_FileFormat_COFF_BigOBJ; + } + } + if(file_format == RB_FileFormat_Null) + { + Temp scratch = scratch_begin(&arena, 1); + COFF_FileHeader header_maybe = {0}; + os_file_read_struct(file, 0, &header_maybe); + U64 section_count = header_maybe.section_count; + U64 section_hdr_opl_off = sizeof(header_maybe) + section_count*sizeof(COFF_SectionHeader); + + // rjf: check if machine type is valid + B32 machine_type_is_valid = 0; + switch(header_maybe.machine) + { + case COFF_MachineType_Unknown: + case COFF_MachineType_X86: case COFF_MachineType_X64: + case COFF_MachineType_Am33: case COFF_MachineType_Arm: + case COFF_MachineType_Arm64: case COFF_MachineType_ArmNt: + case COFF_MachineType_Ebc: case COFF_MachineType_Ia64: + case COFF_MachineType_M32R: case COFF_MachineType_Mips16: + case COFF_MachineType_MipsFpu:case COFF_MachineType_MipsFpu16: + case COFF_MachineType_PowerPc:case COFF_MachineType_PowerPcFp: + case COFF_MachineType_R4000: case COFF_MachineType_RiscV32: + case COFF_MachineType_RiscV64:case COFF_MachineType_RiscV128: + case COFF_MachineType_Sh3: case COFF_MachineType_Sh3Dsp: + case COFF_MachineType_Sh4: case COFF_MachineType_Sh5: + case COFF_MachineType_Thumb: case COFF_MachineType_WceMipsV2: + { + machine_type_is_valid = 1; + }break; + } + + // rjf: check if sections are valid + B32 sections_are_valid = 0; + if(machine_type_is_valid) + { + if(props.size >= section_hdr_opl_off) + { + COFF_SectionHeader *section_hdrs = push_array(scratch.arena, COFF_SectionHeader, section_count); + os_file_read(file, r1u64(sizeof(header_maybe), sizeof(header_maybe) + section_count*sizeof(COFF_SectionHeader)), section_hdrs); + B32 section_ranges_valid = 1; + for EachIndex(section_hdr_idx, section_count) + { + COFF_SectionHeader *hdr = §ion_hdrs[section_hdr_idx]; + if(!(hdr->flags & COFF_SectionFlag_CntUninitializedData)) + { + U64 min = hdr->foff; + U64 max = min + hdr->fsize; + if(hdr->fsize > 0 && !(section_hdr_opl_off <= min && min <= max && max <= props.size)) + { + section_ranges_valid = 0; + break; + } + } + } + sections_are_valid = section_ranges_valid; + } + } + + // rjf: check if symbol table is valid + B32 symbol_table_is_valid = 0; + if(sections_are_valid) + { + U64 symbol_table_off = header_maybe.symbol_table_foff; + U64 symbol_table_size = sizeof(COFF_Symbol16)*header_maybe.symbol_count; + U64 symbol_table_opl_off = symbol_table_off+symbol_table_size; + if(symbol_table_off == 0 && symbol_table_size == 0) + { + symbol_table_off = section_hdr_opl_off; + symbol_table_opl_off = section_hdr_opl_off; + } + symbol_table_is_valid = (section_hdr_opl_off <= symbol_table_off && + symbol_table_off <= symbol_table_opl_off && + symbol_table_opl_off <= props.size); + } + + // rjf: symbol table is valid -> is COFF OBJ + if(symbol_table_is_valid) + { + file_format = RB_FileFormat_COFF_OBJ; + } + + scratch_end(scratch); + } + + //- rjf: ELF magic -> ELF input + if(file_format == RB_FileFormat_Null) + { + U8 identifier_maybe[ELF_Identifier_Max] = {0}; + os_file_read(file, r1u64(0, sizeof(identifier_maybe)), identifier_maybe); + B32 is_elf_magic = (identifier_maybe[ELF_Identifier_Mag0] == 0x7f && + identifier_maybe[ELF_Identifier_Mag1] == 'E' && + identifier_maybe[ELF_Identifier_Mag2] == 'L' && + identifier_maybe[ELF_Identifier_Mag3] == 'F'); + if(is_elf_magic) + { + file_format = ELF_HdrIs64Bit(identifier_maybe) ? RB_FileFormat_ELF64 : RB_FileFormat_ELF32; + } + } + + //- rjf: RDI magic -> RDI input + if(file_format == RB_FileFormat_Null) + { + RDI_Header rdi_header_maybe = {0}; + os_file_read_struct(file, 0, &rdi_header_maybe); + if(rdi_header_maybe.magic == RDI_MAGIC_CONSTANT) + { + file_format = RB_FileFormat_RDI; + } + } + + os_file_close(file); + } + + ////////////////////////// + //- rjf: log file recognition + // + if(file_format != RB_FileFormat_Null) + { + log_infof("%S recognized as %S\n", n->string, rb_file_format_display_name_table[file_format]); + } + else + { + log_infof("%S was not recognized as a supported format.\n", n->string); + } + + ////////////////////////// + //- rjf: load recognized files + // + String8 file_data = {0}; + if(file_format != RB_FileFormat_Null) + { + file_data = os_data_from_file_path(arena, n->string); + } + + ////////////////////////// + //- rjf: PE format => generate new implicit path tasks for PDBs + // + if(file_format == RB_FileFormat_PE) + { + Temp scratch = scratch_begin(&arena, 1); + PE_BinInfo pe_bin_info = pe_bin_info_from_data(scratch.arena, file_data); + String8 raw_debug_dir = str8_substr(file_data, pe_bin_info.data_dir_franges[PE_DataDirectoryIndex_DEBUG]); + PE_DebugInfoList debug_dir = pe_debug_info_list_from_raw_debug_dir(scratch.arena, file_data, raw_debug_dir); + for(PE_DebugInfoNode *n = debug_dir.first; n != 0; n = n->next) + { + if(n->v.path.size != 0) + { + str8_list_push(arena, &input_file_path_tasks, n->v.path); + } + } + scratch_end(scratch); + } + + ////////////////////////// + //- rjf: ELF format => generate new implicit path tasks for debug files + // + if(file_format == RB_FileFormat_ELF32 || + file_format == RB_FileFormat_ELF64) + { + ELF_BinInfo elf = elf_bin_from_data(file_data); + ELF_GnuDebugLink debug_link = {0}; + if(elf_parse_debug_link(file_data, &elf, &debug_link) && + debug_link.path.size != 0) + { + str8_list_push(arena, &input_file_path_tasks, debug_link.path); + } + } + + ////////////////////////// + //- rjf: PE => check if contains DWARF + // + if(file_format == RB_FileFormat_PE) + { + Temp scratch = scratch_begin(&arena, 1); + PE_BinInfo pe_bin_info = pe_bin_info_from_data(scratch.arena, file_data); + String8 raw_section_table = str8_substr(file_data, pe_bin_info.section_table_range); + String8 string_table = str8_substr(file_data, pe_bin_info.string_table_range); + U64 section_count = raw_section_table.size / sizeof(COFF_SectionHeader); + COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_section_table.str; + if(dw_is_dwarf_present_coff_section_table(file_data, string_table, section_count, section_table)) + { + file_format_flags |= RB_FileFormatFlag_HasDWARF; + } + scratch_end(scratch); + } + + ////////////////////////// + //- rjf: ELF => check if contains DWARF + // + if(file_format == RB_FileFormat_ELF32 || + file_format == RB_FileFormat_ELF64) + { + Temp scratch = scratch_begin(&arena, 1); + ELF_BinInfo elf_bin = elf_bin_from_data(file_data); + if(dw_is_dwarf_present_elf_section_table(file_data, &elf_bin)) + { + file_format_flags |= RB_FileFormatFlag_HasDWARF; + } + scratch_end(scratch); + } + + ////////////////////////// + //- rjf: push to list + // + { + RB_File *f = push_array(arena, RB_File, 1); + f->format = file_format; + f->format_flags = file_format_flags; + f->path = n->string; + f->data = file_data; + RB_FileNode *file_n = push_array(arena, RB_FileNode, 1); + file_n->v = f; + SLLQueuePush(input_files.first, input_files.last, file_n); + input_files.count += 1; + } + } + } + + ////////////////////////////// + //- rjf: bucket input files by format + // + RB_FileList input_files_from_format_table[RB_FileFormat_COUNT] = {0}; + for(RB_FileNode *n = input_files.first; n != 0; n = n->next) + { + RB_FileNode *file_n = push_array(arena, RB_FileNode, 1); + file_n->v = n->v; + SLLQueuePush(input_files_from_format_table[n->v->format].first, input_files_from_format_table[n->v->format].last, file_n); + input_files_from_format_table[n->v->format].count += 1; + } + + ////////////////////////////// + //- rjf: unpack which kind of output we're producing, and to where + // + typedef enum OutputKind + { + OutputKind_Null, + OutputKind_RDI, + OutputKind_Dump, + OutputKind_Breakpad, + OutputKind_COUNT + } + OutputKind; + struct + { + String8 arg; + String8 title; + } + output_kind_info[] = + { + {str8_lit_comp(""), str8_lit_comp("")}, + {str8_lit_comp("rdi"), str8_lit_comp("RAD Debug Info (.rdi) Conversion")}, + {str8_lit_comp("dump"), str8_lit_comp("Textual Dumping")}, + {str8_lit_comp("breakpad"), str8_lit_comp("Breakpad Debug Info Conversion")}, + }; + OutputKind output_kind = OutputKind_Null; + String8 output_path = cmd_line_string(cmdline, str8_lit("out")); + { + //- rjf: user manually specified output kind + if(output_kind == OutputKind_Null) + { + for EachNonZeroEnumVal(OutputKind, k) + { + if(cmd_line_has_flag(cmdline, output_kind_info[k].arg)) + { + log_infof("User specified --%S; performing `%S`\n", output_kind_info[k].arg, output_kind_info[k].title); + output_kind = k; + break; + } + } + } + + //- rjf: we can infer from the user-specified output path + if(str8_match(str8_skip_last_dot(output_path), str8_lit("rdi"), StringMatchFlag_CaseInsensitive)) + { + output_kind = OutputKind_RDI; + log_infof("Output path has .rdi extension; performing `%S`\n", output_kind_info[output_kind].title); + } + else if(str8_match(str8_skip_last_dot(output_path), str8_lit("dump"), StringMatchFlag_CaseInsensitive) || + str8_match(str8_skip_last_dot(output_path), str8_lit("txt"), StringMatchFlag_CaseInsensitive)) + { + output_kind = OutputKind_Dump; + log_infof("Output path has .dump or .txt extension; performing `%S`\n", output_kind_info[output_kind].title); + } + else if(str8_match(str8_skip_last_dot(output_path), str8_lit("psym"), StringMatchFlag_CaseInsensitive) || + str8_match(str8_skip_last_dot(output_path), str8_lit("psyms"), StringMatchFlag_CaseInsensitive)) + { + output_kind = OutputKind_Breakpad; + log_infof("Output path has .psym or .psyms extension; performing `%S`\n", output_kind_info[output_kind].title); + } + } + + ////////////////////////////// + //- rjf: print help preamble + // + if(output_kind == OutputKind_Null || cmdline->inputs.node_count == 0) + { + fprintf(stderr, "%s\n", BUILD_TITLE); + fprintf(stderr, "%s\n\n", BUILD_VERSION_STRING_LITERAL); + if(output_kind != OutputKind_Null) + { + fprintf(stderr, "%.*s Help\n", str8_varg(output_kind_info[output_kind].title)); + fprintf(stderr, "To see top-level options for radbin, run the binary with no arguments.\n\n"); + } + fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); + } + + ////////////////////////////// + //- rjf: perform operation based on output kind + // + String8List output_blobs = {0}; + switch(output_kind) + { + //////////////////////////// + //- rjf: no output kind -> nothing to do. output help information to user + // + default: + case OutputKind_Null: + { + fprintf(stderr, "USAGE EXAMPLES\n\n"); + + fprintf(stderr, "radbin --rdi program.exe\n"); + fprintf(stderr, "Find the debug info for `program.exe`, if any, and converts it to RDI.\n\n"); + + fprintf(stderr, "radbin program.pdb --out:program.rdi\n"); + fprintf(stderr, "Converts `program.pdb` to RDI, and stores it in `program.rdi`.\n\n"); + + fprintf(stderr, "radbin --dump program.rdi\n"); + fprintf(stderr, "Outputs the textual dump of the debug information stored in `program.rdi`.\n\n"); + + fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); + + fprintf(stderr, "DESCRIPTION\n\n"); + fprintf(stderr, "This utility provides a number of operations relating to executable image and\n"); + fprintf(stderr, "debug information formats. It can convert debug information to the RAD Debug\n"); + fprintf(stderr, "Info (.rdi) format. It can also parse and dump textualized contents of several\n"); + fprintf(stderr, "formats, including PDB, PE, ELF, and RDI. It also supports converting debug\n"); + fprintf(stderr, "information to the textual Breakpad format.\n\n"); + + fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); + + fprintf(stderr, "ARGUMENTS\n\n"); + + fprintf(stderr, "--rdi Specifies that the utility should convert debug information\n"); + fprintf(stderr, " data to the RAD Debug Info (.rdi) format.\n\n"); + + fprintf(stderr, "--dump Specifies that the utility should dump textualized contents of\n"); + fprintf(stderr, " all input files.\n\n"); + + fprintf(stderr, "--breakpad Specifies that the utility should convert debug information\n"); + fprintf(stderr, " data to the textual Breakpad format.\n\n"); + + fprintf(stderr, "--out: Specifies the path to which output data should be written. If\n"); + fprintf(stderr, " not specified, the utility will choose a fallback. If dumping\n"); + fprintf(stderr, " textual contents, the utility will write to `stdout`. If\n"); + fprintf(stderr, " converting to another format, the utility will form a path by\n"); + fprintf(stderr, " changing the extension of input files accordingly.\n\n"); + + fprintf(stderr, "--deterministic Turns off all sources of non-determinism in generated output,\n"); + fprintf(stderr, " like build names, versions, and dates.\n\n"); + + fprintf(stderr, "--verbose Outputs all log information collected during execution.\n\n"); + + fprintf(stderr, "There are also operation-specific arguments. To see them, run this binary with\n"); + fprintf(stderr, "the operation selected, with no additional inputs (e.g. `radbin --rdi`).\n\n"); + }break; + + //////////////////////////// + //- rjf: RDI, Breakpad -> conversion based on inputs + // + case OutputKind_RDI: + case OutputKind_Breakpad: + { + //- rjf: no inputs => help + if(cmdline->inputs.node_count == 0) switch(output_kind) + { + default: + case OutputKind_RDI: + { + fprintf(stderr, "ARGUMENTS\n\n"); + + fprintf(stderr, "--compress Compresses the RDI file's contents.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "--only: Specifies that only the named subsets of debug\n"); + fprintf(stderr, " information should be generated. See below for\n"); + fprintf(stderr, " a list of valid debug info subset names.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "--omit: Specifies that the named subsets of debug\n"); + fprintf(stderr, " information should not be generated. See below\n"); + fprintf(stderr, " for a list of valid debug info subset names.\n"); + fprintf(stderr, "\n"); + + fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); + + fprintf(stderr, "RAD DEBUG INFO SUBSET NAMES\n\n"); +#define X(name, name_lower) fprintf(stderr, " - " #name_lower "\n"); + RDIM_Subset_XList +#undef X + }break; + case OutputKind_Breakpad: + { + fprintf(stderr, "All input files specified on the command line will be dumped. The following\n"); + fprintf(stderr, "formats are currently supported: PE, COFF, RDI, and ELF\n\n"); + } + } + + //- rjf: unpack subset flags + RDIM_SubsetFlags subset_flags = 0xffffffff; + switch(output_kind) + { + default:{}break; + case OutputKind_RDI: + { + String8List only_names = cmd_line_strings(cmdline, str8_lit("only")); + if(only_names.node_count != 0) + { + subset_flags = 0; + } + for(String8Node *n = only_names.first; n != 0; n = n->next) + { + if(0){} +#define X(name, name_lower) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { subset_flags |= RDIM_SubsetFlag_##name; } + RDIM_Subset_XList +#undef X + } + String8List omit_names = cmd_line_strings(cmdline, str8_lit("omit")); + for(String8Node *n = omit_names.first; n != 0; n = n->next) + { + if(0){} +#define X(name, name_lower) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { subset_flags &= ~RDIM_SubsetFlag_##name; } + RDIM_Subset_XList +#undef X + } + }break; + case OutputKind_Breakpad: + { + subset_flags = RDIM_SubsetFlag_All & ~(RDIM_SubsetFlag_Types|RDIM_SubsetFlag_UDTs); + }break; + } + + //- rjf: convert inputs to RDI info + B32 convert_done = 0; + RDIM_BakeParams bake_params = {0}; + { + //- rjf: PE inputs w/ DWARF, or ELF inputs => DWARF -> RDI conversion + if(!convert_done && + ((input_files_from_format_table[RB_FileFormat_PE].count != 0 && + input_files_from_format_table[RB_FileFormat_PE].first->v->format_flags & RB_FileFormatFlag_HasDWARF) || + (input_files_from_format_table[RB_FileFormat_ELF32].count != 0 || + input_files_from_format_table[RB_FileFormat_ELF64].count != 0))) + { + convert_done = 1; + log_infof("PEs w/ DWARF, or ELFs specified; producing RDI by converting DWARF data\n"); + + // rjf: convert + D2R_ConvertParams convert_params = {0}; + { + B32 got_exe = 0; + B32 got_dbg = 0; + if(!got_exe && !got_dbg) + { + for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_PE].first; n != 0; n = n->next) + { + if(n->v->format_flags & RB_FileFormatFlag_HasDWARF) + { + got_exe = 1; + got_dbg = 1; + convert_params.dbg_name = n->v->path; + convert_params.dbg_data = n->v->data; + convert_params.exe_name = n->v->path; + convert_params.exe_data = n->v->data; + convert_params.exe_kind = ExecutableImageKind_CoffPe; + break; + } + } + } + if(!got_exe) + { + for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF32].first; n != 0; n = n->next) + { + got_exe = 1; + convert_params.exe_name = n->v->path; + convert_params.exe_data = n->v->data; + convert_params.exe_kind = ExecutableImageKind_Elf32; + if(!(n->v->format_flags & RB_FileFormatFlag_HasDWARF)) + { + break; + } + } + } + if(!got_exe) + { + for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF64].first; n != 0; n = n->next) + { + got_exe = 1; + convert_params.exe_name = n->v->path; + convert_params.exe_data = n->v->data; + convert_params.exe_kind = ExecutableImageKind_Elf64; + if(!(n->v->format_flags & RB_FileFormatFlag_HasDWARF)) + { + break; + } + } + } + if(!got_dbg) + { + for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF32].first; n != 0; n = n->next) + { + if(n->v->format_flags & RB_FileFormatFlag_HasDWARF) + { + got_dbg = 1; + convert_params.dbg_name = n->v->path; + convert_params.dbg_data = n->v->data; + break; + } + } + } + if(!got_dbg) + { + for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF64].first; n != 0; n = n->next) + { + if(n->v->format_flags & RB_FileFormatFlag_HasDWARF) + { + got_dbg = 1; + convert_params.dbg_name = n->v->path; + convert_params.dbg_data = n->v->data; + break; + } + } + } + convert_params.subset_flags = subset_flags; + convert_params.deterministic = cmd_line_has_flag(cmdline, str8_lit("deterministic")); + } + ProfScope("convert") bake_params = d2r_convert(arena, async_root, &convert_params); + + // rjf: no output path? -> pick one based on debug + if(output_path.size == 0) + { + output_path = push_str8f(arena, "%S.rdi", str8_chop_last_dot(convert_params.dbg_name)); + } + } + + //- rjf: PDB inputs => PDB -> RDI conversion + if(!convert_done && + input_files_from_format_table[RB_FileFormat_PDB].count != 0) + { + convert_done = 1; + log_infof("PDBs specified; producing RDI by converting PDB data\n"); + + // rjf: get EXE/PDB file data + RB_File *exe_file = rb_file_list_first(&input_files_from_format_table[RB_FileFormat_PE]); + RB_File *pdb_file = rb_file_list_first(&input_files_from_format_table[RB_FileFormat_PDB]); + String8 exe_path = exe_file->path; + String8 pdb_path = pdb_file->path; + String8 exe_data = os_data_from_file_path(arena, exe_path); + String8 pdb_data = os_data_from_file_path(arena, pdb_path); + + // rjf: convert + P2R_ConvertParams convert_params = {0}; + { + convert_params.input_pdb_name = pdb_path; + convert_params.input_exe_name = exe_path; + convert_params.input_pdb_data = pdb_data; + convert_params.input_exe_data = exe_data; + convert_params.subset_flags = subset_flags; + convert_params.deterministic = cmd_line_has_flag(cmdline, str8_lit("deterministic")); + } + ProfScope("convert") bake_params = p2r_convert(arena, async_root, &convert_params); + + // rjf: no output path? -> pick one based on PDB + if(output_path.size == 0) switch(output_kind) + { + default:{}break; + case OutputKind_RDI: + { + output_path = push_str8f(arena, "%S.rdi", str8_chop_last_dot(convert_params.input_pdb_name)); + }break; + case OutputKind_Breakpad: + { + output_path = push_str8f(arena, "%S.psym", str8_chop_last_dot(convert_params.input_pdb_name)); + }break; + } + } + } + + //- rjf: no viable input paths + if(!convert_done && cmdline->inputs.node_count != 0) + { + log_user_errorf("Could not load debug info from the specified inputs. You must provide either a valid PDB file or an executable image (PE, ELF) file with DWARF debug info."); + } + + //- rjf: convert done => generate output + if(convert_done) switch(output_kind) + { + default:{}break; + + //- rjf: generate RDI blobs + case OutputKind_RDI: + { + // rjf: bake + RDIM_BakeResults bake_results = {0}; + ProfScope("bake") bake_results = rdim_bake(arena, async_root, &bake_params); + + // rjf: serialize + RDIM_SerializedSectionBundle serialized_section_bundle = {0}; + ProfScope("serialize") serialized_section_bundle = rdim_serialized_section_bundle_from_bake_results(&bake_results); + + // rjf: compress + RDIM_SerializedSectionBundle serialized_section_bundle__compressed = serialized_section_bundle; + if(cmd_line_has_flag(cmdline, str8_lit("compress"))) ProfScope("compress") + { + serialized_section_bundle__compressed = rdim_compress(arena, &serialized_section_bundle); + } + + // rjf: serialize + String8List blobs = rdim_file_blobs_from_section_bundle(arena, &serialized_section_bundle__compressed); + str8_list_concat_in_place(&output_blobs, &blobs); + }break; + + //- rjf: generate breakpad text + case OutputKind_Breakpad: + { + p2b_async_root = async_root; + String8List dump = {0}; + + //- rjf: kick off unit vmap baking + P2B_BakeUnitVMapIn bake_unit_vmap_in = {&bake_params.units}; + ASYNC_Task *bake_unit_vmap_task = async_task_launch(arena, p2b_bake_unit_vmap_work, .input = &bake_unit_vmap_in); + + //- rjf: kick off line-table baking + P2B_BakeLineTablesIn bake_line_tables_in = {&bake_params.line_tables}; + ASYNC_Task *bake_line_tables_task = async_task_launch(arena, p2b_bake_line_table_work, .input = &bake_line_tables_in); + + //- rjf: build unit -> line table idx array + U64 unit_count = bake_params.units.total_count; + U32 *unit_line_table_idxs = push_array(arena, U32, unit_count+1); + { + U64 dst_idx = 1; + for(RDIM_UnitChunkNode *n = bake_params.units.first; n != 0; n = n->next) + { + for(U64 n_idx = 0; n_idx < n->count; n_idx += 1, dst_idx += 1) + { + unit_line_table_idxs[dst_idx] = rdim_idx_from_line_table(n->v[n_idx].line_table); + } + } + } + + //- rjf: dump MODULE record + str8_list_pushf(arena, &dump, "MODULE windows x86_64 %I64x %S\n", bake_params.top_level_info.exe_hash, bake_params.top_level_info.exe_name); + + //- rjf: dump FILE records + ProfScope("dump FILE records") + { + for(RDIM_SrcFileChunkNode *n = bake_params.src_files.first; n != 0; n = n->next) + { + for(U64 idx = 0; idx < n->count; idx += 1) + { + U64 file_idx = rdim_idx_from_src_file(&n->v[idx]); + String8 src_path = n->v[idx].normal_full_path; + str8_list_pushf(arena, &dump, "FILE %I64u %S\n", file_idx, src_path); + } + } + } + + //- rjf: join unit vmap + ProfBegin("join unit vmap"); + RDIM_UnitVMapBakeResult *bake_unit_vmap_out = async_task_join_struct(bake_unit_vmap_task, RDIM_UnitVMapBakeResult); + RDI_VMapEntry *unit_vmap = bake_unit_vmap_out->vmap.vmap; + U32 unit_vmap_count = bake_unit_vmap_out->vmap.count; + ProfEnd(); + + //- rjf: join line tables + ProfBegin("join line table"); + RDIM_LineTableBakeResult *bake_line_tables_out = async_task_join_struct(bake_line_tables_task, RDIM_LineTableBakeResult); + ProfEnd(); + + //- rjf: kick off FUNC & line record dump tasks + P2B_DumpProcChunkIn *dump_proc_chunk_in = push_array(arena, P2B_DumpProcChunkIn, bake_params.procedures.chunk_count); + ASYNC_Task **dump_proc_chunk_tasks = push_array(arena, ASYNC_Task *, bake_params.procedures.chunk_count); + ProfScope("kick off FUNC & line record dump tasks") + { + U64 task_idx = 0; + for(RDIM_SymbolChunkNode *n = bake_params.procedures.first; n != 0; n = n->next, task_idx += 1) + { + dump_proc_chunk_in[task_idx].unit_vmap = unit_vmap; + dump_proc_chunk_in[task_idx].unit_vmap_count = unit_vmap_count; + dump_proc_chunk_in[task_idx].unit_line_table_idxs = unit_line_table_idxs; + dump_proc_chunk_in[task_idx].unit_count = unit_count; + dump_proc_chunk_in[task_idx].line_tables_bake = bake_line_tables_out; + dump_proc_chunk_in[task_idx].chunk = n; + dump_proc_chunk_tasks[task_idx] = async_task_launch(arena, p2b_dump_proc_chunk_work, .input = &dump_proc_chunk_in[task_idx]); + } + } + + //- rjf: join FUNC & line record dump tasks + ProfScope("join FUNC & line record dump tasks") + { + for(U64 idx = 0; idx < bake_params.procedures.chunk_count; idx += 1) + { + String8List *out = async_task_join_struct(dump_proc_chunk_tasks[idx], String8List); + str8_list_concat_in_place(&dump, out); + } + } + + str8_list_concat_in_place(&output_blobs, &dump); + }break; + } + }break; + + //////////////////////////// + //- rjf: dump -> textual dump of inputs + // + case OutputKind_Dump: + { + B32 deterministic = cmd_line_has_flag(cmdline, str8_lit("deterministic")); + + //- rjf: no inputs => help + if(cmdline->inputs.node_count == 0) + { + fprintf(stderr, "All input files specified on the command line will be dumped. Currently, only\n"); + fprintf(stderr, "RDI files are supported.\n\n"); + + fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); + + fprintf(stderr, "ARGUMENTS\n\n"); + + fprintf(stderr, "--only: Specifies that only the named subsets should\n"); + fprintf(stderr, " be dumped. See below for a list of valid\n"); + fprintf(stderr, " subset names.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "--omit: Specifies that the named subsets should not\n"); + fprintf(stderr, " be dumped. See below for a list of valid\n"); + fprintf(stderr, " subset names.\n"); + fprintf(stderr, "\n"); + + fprintf(stderr, "-------------------------------------------------------------------------------\n\n"); + + fprintf(stderr, "RAD DEBUG INFO SUBSET NAMES\n\n"); +#define X(name, name_lower, title) fprintf(stderr, " - " #name_lower "\n"); + RDI_DumpSubset_XList +#undef X + } + + //- rjf: unpack dump subset flags + RDI_DumpSubsetFlags rdi_dump_subset_flags = RDI_DumpSubsetFlag_All; + { + String8List only_names = cmd_line_strings(cmdline, str8_lit("only")); + if(only_names.node_count != 0) + { + rdi_dump_subset_flags = 0; + } + for(String8Node *n = only_names.first; n != 0; n = n->next) + { + if(0){} +#define X(name, name_lower, title) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { rdi_dump_subset_flags |= RDI_DumpSubsetFlag_##name; } + RDI_DumpSubset_XList +#undef X + } + String8List omit_names = cmd_line_strings(cmdline, str8_lit("omit")); + for(String8Node *n = omit_names.first; n != 0; n = n->next) + { + if(0){} +#define X(name, name_lower, title) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { rdi_dump_subset_flags &= ~RDI_DumpSubsetFlag_##name; } + RDI_DumpSubset_XList +#undef X + } + } + + //- rjf: dump input files in order + String8List dump = {0}; + for(RB_FileNode *n = input_files.first; n != 0; n = n->next) + { + RB_File *f = n->v; + str8_list_pushf(arena, &output_blobs, "# %S (%S)\n\n", deterministic ? str8_skip_last_slash(f->path) : f->path, f->format ? rb_file_format_display_name_table[f->format] : str8_lit("Unsupported format")); + switch(f->format) + { + default:{}break; + + //- rjf: RDI file + case RB_FileFormat_RDI: + { + RDI_Parsed rdi = {0}; + RDI_ParseStatus rdi_status = rdi_parse(f->data.str, f->data.size, &rdi); + String8 error = {0}; + switch(rdi_status) + { + default:{}break; + case RDI_ParseStatus_HeaderDoesNotMatch: {log_user_errorf("RDI parse failure: header does not match\n");}break; + case RDI_ParseStatus_UnsupportedVersionNumber:{log_user_errorf("RDI parse failure: unsupported version\n");}break; + case RDI_ParseStatus_InvalidDataSecionLayout: {log_user_errorf("RDI parse failure: invalid data section layout\n");}break; + case RDI_ParseStatus_MissingRequiredSection: {log_user_errorf("RDI parse failure: missing required section\n");}break; + case RDI_ParseStatus_Good: + { + String8List dump = rdi_dump_list_from_parsed(arena, &rdi, rdi_dump_subset_flags); + str8_list_concat_in_place(&output_blobs, &dump); + }break; + } + }break; + + //- rjf: COFF archive + case RB_FileFormat_COFF_Archive: + case RB_FileFormat_COFF_ThinArchive: + { + // TODO(rjf) + }break; + + //- rjf: COFF big OBJ + case RB_FileFormat_COFF_BigOBJ: + { + // TODO(rjf) + }break; + + //- rjf: COFF OBJ + case RB_FileFormat_COFF_OBJ: + { + // TODO(rjf) + }break; + + //- rjf: PE + case RB_FileFormat_PE: + { + // TODO(rjf) + }break; + } + } + + //- rjf: join with output + str8_list_concat_in_place(&output_blobs, &dump); + }break; + } + + ////////////////////////////// + //- rjf: write outputs + // + if(output_path.size != 0) ProfScope("write outputs [file]") + { + os_write_data_list_to_file_path(output_path, output_blobs); + log_infof("Results written to %S", output_path); + } + else ProfScope("write outputs [stdout]") + { + for(String8Node *n = output_blobs.first; n != 0; n = n->next) + { + for(U64 off = 0; off < n->string.size;) + { + U64 size_to_write = Min(n->string.size - off, GB(2)); + fwrite(n->string.str + off, size_to_write, 1, stdout); + off += size_to_write; + } + } + log_info(str8_lit("Results written to stdout")); + } + + ////////////////////////////// + //- rjf: write info & errors + // + LogScopeResult log_scope = log_scope_end(arena); + if(cmd_line_has_flag(cmdline, str8_lit("verbose")) && log_scope.strings[LogMsgKind_Info].size != 0) + { + String8List lines = wrapped_lines_from_string(arena, log_scope.strings[LogMsgKind_Info], 80, 80, 0); + for(String8Node *n = lines.first; n != 0; n = n->next) + { + fprintf(stderr, "%.*s\n", str8_varg(n->string)); + } + } + if(log_scope.strings[LogMsgKind_UserError].size != 0) + { + String8List lines = wrapped_lines_from_string(arena, log_scope.strings[LogMsgKind_UserError], 80, 80, 0); + for(String8Node *n = lines.first; n != 0; n = n->next) + { + fprintf(stderr, "%.*s\n", str8_varg(n->string)); + } + } +} diff --git a/src/radbin/radbin.h b/src/radbin/radbin.h new file mode 100644 index 00000000..fc98e130 --- /dev/null +++ b/src/radbin/radbin.h @@ -0,0 +1,53 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef RADBIN_H +#define RADBIN_H + +//////////////////////////////// +//~ rjf: Generated Code + +#include "radbin/generated/radbin.meta.h" + +//////////////////////////////// +//~ rjf: File Types + +typedef U32 RB_FileFormatFlags; +enum +{ + RB_FileFormatFlag_HasDWARF = (1<<0), +}; + +typedef struct RB_File RB_File; +struct RB_File +{ + RB_FileFormat format; + RB_FileFormatFlags format_flags; + String8 path; + String8 data; +}; + +typedef struct RB_FileNode RB_FileNode; +struct RB_FileNode +{ + RB_FileNode *next; + RB_File *v; +}; + +typedef struct RB_FileList RB_FileList; +struct RB_FileList +{ + RB_FileNode *first; + RB_FileNode *last; + U64 count; +}; + +read_only global RB_File rb_file_nil = {0}; +#define rb_file_list_first(list) ((list)->first ? (list)->first->v : &rb_file_nil) + +//////////////////////////////// +//~ rjf: Top-Level Entry Point + +internal void rb_entry_point(CmdLine *cmdline); + +#endif //RADBIN_H diff --git a/src/radbin/radbin.mdesk b/src/radbin/radbin.mdesk new file mode 100644 index 00000000..a729b554 --- /dev/null +++ b/src/radbin/radbin.mdesk @@ -0,0 +1,29 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +@table(name display_name) +RB_FileFormatTable: +{ + { PDB "PDB" } + { PE "PE" } + { COFF_OBJ "COFF (OBJ)" } + { COFF_BigOBJ "COFF (Big OBJ)" } + { COFF_Archive "COFF (Archive)" } + { COFF_ThinArchive "COFF (Thin Archive)" } + { ELF32 "ELF32" } + { ELF64 "ELF64" } + { RDI "RDI" } +} + +@enum RB_FileFormat: +{ + Null, + @expand(RB_FileFormatTable a) `$(a.name)`, + COUNT +} + +@data(String8) rb_file_format_display_name_table: +{ + `{0}`, + @expand(RB_FileFormatTable a) `str8_lit_comp("$(a.display_name)")`, +} diff --git a/src/radbin/radbin_main.c b/src/radbin/radbin_main.c new file mode 100644 index 00000000..776931e8 --- /dev/null +++ b/src/radbin/radbin_main.c @@ -0,0 +1,86 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//////////////////////////////// +//~ rjf: Build Options + +#define BUILD_TITLE "Epic Games Tools (R) RAD CLI Binary Utility" +#define BUILD_CONSOLE_INTERFACE 1 + +//////////////////////////////// +//~ rjf: Includes + +//- rjf: [lib] +#include "third_party/rad_lzb_simple/rad_lzb_simple.h" +#include "third_party/rad_lzb_simple/rad_lzb_simple.c" + +//- rjf: [h] +#include "base/base_inc.h" +#include "linker/hash_table.h" +#include "os/os_inc.h" +#include "path/path.h" +#include "async/async.h" +#include "rdi_format/rdi_format_local.h" +#include "rdi_make/rdi_make_local.h" +#include "coff/coff.h" +#include "coff/coff_parse.h" +#include "pe/pe.h" +#include "elf/elf.h" +#include "elf/elf_parse.h" +#include "codeview/codeview.h" +#include "codeview/codeview_parse.h" +#include "dwarf/dwarf.h" +#include "dwarf/dwarf_parse.h" +#include "dwarf/dwarf_coff.h" +#include "dwarf/dwarf_elf.h" +#include "msf/msf.h" +#include "msf/msf_parse.h" +#include "pdb/pdb.h" +#include "pdb/pdb_parse.h" +#include "pdb/pdb_stringize.h" +#include "rdi_from_coff/rdi_from_coff.h" +#include "rdi_from_elf/rdi_from_elf.h" +#include "rdi_from_pdb/rdi_from_pdb.h" +#include "rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.h" +#include "rdi_from_dwarf/rdi_from_dwarf.h" +#include "radbin/radbin.h" + +//- rjf: [c] +#include "base/base_inc.c" +#include "linker/hash_table.c" +#include "os/os_inc.c" +#include "path/path.c" +#include "async/async.c" +#include "rdi_format/rdi_format_local.c" +#include "rdi_make/rdi_make_local.c" +#include "coff/coff.c" +#include "coff/coff_parse.c" +#include "pe/pe.c" +#include "elf/elf.c" +#include "elf/elf_parse.c" +#include "codeview/codeview.c" +#include "codeview/codeview_parse.c" +#include "dwarf/dwarf.c" +#include "dwarf/dwarf_parse.c" +#include "dwarf/dwarf_coff.c" +#include "dwarf/dwarf_elf.c" +#include "msf/msf.c" +#include "msf/msf_parse.c" +#include "pdb/pdb.c" +#include "pdb/pdb_parse.c" +#include "pdb/pdb_stringize.c" +#include "rdi_from_coff/rdi_from_coff.c" +#include "rdi_from_elf/rdi_from_elf.c" +#include "rdi_from_pdb/rdi_from_pdb.c" +#include "rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.c" +#include "rdi_from_dwarf/rdi_from_dwarf.c" +#include "radbin/radbin.c" + +//////////////////////////////// +//~ rjf: Entry Point + +internal void +entry_point(CmdLine *cmdline) +{ + rb_entry_point(cmdline); +} diff --git a/src/radcon/radcon.c b/src/radcon/radcon.c index c66e40ea..55593b54 100644 --- a/src/radcon/radcon.c +++ b/src/radcon/radcon.c @@ -13,12 +13,12 @@ internal RC_Context rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl) { Temp scratch = scratch_begin(&arena, 1); - + if (cmdl->inputs.node_count > 2) { fprintf(stderr, "error: too many input files on the command line.\n"); os_abort(1); } - + B32 is_pe_present = 0; B32 is_pdb_present = 0; B32 is_elf_present = 0; @@ -31,7 +31,7 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl) String8 elf_data = {0}; String8 elf_debug_name = {0}; String8 elf_debug_data = {0}; - + // // Set typed inputs // @@ -71,7 +71,7 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl) } is_elf_debug_present = 1; } - + // // Pick conversion driver // @@ -87,18 +87,18 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl) os_abort(1); } } - + // // Load inputs // for (String8Node *input_n = cmdl->inputs.first; input_n != 0; input_n = input_n->next) { String8 input_data = os_data_from_file_path(arena, input_n->string); - + if (input_data.size == 0) { fprintf(stderr, "unable to read input %.*s\n", str8_varg(input_n->string)); os_abort(1); } - + if (pe_check_magic(input_data)) { if (is_pe_present) { fprintf(stderr, "error: too many PE files are specified on the command line\n"); @@ -139,7 +139,7 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl) fprintf(stderr, "error: unknown file format %.*s\n", str8_varg(input_n->string)); } } - + // // Validate input combos // @@ -159,54 +159,54 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl) } os_abort(1); } - + if (is_pe_present && (is_elf_present || is_elf_debug_present)) { fprintf(stderr, "error: command line has too many image types specified.\n"); os_abort(1); } - - - ImageType image = Image_Null; + + + ExecutableImageKind image = ExecutableImageKind_Null; String8 image_name = {0}; String8 image_data = {0}; String8 debug_name = {0}; String8 debug_data = {0}; - + B32 check_guid = 0; Guid pe_pdb_guid = {0}; - + B32 elf_has_debug_link = 0; ELF_GnuDebugLink debug_link = {0}; - + // // Input has PE/COFF // if (is_pe_present) { - image = Image_CoffPe; + image = ExecutableImageKind_CoffPe; image_name = pe_name; image_data = pe_data; - + PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, pe_data); String8 raw_debug_dir = str8_substr(pe_data, pe.data_dir_franges[PE_DataDirectoryIndex_DEBUG]); - PE_DebugInfoList debug_dir = pe_parse_debug_directory(scratch.arena, pe_data, raw_debug_dir); + PE_DebugInfoList debug_dir = pe_debug_info_list_from_raw_debug_dir(scratch.arena, pe_data, raw_debug_dir); for (PE_DebugInfoNode *debug_n = debug_dir.first; debug_n != 0; debug_n = debug_n->next) { PE_DebugInfo *debug = &debug_n->v; if (debug->header.type == PE_DebugDirectoryType_CODEVIEW) { if (debug->u.codeview.magic == PE_CODEVIEW_PDB70_MAGIC) { check_guid = 1; pe_pdb_guid = debug->u.codeview.pdb70.header.guid; - + if (!is_pdb_present) { pdb_name = debug->u.codeview.pdb70.path; pdb_data = rc_data_from_file_path(arena, pdb_name); is_pdb_present = 1; } - + break; } } } - + if (driver == RC_Driver_Null || driver == RC_Driver_Dwarf) { PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, pe_data); String8 raw_section_table = str8_substr(pe_data, pe.section_table_range); @@ -224,19 +224,19 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl) } } } - + if (is_elf_present || is_elf_debug_present) { if (driver != RC_Driver_Null && driver != RC_Driver_Dwarf) { fprintf(stderr, "error: ELF inputs are only supported when using DWARF driver.\n"); os_abort(1); } - + // // Load image ELF // ELF_BinInfo elf = elf_bin_from_data(elf_data); B32 has_elf_dwarf = dw_is_dwarf_present_elf_section_table(elf_data, &elf); - + // // ELF doesn't have debug info and no .debug was specified on command line, // try to load .debug via debug link @@ -248,54 +248,54 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl) elf_debug_data = rc_data_from_file_path(arena, debug_link.path); is_elf_debug_present = 1; } - + // // Load .debug ELF // ELF_BinInfo elf_debug = elf_bin_from_data(elf_debug_data); B32 has_elf_debug_dwarf = dw_is_dwarf_present_elf_section_table(elf_debug_data, &elf_debug); - + // // Input is image ELF and .debug ELF // B32 is_split_elf = is_elf_present && is_elf_debug_present && !has_elf_dwarf && has_elf_debug_dwarf; if (is_split_elf) { driver = RC_Driver_Dwarf; - image = ELF_HdrIs64Bit(elf.hdr.e_ident) ? Image_Elf64 : Image_Elf32; + image = ELF_HdrIs64Bit(elf.hdr.e_ident) ? ExecutableImageKind_Elf64 : ExecutableImageKind_Elf32; image_name = elf_name; image_data = elf_data; debug_name = elf_debug_name; debug_data = elf_debug_data; goto driver_found; } - + // // Input ELF is image with debug info // B32 is_monolithic_elf = is_elf_present && !is_elf_debug_present && has_elf_dwarf; if (is_monolithic_elf) { driver = RC_Driver_Dwarf; - image = ELF_HdrIs64Bit(elf.hdr.e_ident) ? Image_Elf64 : Image_Elf32; + image = ELF_HdrIs64Bit(elf.hdr.e_ident) ? ExecutableImageKind_Elf64 : ExecutableImageKind_Elf32; image_name = elf_name; image_data = elf_data; debug_name = elf_name; debug_data = elf_data; goto driver_found; } - + // // Input ELF is .debug // B32 is_debug_elf = !is_elf_present && is_elf_debug_present && has_elf_debug_dwarf; if (is_debug_elf) { driver = RC_Driver_Dwarf; - image = ELF_HdrIs64Bit(elf_debug.hdr.e_ident) ? Image_Elf64 : Image_Elf32; + image = ELF_HdrIs64Bit(elf_debug.hdr.e_ident) ? ExecutableImageKind_Elf64 : ExecutableImageKind_Elf32; debug_name = elf_debug_name; debug_data = elf_debug_data; goto driver_found; } } - + // // Input is PDB // @@ -312,9 +312,9 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl) InvalidPath; } } - + driver_found:; - + // // Handle -out param // @@ -332,8 +332,8 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl) out_name = path_replace_file_extension(arena, debug_name, str8_lit("rdi")); } } - - + + // // Validate driver input // @@ -342,8 +342,8 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl) fprintf(stderr, "error: DWARF is an invalid input for PDB driver\n"); os_abort(1); } - - + + RC_Context ctx = {0}; ctx.driver = driver; ctx.image = image; @@ -352,23 +352,23 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl) ctx.debug_name = debug_name; ctx.debug_data = debug_data; ctx.flags = RC_Flag_Strings| - RC_Flag_IndexRuns| - RC_Flag_BinarySections| - RC_Flag_Units| - RC_Flag_Procedures| - RC_Flag_GlobalVariables| - RC_Flag_ThreadVariables| - RC_Flag_Scopes| - RC_Flag_Locals| - RC_Flag_Types| - RC_Flag_UDTs| - RC_Flag_LineInfo| - RC_Flag_GlobalVariableNameMap| - RC_Flag_ThreadVariableNameMap| - RC_Flag_ProcedureNameMap| - RC_Flag_TypeNameMap| - RC_Flag_LinkNameProcedureNameMap| - RC_Flag_NormalSourcePathNameMap; + RC_Flag_IndexRuns| + RC_Flag_BinarySections| + RC_Flag_Units| + RC_Flag_Procedures| + RC_Flag_GlobalVariables| + RC_Flag_ThreadVariables| + RC_Flag_Scopes| + RC_Flag_Locals| + RC_Flag_Types| + RC_Flag_UDTs| + RC_Flag_LineInfo| + RC_Flag_GlobalVariableNameMap| + RC_Flag_ThreadVariableNameMap| + RC_Flag_ProcedureNameMap| + RC_Flag_TypeNameMap| + RC_Flag_LinkNameProcedureNameMap| + RC_Flag_NormalSourcePathNameMap; if (check_guid) { ctx.flags |= RC_Flag_CheckPdbGuid; ctx.guid = pe_pdb_guid; @@ -378,7 +378,7 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl) ctx.debug_link = debug_link; } ctx.out_name = out_name; - + scratch_end(scratch); return ctx; } @@ -387,40 +387,40 @@ internal String8List rc_run(Arena *arena, RC_Context *rc) { Temp scratch = scratch_begin(&arena, 1); - + ProfBegin("Convert"); RDIM_LocalState *local_state = rdim_local_init(); RDIM_BakeParams *convert2bake = 0; switch (rc->driver) { - case RC_Driver_Null: break; - case RC_Driver_Dwarf: convert2bake = d2r_convert(scratch.arena, local_state, rc); break; - case RC_Driver_Pdb: convert2bake = p2r_convert(scratch.arena, local_state, rc); break; + case RC_Driver_Null: break; + case RC_Driver_Dwarf: convert2bake = d2r_convert(scratch.arena, local_state, rc); break; + case RC_Driver_Pdb: convert2bake = p2r_convert(scratch.arena, local_state, rc); break; } ProfEnd(); - + if (rc->errors.node_count) { NotImplemented; } - + ProfBegin("Bake"); RDIM_BakeResults bake2srlz = rdim_bake(local_state, convert2bake); ProfEnd(); - + ProfBegin("Serialize Bake"); RDIM_SerializedSectionBundle srlz2file = rdim_serialized_section_bundle_from_bake_results(&bake2srlz); ProfEnd(); - + RDIM_SerializedSectionBundle srlz2file_compressed = srlz2file; if (rc->flags & RC_Flag_Compress) { ProfBegin("Compress"); srlz2file_compressed = rdim_compress(scratch.arena, &srlz2file); ProfEnd(); } - + ProfBegin("Serialize"); String8List raw_rdi = rdim_file_blobs_from_section_bundle(scratch.arena, &srlz2file_compressed); ProfEnd(); - + scratch_end(scratch); return raw_rdi; } @@ -456,25 +456,25 @@ rc_main(CmdLine *cmdl) fprintf(stderr, " -driver: Sets converter for debug info\n"); } else { Temp scratch = scratch_begin(0,0); - + // make converter context RC_Context rc = rc_context_from_cmd_line(scratch.arena, cmdl); - + // make RDI from context String8List raw_rdi = rc_run(scratch.arena, &rc); - + // output RDI if (rc.errors.node_count == 0) { if (!os_write_data_list_to_file_path(rc.out_name, raw_rdi)) { str8_list_pushf(scratch.arena, &rc.errors, "no write access to path %.*s", str8_varg(rc.out_name)); } } - + // report any errors for (String8Node *error_n = rc.errors.first; error_n != 0; error_n = error_n->next) { fprintf(stderr, "error: %.*s\n", str8_varg(error_n->string)); } - + scratch_end(scratch); } } diff --git a/src/radcon/radcon.h b/src/radcon/radcon.h index 95631068..06458d85 100644 --- a/src/radcon/radcon.h +++ b/src/radcon/radcon.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADCON_H @@ -42,7 +42,7 @@ typedef enum typedef struct RC_Context { - ImageType image; + ExecutableImageKind image; RC_Driver driver; String8 image_name; String8 image_data; @@ -63,4 +63,4 @@ internal String8 rc_rdi_from_cmd_line(Arena *arena, CmdLine *cmdl); internal void rc_main(CmdLine *cmdl); #endif // RADCON_H - + diff --git a/src/radcon/radcon_coff.c b/src/radcon/radcon_coff.c index 08f40a4a..7ce5b4bb 100644 --- a/src/radcon/radcon_coff.c +++ b/src/radcon/radcon_coff.c @@ -1,37 +1,37 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal RDI_Arch c2r_rdi_arch_from_coff_machine(COFF_MachineType machine) { switch (machine) { - case COFF_MachineType_X86: return RDI_Arch_X86; - case COFF_MachineType_X64: return RDI_Arch_X64; - - case COFF_MachineType_Unknown: - case COFF_MachineType_Am33: - case COFF_MachineType_Arm: - case COFF_MachineType_Arm64: - case COFF_MachineType_ArmNt: - case COFF_MachineType_Ebc: - case COFF_MachineType_Ia64: - case COFF_MachineType_M32R: - case COFF_MachineType_Mips16: - case COFF_MachineType_MipsFpu: - case COFF_MachineType_MipsFpu16: - case COFF_MachineType_PowerPc: - case COFF_MachineType_PowerPcFp: - case COFF_MachineType_R4000: - case COFF_MachineType_RiscV32: - case COFF_MachineType_RiscV64: - case COFF_MachineType_Sh3: - case COFF_MachineType_Sh3Dsp: - case COFF_MachineType_Sh4: - case COFF_MachineType_Sh5: - case COFF_MachineType_Thumb: - case COFF_MachineType_WceMipsV2: + case COFF_MachineType_X86: return RDI_Arch_X86; + case COFF_MachineType_X64: return RDI_Arch_X64; + + case COFF_MachineType_Unknown: + case COFF_MachineType_Am33: + case COFF_MachineType_Arm: + case COFF_MachineType_Arm64: + case COFF_MachineType_ArmNt: + case COFF_MachineType_Ebc: + case COFF_MachineType_Ia64: + case COFF_MachineType_M32R: + case COFF_MachineType_Mips16: + case COFF_MachineType_MipsFpu: + case COFF_MachineType_MipsFpu16: + case COFF_MachineType_PowerPc: + case COFF_MachineType_PowerPcFp: + case COFF_MachineType_R4000: + case COFF_MachineType_RiscV32: + case COFF_MachineType_RiscV64: + case COFF_MachineType_Sh3: + case COFF_MachineType_Sh3Dsp: + case COFF_MachineType_Sh4: + case COFF_MachineType_Sh5: + case COFF_MachineType_Thumb: + case COFF_MachineType_WceMipsV2: NotImplemented; - default: + default: return RDI_Arch_NULL; } } @@ -59,13 +59,13 @@ internal RDIM_BinarySectionList c2r_rdi_binary_sections_from_coff_sections(Arena *arena, String8 image_data, String8 string_table, U64 sectab_count, COFF_SectionHeader *sectab) { ProfBeginFunction(); - + RDIM_BinarySectionList binary_sections = {0}; - + for (U64 isec = 0; isec < sectab_count; ++isec) { COFF_SectionHeader *coff_sec = §ab[isec]; RDIM_BinarySection *sec = rdim_binary_section_list_push(arena, &binary_sections); - + sec->name = coff_name_from_section_header(string_table, coff_sec); sec->flags = c2r_rdi_binary_section_flags_from_coff_section_flags(coff_sec->flags); sec->voff_first = coff_sec->voff; @@ -73,7 +73,7 @@ c2r_rdi_binary_sections_from_coff_sections(Arena *arena, String8 image_data, Str sec->foff_first = coff_sec->foff; sec->foff_opl = coff_sec->foff + coff_sec->fsize; } - + ProfEnd(); return binary_sections; } diff --git a/src/radcon/radcon_coff.h b/src/radcon/radcon_coff.h index 252874fd..1b29c820 100644 --- a/src/radcon/radcon_coff.h +++ b/src/radcon/radcon_coff.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADCON_COFF_H diff --git a/src/radcon/radcon_dwarf.c b/src/radcon/radcon_dwarf.c index e2b6af54..06ed7627 100644 --- a/src/radcon/radcon_dwarf.c +++ b/src/radcon/radcon_dwarf.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) // TODO: @@ -35,10 +35,10 @@ internal RDI_RegCode d2r_rdi_reg_from_dw_reg_code(Arch arch, U64 reg_code) { switch (arch) { - case Arch_Null: return 0; - case Arch_x64: return d2r_rdi_reg_from_dw_reg_code_x64(reg_code); - case Arch_x86: return d2r_rdi_reg_from_dw_reg_code_x86(reg_code); - default: InvalidPath; + case Arch_Null: return 0; + case Arch_x64: return d2r_rdi_reg_from_dw_reg_code_x64(reg_code); + case Arch_x86: return d2r_rdi_reg_from_dw_reg_code_x86(reg_code); + default: InvalidPath; } return 0; } @@ -68,21 +68,21 @@ internal RDIM_Type * d2r_type_from_attrib(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { RDIM_Type *type = 0; - + // find attrib DW_Attrib *attrib = dw_attrib_from_tag(input, cu, tag, kind); - + // does tag have this attribute? if (attrib->attrib_kind == kind) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); - + if (value_class == DW_AttribClass_Reference) { // resolve reference DW_Reference ref = dw_ref_from_attrib_ptr(input, cu, attrib); - + // TODO: support for external compile unit references AssertAlways(ref.cu == cu); - + // find or create type type = d2r_find_or_create_type_from_offset(arena, type_table, ref.info_off); } else { @@ -91,7 +91,7 @@ d2r_type_from_attrib(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, D } else if (attrib->attrib_kind == DW_Attrib_Null) { type = rdim_builtin_type_from_kind(*type_table->types, RDI_TypeKind_NULL); } - + return type; } @@ -100,7 +100,7 @@ d2r_range_list_from_tag(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 imag { // collect non-contiguous range Rng1U64List ranges = dw_rnglist_from_attrib(arena, input, cu, tag, DW_Attrib_Ranges); - + // debase ranges for (Rng1U64Node *range_n = ranges.first; range_n != 0; range_n = range_n->next) { // TODO: error handling @@ -109,13 +109,13 @@ d2r_range_list_from_tag(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 imag range_n->v.min -= image_base; range_n->v.max -= image_base; } - + // collect contiguous range DW_Attrib *lo_pc_attrib = dw_attrib_from_tag(input, cu, tag, DW_Attrib_LowPc); DW_Attrib *hi_pc_attrib = dw_attrib_from_tag(input, cu, tag, DW_Attrib_HighPc); if (lo_pc_attrib->attrib_kind != DW_Attrib_Null && hi_pc_attrib->attrib_kind != DW_Attrib_Null) { U64 lo_pc = dw_address_from_attrib_ptr(input, cu, lo_pc_attrib); - + U64 hi_pc; DW_AttribClass hi_pc_class = dw_value_class_from_attrib(cu, hi_pc_attrib); if (hi_pc_class == DW_AttribClass_Address) { @@ -126,17 +126,17 @@ d2r_range_list_from_tag(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 imag } else { AssertAlways(!"undefined attrib encoding"); } - + // TODO: error handling AssertAlways(lo_pc >= image_base); AssertAlways(hi_pc >= image_base); AssertAlways(lo_pc <= hi_pc); - + U64 lo_voff = lo_pc - image_base; U64 hi_voff = hi_pc - image_base; rng1u64_list_push(arena, &ranges, rng_1u64(lo_voff, hi_voff)); } - + return ranges; } @@ -144,7 +144,7 @@ internal RDIM_Type ** d2r_collect_proc_params(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_TagNode *cur_node, U64 *param_count_out) { Temp scratch = scratch_begin(&arena, 1); - + RDIM_TypeList list = {0}; B32 has_vargs = 0; for (DW_TagNode *i = cur_node->first_child; i != 0; i = i->sibling) { @@ -157,18 +157,18 @@ d2r_collect_proc_params(Arena *arena, D2R_TypeTable *type_table, DW_Input *input has_vargs = 1; } } - + if (has_vargs) { RDIM_TypeNode *n = push_array(scratch.arena, RDIM_TypeNode, 1); n->v = type_table->varg_type; SLLQueuePush(list.first, list.last, n); ++list.count; } - + // collect params *param_count_out = list.count; RDIM_Type **params = rdim_array_from_type_list(arena, list); - + scratch_end(scratch); return params; } @@ -178,10 +178,10 @@ d2r_unsigned_type_kind_from_size(U64 byte_size) { RDI_TypeKind result = RDI_TypeKind_NULL; switch (byte_size) { - case 1: result = RDI_TypeKind_U8; break; - case 2: result = RDI_TypeKind_U16; break; - case 4: result = RDI_TypeKind_U32; break; - case 8: result = RDI_TypeKind_U64; break; + case 1: result = RDI_TypeKind_U8; break; + case 2: result = RDI_TypeKind_U16; break; + case 4: result = RDI_TypeKind_U32; break; + case 8: result = RDI_TypeKind_U64; break; } return result; } @@ -191,10 +191,10 @@ d2r_signed_type_kind_from_size(U64 byte_size) { RDI_TypeKind result = RDI_TypeKind_NULL; switch (byte_size) { - case 1: result = RDI_TypeKind_S8; break; - case 2: result = RDI_TypeKind_S16; break; - case 4: result = RDI_TypeKind_S32; break; - case 8: result = RDI_TypeKind_S64; break; + case 1: result = RDI_TypeKind_S8; break; + case 2: result = RDI_TypeKind_S16; break; + case 4: result = RDI_TypeKind_S32; break; + case 8: result = RDI_TypeKind_S64; break; } return result; } @@ -203,37 +203,37 @@ internal RDI_EvalTypeGroup d2r_type_group_from_type_kind(RDI_TypeKind x) { switch (x) { - case RDI_TypeKind_NULL: - case RDI_TypeKind_Void: - case RDI_TypeKind_Handle: + case RDI_TypeKind_NULL: + case RDI_TypeKind_Void: + case RDI_TypeKind_Handle: break; - case RDI_TypeKind_UChar8: - case RDI_TypeKind_UChar16: - case RDI_TypeKind_UChar32: - case RDI_TypeKind_U8: - case RDI_TypeKind_U16: - case RDI_TypeKind_U32: - case RDI_TypeKind_U64: - case RDI_TypeKind_U128: - case RDI_TypeKind_U256: - case RDI_TypeKind_U512: + case RDI_TypeKind_UChar8: + case RDI_TypeKind_UChar16: + case RDI_TypeKind_UChar32: + case RDI_TypeKind_U8: + case RDI_TypeKind_U16: + case RDI_TypeKind_U32: + case RDI_TypeKind_U64: + case RDI_TypeKind_U128: + case RDI_TypeKind_U256: + case RDI_TypeKind_U512: return RDI_EvalTypeGroup_U; - case RDI_TypeKind_Char8: - case RDI_TypeKind_Char16: - case RDI_TypeKind_Char32: - case RDI_TypeKind_S8: - case RDI_TypeKind_S16: - case RDI_TypeKind_S32: - case RDI_TypeKind_S64: - case RDI_TypeKind_S128: - case RDI_TypeKind_S256: - case RDI_TypeKind_S512: + case RDI_TypeKind_Char8: + case RDI_TypeKind_Char16: + case RDI_TypeKind_Char32: + case RDI_TypeKind_S8: + case RDI_TypeKind_S16: + case RDI_TypeKind_S32: + case RDI_TypeKind_S64: + case RDI_TypeKind_S128: + case RDI_TypeKind_S256: + case RDI_TypeKind_S512: return RDI_EvalTypeGroup_S; - case RDI_TypeKind_F32: + case RDI_TypeKind_F32: return RDI_EvalTypeGroup_F32; - case RDI_TypeKind_F64: + case RDI_TypeKind_F64: return RDI_EvalTypeGroup_F64; - default: InvalidPath; + default: InvalidPath; } return RDI_EvalTypeGroup_Other; } @@ -250,569 +250,569 @@ d2r_bytecode_from_expression(Arena *arena, B32 *is_addr_out) { Temp scratch = scratch_begin(&arena, 1); - + RDIM_EvalBytecode bc = {0}; - + *is_addr_out = 0; - + struct Frame { struct Frame *next; RDI_EvalTypeGroup value_type; }; struct Frame *stack = 0; #define push_of_type(type) do { \ - struct Frame *f = push_array(scratch.arena, struct Frame, 1); \ - f->value_type = d2r_type_group_from_type_kind(type); \ - SLLStackPush(stack, f); \ +struct Frame *f = push_array(scratch.arena, struct Frame, 1); \ +f->value_type = d2r_type_group_from_type_kind(type); \ +SLLStackPush(stack, f); \ } while (0) #define pop_type() stack->value_type; SLLStackPop(stack) #define peek_type() stack->value_type - - + + RDI_TypeKind addr_type_kind = RDI_TypeKind_NULL; if (address_size == 4) { addr_type_kind = RDI_TypeKind_U32; } else if (address_size == 8) { addr_type_kind = RDI_TypeKind_U64; } - - + + for (U64 cursor = 0; cursor < expr.size; ) { U8 op = 0; cursor += str8_deserial_read_struct(expr, cursor, &op); - + U64 size_param; switch (op) { - case DW_ExprOp_Lit0: case DW_ExprOp_Lit1: case DW_ExprOp_Lit2: - case DW_ExprOp_Lit3: case DW_ExprOp_Lit4: case DW_ExprOp_Lit5: - case DW_ExprOp_Lit6: case DW_ExprOp_Lit7: case DW_ExprOp_Lit8: - case DW_ExprOp_Lit9: case DW_ExprOp_Lit10: case DW_ExprOp_Lit11: - case DW_ExprOp_Lit12: case DW_ExprOp_Lit13: case DW_ExprOp_Lit14: - case DW_ExprOp_Lit15: case DW_ExprOp_Lit16: case DW_ExprOp_Lit17: - case DW_ExprOp_Lit18: case DW_ExprOp_Lit19: case DW_ExprOp_Lit20: - case DW_ExprOp_Lit21: case DW_ExprOp_Lit22: case DW_ExprOp_Lit23: - case DW_ExprOp_Lit24: case DW_ExprOp_Lit25: case DW_ExprOp_Lit26: - case DW_ExprOp_Lit27: case DW_ExprOp_Lit28: case DW_ExprOp_Lit29: - case DW_ExprOp_Lit30: case DW_ExprOp_Lit31: { - U64 lit = op - DW_ExprOp_Lit0; - - rdim_bytecode_push_uconst(arena, &bc, lit); - push_of_type(RDI_TypeKind_U64); - } break; - - case DW_ExprOp_Const1U: { - U8 val = 0; - cursor += str8_deserial_read_struct(expr, cursor, &val); - - rdim_bytecode_push_uconst(arena, &bc, val); - push_of_type(RDI_TypeKind_U8); - } break; - case DW_ExprOp_Const2U: { - U16 val = 0; - cursor += str8_deserial_read_struct(expr, cursor, &val); - - rdim_bytecode_push_uconst(arena, &bc, val); - push_of_type(RDI_TypeKind_U16); - } break; - case DW_ExprOp_Const4U: { - U32 val = 0; - cursor += str8_deserial_read_struct(expr, cursor, &val); - - rdim_bytecode_push_uconst(arena, &bc, val); - push_of_type(RDI_TypeKind_U32); - } break; - case DW_ExprOp_Const8U: { - U64 val = 0; - cursor += str8_deserial_read_struct(expr, cursor, &val); - - rdim_bytecode_push_uconst(arena, &bc, val); - push_of_type(RDI_TypeKind_U64); - } break; - - case DW_ExprOp_Const1S: { - S8 val = 0; - cursor += str8_deserial_read_struct(expr, cursor, &val); - - rdim_bytecode_push_sconst(arena, &bc, val); - push_of_type(RDI_TypeKind_S8); - } break; - case DW_ExprOp_Const2S: { - S16 val = 0; - cursor += str8_deserial_read_struct(expr, cursor, &val); - - rdim_bytecode_push_sconst(arena, &bc, val); - push_of_type(RDI_TypeKind_S16); - } break; - case DW_ExprOp_Const4S: { - S32 val = 0; - cursor += str8_deserial_read_struct(expr, cursor, &val); - - rdim_bytecode_push_sconst(arena, &bc, val); - push_of_type(RDI_TypeKind_S32); - } break; - case DW_ExprOp_Const8S: { - S64 val = 0; - cursor += str8_deserial_read_struct(expr, cursor, &val); - - rdim_bytecode_push_sconst(arena, &bc, val); - push_of_type(RDI_TypeKind_S64); - } break; - - case DW_ExprOp_ConstU: { - U64 val = 0; - cursor += str8_deserial_read_uleb128(expr, cursor, &val); - - rdim_bytecode_push_uconst(arena, &bc, val); - push_of_type(RDI_TypeKind_U64); - } break; - - case DW_ExprOp_ConstS: { - S64 val = 0; - cursor += str8_deserial_read_sleb128(expr, cursor, &val); - - rdim_bytecode_push_sconst(arena, &bc, val); - push_of_type(RDI_TypeKind_S64); - } break; - - case DW_ExprOp_Addr: { - U64 addr = 0; - cursor += str8_deserial_read(expr, cursor, &addr, address_size, address_size); - if (addr >= image_base) { - U64 voff = addr - image_base; - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_ModuleOff, voff); - push_of_type(addr_type_kind); - } else { - // TODO: error handling - AssertAlways(!"unable to relocate address"); - } - - *is_addr_out = 1; - } break; - - case DW_ExprOp_Reg0: case DW_ExprOp_Reg1: case DW_ExprOp_Reg2: - case DW_ExprOp_Reg3: case DW_ExprOp_Reg4: case DW_ExprOp_Reg5: - case DW_ExprOp_Reg6: case DW_ExprOp_Reg7: case DW_ExprOp_Reg8: - case DW_ExprOp_Reg9: case DW_ExprOp_Reg10: case DW_ExprOp_Reg11: - case DW_ExprOp_Reg12: case DW_ExprOp_Reg13: case DW_ExprOp_Reg14: - case DW_ExprOp_Reg15: case DW_ExprOp_Reg16: case DW_ExprOp_Reg17: - case DW_ExprOp_Reg18: case DW_ExprOp_Reg19: case DW_ExprOp_Reg20: - case DW_ExprOp_Reg21: case DW_ExprOp_Reg22: case DW_ExprOp_Reg23: - case DW_ExprOp_Reg24: case DW_ExprOp_Reg25: case DW_ExprOp_Reg26: - case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29: - case DW_ExprOp_Reg30: case DW_ExprOp_Reg31: { - U64 reg_code_dw = op - DW_ExprOp_Reg0; - U64 reg_size = dw_reg_size_from_code(arch, reg_code_dw); - U64 reg_pos = dw_reg_pos_from_code(arch, reg_code_dw); - - RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); - U32 regread_param = RDI_EncodeRegReadParam(reg_code_rdi, reg_size, reg_pos); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegRead, regread_param); - push_of_type(d2r_unsigned_type_kind_from_size(reg_size)); - } break; - - case DW_ExprOp_RegX: { - U64 reg_code_dw = 0; - cursor += str8_deserial_read_uleb128(expr, cursor, ®_code_dw); - - U64 reg_size = dw_reg_size_from_code(arch, reg_code_dw); - U64 reg_pos = dw_reg_pos_from_code(arch, reg_code_dw); - - RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); - U32 regread_param = RDI_EncodeRegReadParam(reg_code_rdi, reg_size, reg_pos); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegRead, regread_param); - push_of_type(d2r_unsigned_type_kind_from_size(reg_size)); - - *is_addr_out = 1; - } break; - - case DW_ExprOp_ImplicitValue: { - U64 val_size = 0; - String8 val = {0}; - cursor += str8_deserial_read_uleb128(expr, cursor, &val_size); - cursor += str8_deserial_read_block(expr, cursor, val_size, &val); - if (val.size <= sizeof(U64)) { - U64 val64 = 0; - MemoryCopy(&val64, val.str, val.size); - - rdim_bytecode_push_uconst(arena, &bc, val64); - push_of_type(d2r_unsigned_type_kind_from_size(val_size)); - } else { - // TODO: currenlty no way to encode string in RDIM_EvalBytecodeOp - NotImplemented; - } - } break; - - case DW_ExprOp_Piece: { - U64 piece_byte_size = 0; - cursor += str8_deserial_read_uleb128(expr, cursor, &piece_byte_size); - - U64 partial_value_size32 = safe_cast_u32(piece_byte_size); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_PartialValue, partial_value_size32); - } break; - - case DW_ExprOp_BitPiece: { - U64 piece_bit_size = 0; - U64 piece_bit_off = 0; - cursor += str8_deserial_read_uleb128(expr, cursor, &piece_bit_size); - cursor += str8_deserial_read_uleb128(expr, cursor, &piece_bit_off); - - U32 piece_bit_size32 = safe_cast_u32(piece_bit_size); - U32 piece_bit_off32 = safe_cast_u32(piece_bit_off); - - U64 partial_value = ((U64)piece_bit_size32 << 32) | (U64)piece_bit_off32; - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_PartialValueBit, partial_value); - } break; - - case DW_ExprOp_Pick: { - U8 stack_idx = 0; - cursor += str8_deserial_read_struct(expr, cursor, &stack_idx); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Pick, stack_idx); - } break; - - case DW_ExprOp_PlusUConst: { - U64 addend = 0; - cursor += str8_deserial_read_uleb128(expr, cursor, &addend); - rdim_bytecode_push_uconst(arena, &bc, addend); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, RDI_EvalTypeGroup_U); - } break; - - case DW_ExprOp_Skip: { - S16 skip = 0; - cursor += str8_deserial_read_struct(expr, cursor, &skip); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Skip, skip); - } break; - - case DW_ExprOp_Bra: { - NotImplemented; - } break; - - case DW_ExprOp_BReg0: case DW_ExprOp_BReg1: case DW_ExprOp_BReg2: - case DW_ExprOp_BReg3: case DW_ExprOp_BReg4: case DW_ExprOp_BReg5: - case DW_ExprOp_BReg6: case DW_ExprOp_BReg7: case DW_ExprOp_BReg8: - case DW_ExprOp_BReg9: case DW_ExprOp_BReg10: case DW_ExprOp_BReg11: - case DW_ExprOp_BReg12: case DW_ExprOp_BReg13: case DW_ExprOp_BReg14: - case DW_ExprOp_BReg15: case DW_ExprOp_BReg16: case DW_ExprOp_BReg17: - case DW_ExprOp_BReg18: case DW_ExprOp_BReg19: case DW_ExprOp_BReg20: - case DW_ExprOp_BReg21: case DW_ExprOp_BReg22: case DW_ExprOp_BReg23: - case DW_ExprOp_BReg24: case DW_ExprOp_BReg25: case DW_ExprOp_BReg26: - case DW_ExprOp_BReg27: case DW_ExprOp_BReg28: case DW_ExprOp_BReg29: - case DW_ExprOp_BReg30: case DW_ExprOp_BReg31: { - U64 reg_code_dw = op - DW_ExprOp_BReg0; - S64 reg_off = 0; - cursor += str8_deserial_read_sleb128(expr, cursor, ®_off); + case DW_ExprOp_Lit0: case DW_ExprOp_Lit1: case DW_ExprOp_Lit2: + case DW_ExprOp_Lit3: case DW_ExprOp_Lit4: case DW_ExprOp_Lit5: + case DW_ExprOp_Lit6: case DW_ExprOp_Lit7: case DW_ExprOp_Lit8: + case DW_ExprOp_Lit9: case DW_ExprOp_Lit10: case DW_ExprOp_Lit11: + case DW_ExprOp_Lit12: case DW_ExprOp_Lit13: case DW_ExprOp_Lit14: + case DW_ExprOp_Lit15: case DW_ExprOp_Lit16: case DW_ExprOp_Lit17: + case DW_ExprOp_Lit18: case DW_ExprOp_Lit19: case DW_ExprOp_Lit20: + case DW_ExprOp_Lit21: case DW_ExprOp_Lit22: case DW_ExprOp_Lit23: + case DW_ExprOp_Lit24: case DW_ExprOp_Lit25: case DW_ExprOp_Lit26: + case DW_ExprOp_Lit27: case DW_ExprOp_Lit28: case DW_ExprOp_Lit29: + case DW_ExprOp_Lit30: case DW_ExprOp_Lit31: { + U64 lit = op - DW_ExprOp_Lit0; + + rdim_bytecode_push_uconst(arena, &bc, lit); + push_of_type(RDI_TypeKind_U64); + } break; - RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegReadDyn, reg_code_rdi); - if (reg_off > 0) { - rdim_bytecode_push_sconst(arena, &bc, reg_off); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, RDI_EvalTypeGroup_S); - } - push_of_type(RDI_TypeKind_S64); - - *is_addr_out = 1; - } break; - - case DW_ExprOp_BRegX: { - U64 reg_code_dw = 0; - S64 reg_off = 0; - cursor += str8_deserial_read_uleb128(expr, cursor, ®_code_dw); - cursor += str8_deserial_read_sleb128(expr, cursor, ®_off); - - RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegReadDyn, reg_code_rdi); - if (reg_off > 0) { - rdim_bytecode_push_sconst(arena, &bc, reg_off); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, RDI_EvalTypeGroup_S); - } - push_of_type(RDI_TypeKind_S64); - - *is_addr_out = 1; - } break; - - case DW_ExprOp_FBReg: { - S64 frame_off = 0; - cursor += str8_deserial_read_sleb128(expr, cursor, &frame_off); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_FrameOff, frame_off); - - *is_addr_out = 1; - } break; - - case DW_ExprOp_Deref: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_MemRead, address_size); - } break; - - case DW_ExprOp_DerefSize: { - U8 deref_size_in_bytes = 0; - cursor += str8_deserial_read_struct(expr, cursor, &deref_size_in_bytes); - if (0 < deref_size_in_bytes && deref_size_in_bytes <= address_size) { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_MemRead, deref_size_in_bytes); - } else { - // TODO: error handling - AssertAlways(!"ill formed expression"); - } - } break; - - case DW_ExprOp_XDerefSize: { - // TODO: error handling - AssertAlways(!"no suitable conversion"); - } break; - - case DW_ExprOp_Call2: - case DW_ExprOp_Call4: - case DW_ExprOp_CallRef: { - // TODO: error handling - AssertAlways(!"calls are not supported"); - } break; - - case DW_ExprOp_ImplicitPointer: - case DW_ExprOp_GNU_ImplicitPointer: { - // TODO: - AssertAlways(!"sample"); - } break; - - case DW_ExprOp_Convert: - case DW_ExprOp_GNU_Convert: { - U64 type_info_off = 0; - cursor += str8_deserial_read_uleb128(expr, cursor, &type_info_off); - - RDI_EvalTypeGroup in = stack ? d2r_type_group_from_type_kind(stack->value_type) : RDI_EvalTypeGroup_Other; - RDI_EvalTypeGroup out = RDI_EvalTypeGroup_Other; - - if (type_info_off == 0) { - // - // 2.5.1 - // Instead of a base type, elements can have a generic type, - // which is an integral type that has the size of an address - // on the target machine and unspecified signedness. - // - out = d2r_type_group_from_type_kind(addr_type_kind); - } else { - // find ref tag - DW_TagNode *tag_node = dw_tag_node_from_info_off(cu, type_info_off); - DW_Tag tag = tag_node->tag; - if (tag.kind == DW_Tag_BaseType) { - // extract encoding attribute - DW_ATE encoding = dw_const_u64_from_attrib(input, cu, tag, DW_Attrib_Encoding); - - // DW_ATE -> RDI_EvalTypeGroup - switch (encoding) { - case DW_ATE_SignedChar: - case DW_ATE_Signed: out = RDI_EvalTypeGroup_S; break; - case DW_ATE_UnsignedChar: - case DW_ATE_Unsigned: out = RDI_EvalTypeGroup_U; break; - case DW_ATE_Float: { - U64 byte_size = dw_const_u64_from_attrib(input, cu, tag, DW_Attrib_ByteSize); - switch (byte_size) { - case 4: out = RDI_EvalTypeGroup_F32; break; - case 8: out = RDI_EvalTypeGroup_F64; break; - default: InvalidPath; - } - } break; - default: InvalidPath; - } - } else { - AssertAlways(!"unexpected tag"); // TODO: error handling - } - } - - if (in == RDI_EvalTypeGroup_Other) { - push_of_type(out); - break; - } - - // TODO: error handling - AssertAlways(in != RDI_EvalTypeGroup_Other); - AssertAlways(out != RDI_EvalTypeGroup_Other); - - U16 operand = (U16)in | ((U16)out << 8); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Convert, operand); - } break; - - case DW_ExprOp_GNU_ParameterRef: { - // TODO: - AssertAlways(!"sample"); - } break; - - case DW_ExprOp_DerefType: - case DW_ExprOp_GNU_DerefType: { - // TODO: - AssertAlways(!"sample"); - } break; - - case DW_ExprOp_ConstType: - case DW_ExprOp_GNU_ConstType: { - // TODO: - AssertAlways(!"sample"); - } break; - - case DW_ExprOp_RegvalType: { - // TODO: - AssertAlways(!"sample"); - } break; - - case DW_ExprOp_EntryValue: - case DW_ExprOp_GNU_EntryValue: { - U64 entry_value_expr_size = 0; - String8 entry_value_expr = {0}; - cursor += str8_deserial_read_uleb128(expr, cursor, &entry_value_expr_size); - cursor += str8_deserial_read_block(expr, cursor, entry_value_expr_size, &entry_value_expr); - - B32 dummy = 0; - RDIM_EvalBytecode call_site_bc = d2r_bytecode_from_expression(arena, input, image_base, address_size, arch, addr_lu, entry_value_expr, cu, &dummy); - - U32 encoded_size32 = safe_cast_u32(call_site_bc.encoded_size); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_CallSiteValue, encoded_size32); - rdim_bytecode_concat_in_place(&bc, &call_site_bc); - } break; - - case DW_ExprOp_Addrx: { - U64 addr_idx = 0; - cursor += str8_deserial_read_uleb128(expr, cursor, &addr_idx); - U64 addr = dw_addr_from_list_unit(addr_lu, addr_idx); - if (addr != max_U64) { + case DW_ExprOp_Const1U: { + U8 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_uconst(arena, &bc, val); + push_of_type(RDI_TypeKind_U8); + } break; + case DW_ExprOp_Const2U: { + U16 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_uconst(arena, &bc, val); + push_of_type(RDI_TypeKind_U16); + } break; + case DW_ExprOp_Const4U: { + U32 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_uconst(arena, &bc, val); + push_of_type(RDI_TypeKind_U32); + } break; + case DW_ExprOp_Const8U: { + U64 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_uconst(arena, &bc, val); + push_of_type(RDI_TypeKind_U64); + } break; + + case DW_ExprOp_Const1S: { + S8 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_sconst(arena, &bc, val); + push_of_type(RDI_TypeKind_S8); + } break; + case DW_ExprOp_Const2S: { + S16 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_sconst(arena, &bc, val); + push_of_type(RDI_TypeKind_S16); + } break; + case DW_ExprOp_Const4S: { + S32 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_sconst(arena, &bc, val); + push_of_type(RDI_TypeKind_S32); + } break; + case DW_ExprOp_Const8S: { + S64 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_sconst(arena, &bc, val); + push_of_type(RDI_TypeKind_S64); + } break; + + case DW_ExprOp_ConstU: { + U64 val = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, &val); + + rdim_bytecode_push_uconst(arena, &bc, val); + push_of_type(RDI_TypeKind_U64); + } break; + + case DW_ExprOp_ConstS: { + S64 val = 0; + cursor += str8_deserial_read_sleb128(expr, cursor, &val); + + rdim_bytecode_push_sconst(arena, &bc, val); + push_of_type(RDI_TypeKind_S64); + } break; + + case DW_ExprOp_Addr: { + U64 addr = 0; + cursor += str8_deserial_read(expr, cursor, &addr, address_size, address_size); if (addr >= image_base) { U64 voff = addr - image_base; rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_ModuleOff, voff); + push_of_type(addr_type_kind); } else { // TODO: error handling AssertAlways(!"unable to relocate address"); } - } else { + + *is_addr_out = 1; + } break; + + case DW_ExprOp_Reg0: case DW_ExprOp_Reg1: case DW_ExprOp_Reg2: + case DW_ExprOp_Reg3: case DW_ExprOp_Reg4: case DW_ExprOp_Reg5: + case DW_ExprOp_Reg6: case DW_ExprOp_Reg7: case DW_ExprOp_Reg8: + case DW_ExprOp_Reg9: case DW_ExprOp_Reg10: case DW_ExprOp_Reg11: + case DW_ExprOp_Reg12: case DW_ExprOp_Reg13: case DW_ExprOp_Reg14: + case DW_ExprOp_Reg15: case DW_ExprOp_Reg16: case DW_ExprOp_Reg17: + case DW_ExprOp_Reg18: case DW_ExprOp_Reg19: case DW_ExprOp_Reg20: + case DW_ExprOp_Reg21: case DW_ExprOp_Reg22: case DW_ExprOp_Reg23: + case DW_ExprOp_Reg24: case DW_ExprOp_Reg25: case DW_ExprOp_Reg26: + case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29: + case DW_ExprOp_Reg30: case DW_ExprOp_Reg31: { + U64 reg_code_dw = op - DW_ExprOp_Reg0; + U64 reg_size = dw_reg_size_from_code(arch, reg_code_dw); + U64 reg_pos = dw_reg_pos_from_code(arch, reg_code_dw); + + RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); + U32 regread_param = RDI_EncodeRegReadParam(reg_code_rdi, reg_size, reg_pos); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegRead, regread_param); + push_of_type(d2r_unsigned_type_kind_from_size(reg_size)); + } break; + + case DW_ExprOp_RegX: { + U64 reg_code_dw = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, ®_code_dw); + + U64 reg_size = dw_reg_size_from_code(arch, reg_code_dw); + U64 reg_pos = dw_reg_pos_from_code(arch, reg_code_dw); + + RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); + U32 regread_param = RDI_EncodeRegReadParam(reg_code_rdi, reg_size, reg_pos); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegRead, regread_param); + push_of_type(d2r_unsigned_type_kind_from_size(reg_size)); + + *is_addr_out = 1; + } break; + + case DW_ExprOp_ImplicitValue: { + U64 val_size = 0; + String8 val = {0}; + cursor += str8_deserial_read_uleb128(expr, cursor, &val_size); + cursor += str8_deserial_read_block(expr, cursor, val_size, &val); + if (val.size <= sizeof(U64)) { + U64 val64 = 0; + MemoryCopy(&val64, val.str, val.size); + + rdim_bytecode_push_uconst(arena, &bc, val64); + push_of_type(d2r_unsigned_type_kind_from_size(val_size)); + } else { + // TODO: currenlty no way to encode string in RDIM_EvalBytecodeOp + NotImplemented; + } + } break; + + case DW_ExprOp_Piece: { + U64 piece_byte_size = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, &piece_byte_size); + + U64 partial_value_size32 = safe_cast_u32(piece_byte_size); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_PartialValue, partial_value_size32); + } break; + + case DW_ExprOp_BitPiece: { + U64 piece_bit_size = 0; + U64 piece_bit_off = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, &piece_bit_size); + cursor += str8_deserial_read_uleb128(expr, cursor, &piece_bit_off); + + U32 piece_bit_size32 = safe_cast_u32(piece_bit_size); + U32 piece_bit_off32 = safe_cast_u32(piece_bit_off); + + U64 partial_value = ((U64)piece_bit_size32 << 32) | (U64)piece_bit_off32; + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_PartialValueBit, partial_value); + } break; + + case DW_ExprOp_Pick: { + U8 stack_idx = 0; + cursor += str8_deserial_read_struct(expr, cursor, &stack_idx); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Pick, stack_idx); + } break; + + case DW_ExprOp_PlusUConst: { + U64 addend = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, &addend); + rdim_bytecode_push_uconst(arena, &bc, addend); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, RDI_EvalTypeGroup_U); + } break; + + case DW_ExprOp_Skip: { + S16 skip = 0; + cursor += str8_deserial_read_struct(expr, cursor, &skip); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Skip, skip); + } break; + + case DW_ExprOp_Bra: { + NotImplemented; + } break; + + case DW_ExprOp_BReg0: case DW_ExprOp_BReg1: case DW_ExprOp_BReg2: + case DW_ExprOp_BReg3: case DW_ExprOp_BReg4: case DW_ExprOp_BReg5: + case DW_ExprOp_BReg6: case DW_ExprOp_BReg7: case DW_ExprOp_BReg8: + case DW_ExprOp_BReg9: case DW_ExprOp_BReg10: case DW_ExprOp_BReg11: + case DW_ExprOp_BReg12: case DW_ExprOp_BReg13: case DW_ExprOp_BReg14: + case DW_ExprOp_BReg15: case DW_ExprOp_BReg16: case DW_ExprOp_BReg17: + case DW_ExprOp_BReg18: case DW_ExprOp_BReg19: case DW_ExprOp_BReg20: + case DW_ExprOp_BReg21: case DW_ExprOp_BReg22: case DW_ExprOp_BReg23: + case DW_ExprOp_BReg24: case DW_ExprOp_BReg25: case DW_ExprOp_BReg26: + case DW_ExprOp_BReg27: case DW_ExprOp_BReg28: case DW_ExprOp_BReg29: + case DW_ExprOp_BReg30: case DW_ExprOp_BReg31: { + U64 reg_code_dw = op - DW_ExprOp_BReg0; + S64 reg_off = 0; + cursor += str8_deserial_read_sleb128(expr, cursor, ®_off); + + RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegReadDyn, reg_code_rdi); + if (reg_off > 0) { + rdim_bytecode_push_sconst(arena, &bc, reg_off); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, RDI_EvalTypeGroup_S); + } + push_of_type(RDI_TypeKind_S64); + + *is_addr_out = 1; + } break; + + case DW_ExprOp_BRegX: { + U64 reg_code_dw = 0; + S64 reg_off = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, ®_code_dw); + cursor += str8_deserial_read_sleb128(expr, cursor, ®_off); + + RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegReadDyn, reg_code_rdi); + if (reg_off > 0) { + rdim_bytecode_push_sconst(arena, &bc, reg_off); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, RDI_EvalTypeGroup_S); + } + push_of_type(RDI_TypeKind_S64); + + *is_addr_out = 1; + } break; + + case DW_ExprOp_FBReg: { + S64 frame_off = 0; + cursor += str8_deserial_read_sleb128(expr, cursor, &frame_off); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_FrameOff, frame_off); + + *is_addr_out = 1; + } break; + + case DW_ExprOp_Deref: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_MemRead, address_size); + } break; + + case DW_ExprOp_DerefSize: { + U8 deref_size_in_bytes = 0; + cursor += str8_deserial_read_struct(expr, cursor, &deref_size_in_bytes); + if (0 < deref_size_in_bytes && deref_size_in_bytes <= address_size) { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_MemRead, deref_size_in_bytes); + } else { + // TODO: error handling + AssertAlways(!"ill formed expression"); + } + } break; + + case DW_ExprOp_XDerefSize: { // TODO: error handling - AssertAlways(!"out of bounds index"); - } - } break; - - case DW_ExprOp_CallFrameCfa: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_FrameOff, 0); - } break; - - case DW_ExprOp_FormTlsAddress: { - // TODO: - AssertAlways(!"RDI_EvalOp_TLSOff accepts immediate"); - } break; - - case DW_ExprOp_PushObjectAddress: { - AssertAlways(!"sample"); - } break; - - case DW_ExprOp_Nop: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Noop, 0); - } break; - - case DW_ExprOp_Eq: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_EqEq, peek_type()); - } break; - - case DW_ExprOp_Ge: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_GrEq, peek_type()); - } break; - - case DW_ExprOp_Gt: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Grtr, peek_type()); - } break; - - case DW_ExprOp_Le: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_LsEq, peek_type()); - } break; - - case DW_ExprOp_Lt: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Less, peek_type()); - } break; - - case DW_ExprOp_Ne: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_NtEq, peek_type()); - } break; - - case DW_ExprOp_Shl: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_LShift, peek_type()); - } break; - - case DW_ExprOp_Shr: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RShift, RDI_EvalTypeGroup_U); - } break; - - case DW_ExprOp_Shra: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RShift, RDI_EvalTypeGroup_S); - } break; - - case DW_ExprOp_Xor: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitXor, peek_type()); - } break; - - case DW_ExprOp_XDeref: { - // TODO: error handling - Assert(!"multiple address spaces are not supported"); - } break; - - case DW_ExprOp_Abs: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Abs, peek_type()); - } break; - - case DW_ExprOp_And: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitAnd, peek_type()); - } break; - - case DW_ExprOp_Div: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Div, peek_type()); - } break; - - case DW_ExprOp_Minus: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Sub, peek_type()); - } break; - - case DW_ExprOp_Mod: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Mod, peek_type()); - } break; - - case DW_ExprOp_Mul: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Mul, peek_type()); - } break; - - case DW_ExprOp_Neg: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Neg, peek_type()); - } break; - - case DW_ExprOp_Not: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitNot, peek_type()); - } break; - - case DW_ExprOp_Or: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitOr, peek_type()); - } break; - - case DW_ExprOp_Plus: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, peek_type()); - } break; - - case DW_ExprOp_Rot: { - AssertAlways(!"no suitable conversion"); - } break; - - case DW_ExprOp_Swap: { - AssertAlways(!"no suitable conversion"); - } break; - - case DW_ExprOp_Dup: { - AssertAlways(!"no suitable conversion"); - } break; - - case DW_ExprOp_Drop: { - AssertAlways(!"no suitable conversion"); - } break; - - case DW_ExprOp_Over: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Pick, 1); - } break; - - case DW_ExprOp_StackValue: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Stop, 0); - } break; - - default: InvalidPath; break; + AssertAlways(!"no suitable conversion"); + } break; + + case DW_ExprOp_Call2: + case DW_ExprOp_Call4: + case DW_ExprOp_CallRef: { + // TODO: error handling + AssertAlways(!"calls are not supported"); + } break; + + case DW_ExprOp_ImplicitPointer: + case DW_ExprOp_GNU_ImplicitPointer: { + // TODO: + AssertAlways(!"sample"); + } break; + + case DW_ExprOp_Convert: + case DW_ExprOp_GNU_Convert: { + U64 type_info_off = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, &type_info_off); + + RDI_EvalTypeGroup in = stack ? d2r_type_group_from_type_kind(stack->value_type) : RDI_EvalTypeGroup_Other; + RDI_EvalTypeGroup out = RDI_EvalTypeGroup_Other; + + if (type_info_off == 0) { + // + // 2.5.1 + // Instead of a base type, elements can have a generic type, + // which is an integral type that has the size of an address + // on the target machine and unspecified signedness. + // + out = d2r_type_group_from_type_kind(addr_type_kind); + } else { + // find ref tag + DW_TagNode *tag_node = dw_tag_node_from_info_off(cu, type_info_off); + DW_Tag tag = tag_node->tag; + if (tag.kind == DW_Tag_BaseType) { + // extract encoding attribute + DW_ATE encoding = dw_const_u64_from_attrib(input, cu, tag, DW_Attrib_Encoding); + + // DW_ATE -> RDI_EvalTypeGroup + switch (encoding) { + case DW_ATE_SignedChar: + case DW_ATE_Signed: out = RDI_EvalTypeGroup_S; break; + case DW_ATE_UnsignedChar: + case DW_ATE_Unsigned: out = RDI_EvalTypeGroup_U; break; + case DW_ATE_Float: { + U64 byte_size = dw_const_u64_from_attrib(input, cu, tag, DW_Attrib_ByteSize); + switch (byte_size) { + case 4: out = RDI_EvalTypeGroup_F32; break; + case 8: out = RDI_EvalTypeGroup_F64; break; + default: InvalidPath; + } + } break; + default: InvalidPath; + } + } else { + AssertAlways(!"unexpected tag"); // TODO: error handling + } + } + + if (in == RDI_EvalTypeGroup_Other) { + push_of_type(out); + break; + } + + // TODO: error handling + AssertAlways(in != RDI_EvalTypeGroup_Other); + AssertAlways(out != RDI_EvalTypeGroup_Other); + + U16 operand = (U16)in | ((U16)out << 8); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Convert, operand); + } break; + + case DW_ExprOp_GNU_ParameterRef: { + // TODO: + AssertAlways(!"sample"); + } break; + + case DW_ExprOp_DerefType: + case DW_ExprOp_GNU_DerefType: { + // TODO: + AssertAlways(!"sample"); + } break; + + case DW_ExprOp_ConstType: + case DW_ExprOp_GNU_ConstType: { + // TODO: + AssertAlways(!"sample"); + } break; + + case DW_ExprOp_RegvalType: { + // TODO: + AssertAlways(!"sample"); + } break; + + case DW_ExprOp_EntryValue: + case DW_ExprOp_GNU_EntryValue: { + U64 entry_value_expr_size = 0; + String8 entry_value_expr = {0}; + cursor += str8_deserial_read_uleb128(expr, cursor, &entry_value_expr_size); + cursor += str8_deserial_read_block(expr, cursor, entry_value_expr_size, &entry_value_expr); + + B32 dummy = 0; + RDIM_EvalBytecode call_site_bc = d2r_bytecode_from_expression(arena, input, image_base, address_size, arch, addr_lu, entry_value_expr, cu, &dummy); + + U32 encoded_size32 = safe_cast_u32(call_site_bc.encoded_size); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_CallSiteValue, encoded_size32); + rdim_bytecode_concat_in_place(&bc, &call_site_bc); + } break; + + case DW_ExprOp_Addrx: { + U64 addr_idx = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, &addr_idx); + U64 addr = dw_addr_from_list_unit(addr_lu, addr_idx); + if (addr != max_U64) { + if (addr >= image_base) { + U64 voff = addr - image_base; + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_ModuleOff, voff); + } else { + // TODO: error handling + AssertAlways(!"unable to relocate address"); + } + } else { + // TODO: error handling + AssertAlways(!"out of bounds index"); + } + } break; + + case DW_ExprOp_CallFrameCfa: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_FrameOff, 0); + } break; + + case DW_ExprOp_FormTlsAddress: { + // TODO: + AssertAlways(!"RDI_EvalOp_TLSOff accepts immediate"); + } break; + + case DW_ExprOp_PushObjectAddress: { + AssertAlways(!"sample"); + } break; + + case DW_ExprOp_Nop: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Noop, 0); + } break; + + case DW_ExprOp_Eq: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_EqEq, peek_type()); + } break; + + case DW_ExprOp_Ge: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_GrEq, peek_type()); + } break; + + case DW_ExprOp_Gt: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Grtr, peek_type()); + } break; + + case DW_ExprOp_Le: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_LsEq, peek_type()); + } break; + + case DW_ExprOp_Lt: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Less, peek_type()); + } break; + + case DW_ExprOp_Ne: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_NtEq, peek_type()); + } break; + + case DW_ExprOp_Shl: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_LShift, peek_type()); + } break; + + case DW_ExprOp_Shr: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RShift, RDI_EvalTypeGroup_U); + } break; + + case DW_ExprOp_Shra: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RShift, RDI_EvalTypeGroup_S); + } break; + + case DW_ExprOp_Xor: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitXor, peek_type()); + } break; + + case DW_ExprOp_XDeref: { + // TODO: error handling + Assert(!"multiple address spaces are not supported"); + } break; + + case DW_ExprOp_Abs: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Abs, peek_type()); + } break; + + case DW_ExprOp_And: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitAnd, peek_type()); + } break; + + case DW_ExprOp_Div: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Div, peek_type()); + } break; + + case DW_ExprOp_Minus: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Sub, peek_type()); + } break; + + case DW_ExprOp_Mod: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Mod, peek_type()); + } break; + + case DW_ExprOp_Mul: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Mul, peek_type()); + } break; + + case DW_ExprOp_Neg: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Neg, peek_type()); + } break; + + case DW_ExprOp_Not: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitNot, peek_type()); + } break; + + case DW_ExprOp_Or: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitOr, peek_type()); + } break; + + case DW_ExprOp_Plus: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, peek_type()); + } break; + + case DW_ExprOp_Rot: { + AssertAlways(!"no suitable conversion"); + } break; + + case DW_ExprOp_Swap: { + AssertAlways(!"no suitable conversion"); + } break; + + case DW_ExprOp_Dup: { + AssertAlways(!"no suitable conversion"); + } break; + + case DW_ExprOp_Drop: { + AssertAlways(!"no suitable conversion"); + } break; + + case DW_ExprOp_Over: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Pick, 1); + } break; + + case DW_ExprOp_StackValue: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Stop, 0); + } break; + + default: InvalidPath; break; } } - + #undef peek_type #undef pop_type #undef push_of_type @@ -827,7 +827,7 @@ d2r_transpile_expression(Arena *arena, DW_Input *input, U64 image_base, U64 addr if (expr.size) { B32 is_addr = 0; RDIM_EvalBytecode bytecode = d2r_bytecode_from_expression(arena, input, image_base, address_size, arch, addr_lu, expr, cu, &is_addr); - + loc = push_array(arena, RDIM_Location, 1); loc->kind = is_addr ? RDI_LocationKind_AddrBytecodeStream : RDI_LocationKind_ValBytecodeStream; loc->bytecode = bytecode; @@ -855,29 +855,29 @@ d2r_locset_from_attrib(Arena *arena, DW_AttribKind kind) { RDIM_LocationSet locset = {0}; - + // extract attrib from tag 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_LocList || attrib_class == DW_AttribClass_LocListPtr) { Temp scratch = scratch_begin(&arena, 1); - + // extract location list from attrib DW_LocList loclist = dw_loclist_from_attrib_ptr(scratch.arena, input, cu, attrib); - + // convert location list to RDIM location set for (DW_LocNode *loc_n = loclist.first; loc_n != 0; loc_n = loc_n->next) { RDIM_Location *location = d2r_transpile_expression(arena, input, image_base, cu->address_size, arch, cu->addr_lu, cu, loc_n->v.expr); RDIM_Rng1U64 voff_range = { .min = loc_n->v.range.min - image_base, .max = loc_n->v.range.max - image_base }; rdim_location_set_push_case(arena, scopes, &locset, voff_range, location); } - + scratch_end(scratch); } else if (attrib_class == DW_AttribClass_ExprLoc) { // extract expression from attrib String8 expr = dw_exprloc_from_attrib_ptr(input, cu, attrib); - + // convert expression and inherit life-time ranges from enclosed scope RDIM_Location *location = d2r_transpile_expression(arena, input, image_base, cu->address_size, arch, cu->addr_lu, cu, expr); for (RDIM_Rng1U64Node *range_n = curr_scope->voff_ranges.first; range_n != 0; range_n = range_n->next) { @@ -886,7 +886,7 @@ d2r_locset_from_attrib(Arena *arena, } else if (attrib_class != DW_AttribClass_Null) { AssertAlways(!"unexpected attrib class"); } - + return locset; } @@ -901,28 +901,28 @@ d2r_var_locset_from_tag(Arena *arena, DW_Tag tag) { RDIM_LocationSet locset = {0}; - + B32 has_const_value = dw_tag_has_attrib(input, cu, tag, DW_Attrib_ConstValue); B32 has_location = dw_tag_has_attrib(input, cu, tag, DW_Attrib_Location); - + if (has_const_value && has_location) { // TODO: error handling AssertAlways(!"unexpected variable encoding"); } - + if (has_const_value) { // extract const value U64 const_value = dw_u64_from_attrib(input, cu, tag, DW_Attrib_ConstValue); - + // make value byte code RDIM_EvalBytecode bc = {0}; rdim_bytecode_push_uconst(arena, &bc, const_value); - + // fill out location RDIM_Location *loc = push_array(arena, RDIM_Location, 1); loc->kind = RDI_LocationKind_ValBytecodeStream; loc->bytecode = bc; - + // push location cases for (RDIM_Rng1U64Node *range_n = curr_scope->voff_ranges.first; range_n != 0; range_n = range_n->next) { rdim_location_set_push_case(arena, scopes, &locset, range_n->v, loc); @@ -930,7 +930,7 @@ d2r_var_locset_from_tag(Arena *arena, } else if (has_location) { locset = d2r_locset_from_attrib(arena, input, cu, scopes, curr_scope, image_base, arch, tag, DW_Attrib_Location); } - + return locset; } @@ -938,38 +938,38 @@ internal D2R_CompUnitContribMap d2r_cu_contrib_map_from_aranges(Arena *arena, DW_Input *input, U64 image_base) { Temp scratch = scratch_begin(&arena, 1); - + String8 aranges_data = input->sec[DW_Section_ARanges].data; Rng1U64List unit_range_list = dw_unit_ranges_from_data(scratch.arena, aranges_data); - + D2R_CompUnitContribMap cm = {0}; cm.count = 0; cm.info_off_arr = push_array(arena, U64, unit_range_list.count); cm.voff_range_arr = push_array(arena, RDIM_Rng1U64List, unit_range_list.count); - + for (Rng1U64Node *range_n = unit_range_list.first; range_n != 0; range_n = range_n->next) { String8 unit_data = str8_substr(aranges_data, range_n->v); U64 unit_cursor = 0; - + U64 unit_length = 0; U64 unit_length_size = str8_deserial_read_dwarf_packed_size(unit_data, unit_cursor, &unit_length); if (unit_length_size == 0) { continue; } unit_cursor += unit_length_size; - + DW_Version version = 0; U64 version_size = str8_deserial_read_struct(unit_data, unit_cursor, &version); if (version_size == 0) { continue; } unit_cursor += version; - + if (version != DW_Version_2) { AssertAlways(!"unknown .debug_aranges version"); continue; } - + DW_Format unit_format = DW_FormatFromSize(unit_length); U64 cu_info_off = 0; U64 cu_info_off_size = str8_deserial_read_dwarf_uint(unit_data, unit_cursor, unit_format, &cu_info_off); @@ -977,27 +977,27 @@ d2r_cu_contrib_map_from_aranges(Arena *arena, DW_Input *input, U64 image_base) continue; } unit_cursor += cu_info_off_size; - + U8 address_size = 0; U64 address_size_size = str8_deserial_read_struct(unit_data, unit_cursor, &address_size); if (address_size_size == 0) { continue; } unit_cursor += address_size_size; - + U8 segment_selector_size = 0; U64 segment_selector_size_size = str8_deserial_read_struct(unit_data, unit_cursor, &segment_selector_size); if (segment_selector_size_size == 0) { continue; } unit_cursor += segment_selector_size_size; - + U64 tuple_size = address_size * 2 + segment_selector_size; U64 bytes_too_far_past_boundary = unit_cursor % tuple_size; if (bytes_too_far_past_boundary > 0) { unit_cursor += tuple_size - bytes_too_far_past_boundary; } - + RDIM_Rng1U64List voff_ranges = {0}; if (segment_selector_size == 0) { while (unit_cursor + address_size * 2 <= unit_data.size) { @@ -1005,14 +1005,14 @@ d2r_cu_contrib_map_from_aranges(Arena *arena, DW_Input *input, U64 image_base) U64 length = 0; unit_cursor += str8_deserial_read(unit_data, unit_cursor, &address, address_size, address_size); unit_cursor += str8_deserial_read(unit_data, unit_cursor, &length, address_size, address_size); - + if (address == 0 && length == 0) { break; } - + // TODO: error handling AssertAlways(address >= image_base); - + U64 min = address - image_base; U64 max = min + length; rdim_rng1u64_list_push(arena, &voff_ranges, (RDIM_Rng1U64){.min = min, .max = max}); @@ -1021,20 +1021,20 @@ d2r_cu_contrib_map_from_aranges(Arena *arena, DW_Input *input, U64 image_base) // TODO: segment relative addressing NotImplemented; } - + U64 map_idx = cm.count++; cm.info_off_arr[map_idx] = cu_info_off; cm.voff_range_arr[map_idx] = voff_ranges; } - + scratch_end(scratch); return cm; } -internal RDIM_Rng1U64List +internal RDIM_Rng1U64ChunkList d2r_voff_ranges_from_cu_info_off(D2R_CompUnitContribMap map, U64 info_off) { - RDIM_Rng1U64List voff_ranges = {0}; + RDIM_Rng1U64ChunkList voff_ranges = {0}; U64 voff_list_idx = u64_array_bsearch(map.info_off_arr, map.count, info_off); if (voff_list_idx < map.count) { voff_ranges = map.voff_range_arr[voff_list_idx]; @@ -1047,101 +1047,101 @@ d2r_push_scope(Arena *arena, RDIM_ScopeChunkList *scopes, U64 scope_chunk_cap, D { // fill out scope RDIM_Scope *scope = rdim_scope_chunk_list_push(arena, scopes, scope_chunk_cap); - + // push ranges for (Rng1U64Node *i = ranges.first; i != 0; i = i->next) { rdim_scope_push_voff_range(arena, scopes, scope, (RDIM_Rng1U64){.min = i->v.min, i->v.max}); } - + // associate scope with tag tag_stack->scope = scope; - + // update scope hierarchy DW_TagKind parent_tag_kind = tag_stack->next->cur_node->tag.kind; if (parent_tag_kind == DW_Tag_SubProgram || parent_tag_kind == DW_Tag_InlinedSubroutine || parent_tag_kind == DW_Tag_LexicalBlock) { RDIM_Scope *parent = tag_stack->next->scope; - + scope->parent_scope = parent; scope->symbol = parent->symbol; - + if (parent->last_child) { parent->last_child->next_sibling = scope; } SLLQueuePush_N(parent->first_child, parent->last_child, scope, next_sibling); } - + return scope; } -internal RDIM_BakeParams * +internal RDIM_BakeParams d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) { Temp scratch = scratch_begin(&arena, 1); - + //////////////////////////////// - + ProfBegin("compute exe hash"); U64 exe_hash = rdi_hash(in->image_data.str, in->image_data.size); ProfEnd(); - + //////////////////////////////// - + Arch arch = Arch_Null; U64 image_base = 0; RDIM_BinarySectionList binary_sections = {0}; DW_Input input = {0}; - - if (in->image == Image_CoffPe) { + + if (in->image == ExecutableImageKind_CoffPe) { PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, in->image_data); - + // get image arch arch = pe.arch; - + // get image base image_base = pe.image_base; - + // get image sections String8 raw_sections = str8_substr(in->image_data, pe.section_table_range); U64 section_count = raw_sections.size / sizeof(COFF_SectionHeader); COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_sections.str; - + // convert sections String8 string_table = str8_substr(in->image_data, pe.string_table_range); binary_sections = c2r_rdi_binary_sections_from_coff_sections(arena, in->image_data, string_table, section_count, section_table); - + // make DWARF input input = dw_input_from_coff_section_table(scratch.arena, in->image_data, string_table, section_count, section_table); - } else if (in->image == Image_Elf32 || in->image == Image_Elf64) { + } else if (in->image == ExecutableImageKind_Elf32 || in->image == ExecutableImageKind_Elf64) { ELF_BinInfo elf = elf_bin_from_data(in->debug_data); - + // get image arch arch = arch_from_elf_machine(elf.hdr.e_machine); - + // get image base image_base = elf_base_addr_from_bin(&elf.hdr); - + // get image sections ELF_Shdr64Array shdrs = elf_shdr64_array_from_bin(scratch.arena, in->debug_data, &elf.hdr); - + // convert sections binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, shdrs); - + // make DWARF input input = dw_input_from_elf_section_table(scratch.arena, in->debug_data, &elf); } else { InvalidPath; } - + //////////////////////////////// - + RDIM_TopLevelInfo top_level_info = rdim_make_top_level_info(in->image_name, arch, exe_hash, binary_sections); - + //////////////////////////////// - + U64 arch_addr_size = rdi_addr_size_from_arch(arch); - + //////////////////////////////// - + static const U64 UNIT_CHUNK_CAP = 256; static const U64 UDT_CHUNK_CAP = 256; static const U64 TYPE_CHUNK_CAP = 256; @@ -1152,7 +1152,7 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) static const U64 INLINE_SITE_CHUNK_CAP = 256; static const U64 SRC_FILE_CAP = 256; static const U64 LINE_TABLE_CAP = 256; - + RDIM_UnitChunkList units = {0}; RDIM_UDTChunkList udts = {0}; RDIM_TypeChunkList types = rdim_init_type_chunk_list(arena, arch); @@ -1163,13 +1163,13 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) RDIM_InlineSiteChunkList inline_sites = {0}; RDIM_SrcFileChunkList src_files = {0}; RDIM_LineTableChunkList line_tables = {0}; - + //////////////////////////////// - + RDIM_Scope *global_scope = rdim_scope_chunk_list_push(arena, &scopes, SCOPE_CHUNK_CAP); - + //////////////////////////////// - + ProfBegin("Make Unit Contrib Map"); D2R_CompUnitContribMap cu_contrib_map = {0}; if (input.sec[DW_Section_ARanges].data.size > 0) { @@ -1179,15 +1179,15 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) NotImplemented; } ProfEnd(); - + ProfBegin("Parse Comop Unit Ranges"); DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, &input); Rng1U64List cu_range_list = dw_unit_ranges_from_data(scratch.arena, input.sec[DW_Section_Info].data); Rng1U64Array cu_ranges = rng1u64_array_from_list(scratch.arena, &cu_range_list); ProfEnd(); - + //////////////////////////////// - + ProfBegin("Parse Compile Unit Headers"); B32 is_parse_relaxed = !(in->flags & RC_Flag_StrictDwarfParse); DW_CompUnit *cu_arr = push_array(scratch.arena, DW_CompUnit, cu_ranges.count); @@ -1195,9 +1195,9 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) cu_arr[cu_idx] = dw_cu_from_info_off(scratch.arena, &input, lu_input, cu_ranges.v[cu_idx].min, is_parse_relaxed); } ProfEnd(); - + //////////////////////////////// - + ProfBegin("Parse Line Tables"); DW_LineTableParseResult *cu_line_tables = push_array(scratch.arena, DW_LineTableParseResult, cu_ranges.count); for (U64 cu_idx = 0; cu_idx < cu_ranges.count; ++cu_idx) { @@ -1208,17 +1208,17 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) cu_line_tables[cu_idx] = dw_parsed_line_table_from_data(scratch.arena, cu_stmt_list, &input, cu_dir, cu_name, cu->address_size, cu->str_offsets_lu); } ProfEnd(); - + //////////////////////////////// - + ProfBegin("Convert Line Tables"); - + HashTable *source_file_ht = hash_table_init(scratch.arena, 0x4000); RDIM_LineTable **cu_line_tables_rdi = push_array(scratch.arena, RDIM_LineTable *, cu_ranges.count); - + for (U64 cu_idx = 0; cu_idx < cu_ranges.count; ++cu_idx) { cu_line_tables_rdi[cu_idx] = rdim_line_table_chunk_list_push(arena, &line_tables, LINE_TABLE_CAP); - + DW_LineTableParseResult *line_table = &cu_line_tables[cu_idx]; DW_LineVMFileArray *dir_table = &line_table->vm_header.dir_table; DW_LineVMFileArray *file_table = &line_table->vm_header.file_table; @@ -1238,27 +1238,27 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) } src_file_map[file_idx] = src_file; } - + for (DW_LineSeqNode *line_seq = line_table->first_seq; line_seq != 0; line_seq = line_seq->next) { if (line_seq->count == 0) { continue; } - + U64 *voffs = push_array(arena, U64, line_seq->count); U32 *line_nums = push_array(arena, U32, line_seq->count); U16 *col_nums = 0; U64 line_idx = 0; - + DW_LineNode *file_line_n = line_seq->first; U64 file_line_count = 0; - + for (DW_LineNode *line_n = file_line_n; line_n != 0; line_n = line_n->next) { if (file_line_n->v.file_index != line_n->v.file_index || line_n->next == 0) { U64 file_index = file_line_n->v.file_index; U64 *file_voffs = &voffs[line_idx]; U32 *file_line_nums = &line_nums[line_idx]; U16 *file_col_nums = 0; - + U64 lines_written = 0; U64 prev_ln = max_U64; DW_LineNode *sentinel = line_n->v.file_index != file_line_n->v.file_index ? line_n : 0; @@ -1266,82 +1266,82 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) if (file_line_n->v.line != prev_ln) { // TODO: error handling AssertAlways(file_line_n->v.address >= image_base); - + voffs[line_idx] = file_line_n->v.address - image_base; line_nums[line_idx] = file_line_n->v.line; - + ++lines_written; ++line_idx; - + prev_ln = file_line_n->v.line; } } - + RDIM_SrcFile *src_file = src_file_map[file_index]; RDIM_LineSequence *line_seq = rdim_line_table_push_sequence(arena, &line_tables, cu_line_tables_rdi[cu_idx], src_file, file_voffs, file_line_nums, file_col_nums, lines_written); rdim_src_file_push_line_sequence(arena, &src_files, src_file, line_seq); - + file_line_count = 1; } else { ++file_line_count; } } - + // handle last line if (file_line_n) { U64 file_index = file_line_n->v.file_index; U64 *file_voffs = &voffs[line_idx]; U32 *file_line_nums = &line_nums[line_idx]; U16 *file_col_nums = 0; - + for (; file_line_n != 0; file_line_n = file_line_n->next, ++line_idx) { // TODO: error handling AssertAlways(file_line_n->v.address >= image_base); voffs[line_idx] = file_line_n->v.address - image_base; line_nums[line_idx] = file_line_n->v.line; } - + RDIM_SrcFile *src_file = src_file_map[file_index]; RDIM_LineSequence *line_seq = rdim_line_table_push_sequence(arena, &line_tables, cu_line_tables_rdi[cu_idx], src_file, file_voffs, file_line_nums, file_col_nums, file_line_count); rdim_src_file_push_line_sequence(arena, &src_files, src_file, line_seq); } - + //Assert(line_idx == line_seq->count); } } - + ProfEnd(); - + //////////////////////////////// ProfBegin("Convert Units"); - + for (U64 cu_idx = 0; cu_idx < cu_ranges.count; ++cu_idx) { Temp comp_temp = temp_begin(scratch.arena); - + DW_CompUnit *cu = &cu_arr[cu_idx]; - + // parse and build tag tree DW_TagTree tag_tree = dw_tag_tree_from_cu(comp_temp.arena, &input, cu); - + // build tag hash table for abstract origin resolution cu->tag_ht = dw_make_tag_hash_table(comp_temp.arena, tag_tree); - + String8 dwo_name = dw_string_from_attrib(&input, cu, cu->tag, DW_Attrib_DwoName); String8 gnu_dwo_name = dw_string_from_attrib(&input, cu, cu->tag, DW_Attrib_GNU_DwoName); if (dwo_name.size || gnu_dwo_name.size || cu->dwo_id) { // TODO: report that we dont support DWO continue; } - + // get unit's contribution ranges RDIM_Rng1U64List cu_voff_ranges = d2r_voff_ranges_from_cu_info_off(cu_contrib_map, cu_ranges.v[cu_idx].min); - + String8 cu_name = dw_string_from_attrib(&input, cu, cu->tag, DW_Attrib_Name); String8 cu_dir = dw_string_from_attrib(&input, cu, cu->tag, DW_Attrib_CompDir); String8 cu_prod = dw_string_from_attrib(&input, cu, cu->tag, DW_Attrib_Producer); DW_Language cu_lang = dw_const_u64_from_attrib(&input, cu, cu->tag, DW_Attrib_Language); - + RDIM_Unit *unit = rdim_unit_chunk_list_push(arena, &units, UNIT_CHUNK_CAP); unit->unit_name = cu_name; unit->compiler_name = cu_prod; @@ -1352,452 +1352,525 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) unit->language = rdi_language_from_dw_language(cu_lang); unit->line_table = cu_line_tables_rdi[cu_idx]; unit->voff_ranges = cu_voff_ranges; - + D2R_TypeTable *type_table = push_array(comp_temp.arena, D2R_TypeTable, 1); type_table->ht = hash_table_init(comp_temp.arena, 0x4000); type_table->types = &types; type_table->type_chunk_cap = TYPE_CHUNK_CAP; type_table->varg_type = d2r_create_type(arena, type_table); type_table->varg_type->kind = RDI_TypeKind_Variadic; - + D2R_TagNode *free_tags = push_array(comp_temp.arena, D2R_TagNode, 1); D2R_TagNode *tag_stack = push_array(comp_temp.arena, D2R_TagNode, 1); tag_stack->cur_node = tag_tree.root; - + while (tag_stack) { while (tag_stack->cur_node) { DW_TagNode *cur_node = tag_stack->cur_node; DW_Tag tag = cur_node->tag; B32 visit_children = 1; - + switch (tag.kind) { - case DW_Tag_Null: { - InvalidPath; - } break; - case DW_Tag_ClassType: { - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - - B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); - if (is_decl) { - type->kind = RDI_TypeKind_IncompleteClass; - - Assert(!cur_node->first_child); - visit_children = 0; - } else { - RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); - udt->self_type = type; - - type->kind = RDI_TypeKind_Class; - type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); - type->udt = udt; - type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - - tag_stack->type = type; - } - } break; - case DW_Tag_StructureType: { - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - - B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); - if (is_decl) { - type->kind = RDI_TypeKind_IncompleteStruct; - - // TODO: error handling - Assert(!cur_node->first_child); - visit_children = 0; - } else { - RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); - udt->self_type = type; - - type->kind = RDI_TypeKind_Struct; - type->udt = udt; - type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); + case DW_Tag_Null: { + InvalidPath; + } break; + case DW_Tag_ClassType: { + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - tag_stack->type = type; - } - } break; - case DW_Tag_UnionType: { - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - - B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); - if (is_decl) { - type->kind = RDI_TypeKind_IncompleteUnion; - - // TODO: error handling - Assert(!cur_node->first_child); - visit_children = 0; - } else { - RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); - udt->self_type = type; - - type->kind = RDI_TypeKind_Union; - type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); - type->udt = udt; - - tag_stack->type = type; - } - } break; - case DW_Tag_EnumerationType: { - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - - B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); - if (is_decl) { - type->kind = RDI_TypeKind_IncompleteEnum; - - // TODO: error handling - Assert(!cur_node->first_child); - visit_children = 0; - } else { - RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); - udt->self_type = type; - - type->kind = RDI_TypeKind_Enum; - type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); - type->udt = udt; - - tag_stack->type = type; - } - } break; - case DW_Tag_SubroutineType: { - // collect parameters - RDIM_TypeList param_list = {0}; - for (DW_TagNode *n = cur_node->first_child; n != 0; n = n->sibling) { - if (n->tag.kind == DW_Tag_FormalParameter) { - RDIM_Type *param_type = d2r_type_from_attrib(arena, type_table, &input, cu, n->tag, DW_Attrib_Type); - rdim_type_list_push(comp_temp.arena, ¶m_list, param_type); - } else if (n->tag.kind == DW_Tag_UnspecifiedParameters) { - rdim_type_list_push(comp_temp.arena, ¶m_list, type_table->varg_type); + B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); + if (is_decl) { + type->kind = RDI_TypeKind_IncompleteClass; + + Assert(!cur_node->first_child); + visit_children = 0; } else { + RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); + udt->self_type = type; + + type->kind = RDI_TypeKind_Class; + type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); + type->udt = udt; + type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + + tag_stack->type = type; + } + } break; + case DW_Tag_StructureType: { + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + + B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); + if (is_decl) { + type->kind = RDI_TypeKind_IncompleteStruct; + // TODO: error handling - AssertAlways(!"unexpected tag"); - } - } - - // init proceudre type - RDIM_Type *ret_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Function; - type->byte_size = arch_addr_size; - type->direct_type = ret_type; - type->count = param_list.count; - type->param_types = rdim_array_from_type_list(arena, param_list); - - visit_children = 0; - } break; - case DW_Tag_Typedef: { - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Alias; - type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - } break; - case DW_Tag_BaseType: { - DW_ATE encoding = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_Encoding); - U64 byte_size = dw_byte_size_from_tag(&input, cu, tag); - - // convert base type encoding to RDI version - RDI_TypeKind kind = RDI_TypeKind_NULL; - switch (encoding) { - case DW_ATE_Null: kind = RDI_TypeKind_NULL; break; - case DW_ATE_Address: kind = RDI_TypeKind_Void; break; - case DW_ATE_Boolean: kind = RDI_TypeKind_Bool; break; - case DW_ATE_ComplexFloat: { - switch (byte_size) { - case 4: kind = RDI_TypeKind_ComplexF32; break; - case 8: kind = RDI_TypeKind_ComplexF64; break; - case 10: kind = RDI_TypeKind_ComplexF80; break; - case 16: kind = RDI_TypeKind_ComplexF128; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling + Assert(!cur_node->first_child); + visit_children = 0; + } else { + RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); + udt->self_type = type; + + type->kind = RDI_TypeKind_Struct; + type->udt = udt; + type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); + + tag_stack->type = type; } } break; - case DW_ATE_Float: { - switch (byte_size) { - case 2: kind = RDI_TypeKind_F16; break; - case 4: kind = RDI_TypeKind_F32; break; - case 6: kind = RDI_TypeKind_F48; break; - case 8: kind = RDI_TypeKind_F64; break; - case 16: kind = RDI_TypeKind_F128; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling - } - } break; - case DW_ATE_Signed: { - switch (byte_size) { - case 1: kind = RDI_TypeKind_S8; break; - case 2: kind = RDI_TypeKind_S16; break; - case 4: kind = RDI_TypeKind_S32; break; - case 8: kind = RDI_TypeKind_S64; break; - case 16: kind = RDI_TypeKind_S128; break; - case 32: kind = RDI_TypeKind_S256; break; - case 64: kind = RDI_TypeKind_S512; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling - } - } break; - case DW_ATE_SignedChar: { - switch (byte_size) { - case 1: kind = RDI_TypeKind_Char8; break; - case 2: kind = RDI_TypeKind_Char16; break; - case 4: kind = RDI_TypeKind_Char32; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling - } - } break; - case DW_ATE_Unsigned: { - switch (byte_size) { - case 1: kind = RDI_TypeKind_U8; break; - case 2: kind = RDI_TypeKind_U16; break; - case 4: kind = RDI_TypeKind_U32; break; - case 8: kind = RDI_TypeKind_U64; break; - case 16: kind = RDI_TypeKind_U128; break; - case 32: kind = RDI_TypeKind_U256; break; - case 64: kind = RDI_TypeKind_U512; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling - } - } break; - case DW_ATE_UnsignedChar: { - switch (byte_size) { - case 1: kind = RDI_TypeKind_UChar8; break; - case 2: kind = RDI_TypeKind_UChar16; break; - case 4: kind = RDI_TypeKind_UChar32; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling - } - } break; - case DW_ATE_ImaginaryFloat: { - NotImplemented; - } break; - case DW_ATE_PackedDecimal: { - NotImplemented; - } break; - case DW_ATE_NumericString: { - NotImplemented; - } break; - case DW_ATE_Edited: { - NotImplemented; - } break; - case DW_ATE_SignedFixed: { - NotImplemented; - } break; - case DW_ATE_UnsignedFixed: { - NotImplemented; - } break; - case DW_ATE_DecimalFloat: { - NotImplemented; - } break; - case DW_ATE_Utf: { - NotImplemented; - } break; - case DW_ATE_Ucs: { - NotImplemented; - } break; - case DW_ATE_Ascii: { - NotImplemented; - } break; - default: AssertAlways(!"unexpected base type encoding"); break; // TODO: error handling - } - - RDIM_Type *base_type = rdim_builtin_type_from_kind(types, kind); - base_type->kind = kind; - base_type->byte_size = byte_size; - - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Alias; - type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - type->direct_type = base_type; - } break; - case DW_Tag_PointerType: { - RDIM_Type *direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - - // TODO: - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Allocated)); - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Associated)); - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Alignment)); - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_AddressClass)); - - U64 byte_size = arch_addr_size; - if (cu->version == DW_Version_5 || cu->relaxed) { - dw_try_byte_size_from_tag(&input, cu, tag, &byte_size); - } - - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Ptr; - type->byte_size = byte_size; - type->direct_type = direct_type; - } break; - case DW_Tag_RestrictType: { - // TODO: - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Alignment)); - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); - - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Modifier; - type->byte_size = arch_addr_size; - type->flags = RDI_TypeModifierFlag_Restrict; - type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - } break; - case DW_Tag_VolatileType: { - // TODO: - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); - - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Modifier; - type->byte_size = arch_addr_size; - type->flags = RDI_TypeModifierFlag_Volatile; - type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - } break; - case DW_Tag_ConstType: { - // TODO: - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Alignment)); - - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Modifier; - type->byte_size = arch_addr_size; - type->flags = RDI_TypeModifierFlag_Const; - type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - } break; - case DW_Tag_ArrayType: { - // * DWARF vs RDI Array Type Graph * - // - // For example lets take following decl: - // - // int (*foo[2])[3][4]; - // - // This compiles to in DWARF: - // - // foo -> DW_TAG_ArrayType -> (A0) DW_TAG_Subrange [2] - // \ - // -> (B0) DW_TAG_PointerType -> (A1) DW_TAG_ArrayType -> DW_TAG_Subrange [3] -> DW_Tag_Subrange [4] - // \ - // -> (B1) DW_TAG_BaseType (int) - // - // RDI expects: - // - // foo -> Array (2) -> Pointer -> Array (3) -> Array (4) -> int - // - // Note that DWARF forks the graph on DW_TAG_ArrayType to describe array ranges in branch A and - // in branch B describes array type which might be a struct, pointer, base type, or any other type tag. - // However, in RDI we have a simple list of type nodes and to convert we need to append type nodes from - // B to A. - - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Array; - type->direct_type = 0; - - U64 subrange_count = 0; - RDIM_Type *t = type; - for (DW_TagNode *n = cur_node->first_child; n != 0; n = n->sibling) { - if (n->tag.kind != DW_Tag_SubrangeType) { + case DW_Tag_UnionType: { + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + + B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); + if (is_decl) { + type->kind = RDI_TypeKind_IncompleteUnion; + // TODO: error handling - AssertAlways(!"unexpected tag"); - continue; - } - - if (subrange_count > 0) { - // init array type node - RDIM_Type *s = d2r_create_type(arena, type_table); - s->kind = RDI_TypeKind_Array; - s->direct_type = 0; - - // append new array type node - t->direct_type = s; - t = s; - } - - // resolve array lower bound - U64 lower_bound = 0; - if (dw_tag_has_attrib(&input, cu, n->tag, DW_Attrib_LowerBound)) { - lower_bound = dw_u64_from_attrib(&input, cu, n->tag, DW_Attrib_LowerBound); + Assert(!cur_node->first_child); + visit_children = 0; } else { - lower_bound = dw_pick_default_lower_bound(cu_lang); + RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); + udt->self_type = type; + + type->kind = RDI_TypeKind_Union; + type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); + type->udt = udt; + + tag_stack->type = type; } - - // resolve array upper bound - U64 upper_bound = 0; - if (dw_tag_has_attrib(&input, cu, n->tag, DW_Attrib_Count)) { - U64 count = dw_u64_from_attrib(&input, cu, n->tag, DW_Attrib_Count); - upper_bound = lower_bound + count; - } else if (dw_tag_has_attrib(&input, cu, n->tag, DW_Attrib_UpperBound)) { - upper_bound = dw_u64_from_attrib(&input, cu, n->tag, DW_Attrib_UpperBound); - // turn upper bound into exclusive range - upper_bound += 1; + } break; + case DW_Tag_EnumerationType: { + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + + B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); + if (is_decl) { + type->kind = RDI_TypeKind_IncompleteEnum; + + // TODO: error handling + Assert(!cur_node->first_child); + visit_children = 0; } else { - // zero size array + RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); + udt->self_type = type; + + type->kind = RDI_TypeKind_Enum; + type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); + type->udt = udt; + + tag_stack->type = type; } - - t->count = upper_bound - lower_bound; - ++subrange_count; - } - - Assert(t->direct_type == 0); - t->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - - visit_children = 0; - } break; - case DW_Tag_SubrangeType: { - // TODO: error handling - AssertAlways(!"unexpected tag"); - } break; - case DW_Tag_Inheritance: { - DW_TagNode *parent_node = tag_stack->next->cur_node; - if (parent_node->tag.kind != DW_Tag_StructureType && - parent_node->tag.kind != DW_Tag_ClassType) { + } break; + case DW_Tag_SubroutineType: { + // collect parameters + RDIM_TypeList param_list = {0}; + for (DW_TagNode *n = cur_node->first_child; n != 0; n = n->sibling) { + if (n->tag.kind == DW_Tag_FormalParameter) { + RDIM_Type *param_type = d2r_type_from_attrib(arena, type_table, &input, cu, n->tag, DW_Attrib_Type); + rdim_type_list_push(comp_temp.arena, ¶m_list, param_type); + } else if (n->tag.kind == DW_Tag_UnspecifiedParameters) { + rdim_type_list_push(comp_temp.arena, ¶m_list, type_table->varg_type); + } else { + // TODO: error handling + AssertAlways(!"unexpected tag"); + } + } + + // init proceudre type + RDIM_Type *ret_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Function; + type->byte_size = arch_addr_size; + type->direct_type = ret_type; + type->count = param_list.count; + type->param_types = rdim_array_from_type_list(arena, param_list); + + visit_children = 0; + } break; + case DW_Tag_Typedef: { + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Alias; + type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + } break; + case DW_Tag_BaseType: { + DW_ATE encoding = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_Encoding); + U64 byte_size = dw_byte_size_from_tag(&input, cu, tag); + + // convert base type encoding to RDI version + RDI_TypeKind kind = RDI_TypeKind_NULL; + switch (encoding) { + case DW_ATE_Null: kind = RDI_TypeKind_NULL; break; + case DW_ATE_Address: kind = RDI_TypeKind_Void; break; + case DW_ATE_Boolean: kind = RDI_TypeKind_Bool; break; + case DW_ATE_ComplexFloat: { + switch (byte_size) { + case 4: kind = RDI_TypeKind_ComplexF32; break; + case 8: kind = RDI_TypeKind_ComplexF64; break; + case 10: kind = RDI_TypeKind_ComplexF80; break; + case 16: kind = RDI_TypeKind_ComplexF128; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_Float: { + switch (byte_size) { + case 2: kind = RDI_TypeKind_F16; break; + case 4: kind = RDI_TypeKind_F32; break; + case 6: kind = RDI_TypeKind_F48; break; + case 8: kind = RDI_TypeKind_F64; break; + case 16: kind = RDI_TypeKind_F128; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_Signed: { + switch (byte_size) { + case 1: kind = RDI_TypeKind_S8; break; + case 2: kind = RDI_TypeKind_S16; break; + case 4: kind = RDI_TypeKind_S32; break; + case 8: kind = RDI_TypeKind_S64; break; + case 16: kind = RDI_TypeKind_S128; break; + case 32: kind = RDI_TypeKind_S256; break; + case 64: kind = RDI_TypeKind_S512; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_SignedChar: { + switch (byte_size) { + case 1: kind = RDI_TypeKind_Char8; break; + case 2: kind = RDI_TypeKind_Char16; break; + case 4: kind = RDI_TypeKind_Char32; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_Unsigned: { + switch (byte_size) { + case 1: kind = RDI_TypeKind_U8; break; + case 2: kind = RDI_TypeKind_U16; break; + case 4: kind = RDI_TypeKind_U32; break; + case 8: kind = RDI_TypeKind_U64; break; + case 16: kind = RDI_TypeKind_U128; break; + case 32: kind = RDI_TypeKind_U256; break; + case 64: kind = RDI_TypeKind_U512; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_UnsignedChar: { + switch (byte_size) { + case 1: kind = RDI_TypeKind_UChar8; break; + case 2: kind = RDI_TypeKind_UChar16; break; + case 4: kind = RDI_TypeKind_UChar32; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_ImaginaryFloat: { + NotImplemented; + } break; + case DW_ATE_PackedDecimal: { + NotImplemented; + } break; + case DW_ATE_NumericString: { + NotImplemented; + } break; + case DW_ATE_Edited: { + NotImplemented; + } break; + case DW_ATE_SignedFixed: { + NotImplemented; + } break; + case DW_ATE_UnsignedFixed: { + NotImplemented; + } break; + case DW_ATE_DecimalFloat: { + NotImplemented; + } break; + case DW_ATE_Utf: { + NotImplemented; + } break; + case DW_ATE_Ucs: { + NotImplemented; + } break; + case DW_ATE_Ascii: { + NotImplemented; + } break; + default: AssertAlways(!"unexpected base type encoding"); break; // TODO: error handling + } + + RDIM_Type *base_type = rdim_builtin_type_from_kind(types, kind); + base_type->kind = kind; + base_type->byte_size = byte_size; + + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Alias; + type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + type->direct_type = base_type; + } break; + case DW_Tag_PointerType: { + RDIM_Type *direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + + // TODO: + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Allocated)); + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Associated)); + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Alignment)); + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_AddressClass)); + + U64 byte_size = arch_addr_size; + if (cu->version == DW_Version_5 || cu->relaxed) { + dw_try_byte_size_from_tag(&input, cu, tag, &byte_size); + } + + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Ptr; + type->byte_size = byte_size; + type->direct_type = direct_type; + } break; + case DW_Tag_RestrictType: { + // TODO: + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Alignment)); + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); + + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Modifier; + type->byte_size = arch_addr_size; + type->flags = RDI_TypeModifierFlag_Restrict; + type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + } break; + case DW_Tag_VolatileType: { + // TODO: + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); + + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Modifier; + type->byte_size = arch_addr_size; + type->flags = RDI_TypeModifierFlag_Volatile; + type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + } break; + case DW_Tag_ConstType: { + // TODO: + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Alignment)); + + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Modifier; + type->byte_size = arch_addr_size; + type->flags = RDI_TypeModifierFlag_Const; + type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + } break; + case DW_Tag_ArrayType: { + // * DWARF vs RDI Array Type Graph * + // + // For example lets take following decl: + // + // int (*foo[2])[3][4]; + // + // This compiles to in DWARF: + // + // foo -> DW_TAG_ArrayType -> (A0) DW_TAG_Subrange [2] + // \ + // -> (B0) DW_TAG_PointerType -> (A1) DW_TAG_ArrayType -> DW_TAG_Subrange [3] -> DW_Tag_Subrange [4] + // \ + // -> (B1) DW_TAG_BaseType (int) + // + // RDI expects: + // + // foo -> Array (2) -> Pointer -> Array (3) -> Array (4) -> int + // + // Note that DWARF forks the graph on DW_TAG_ArrayType to describe array ranges in branch A and + // in branch B describes array type which might be a struct, pointer, base type, or any other type tag. + // However, in RDI we have a simple list of type nodes and to convert we need to append type nodes from + // B to A. + + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Array; + type->direct_type = 0; + + U64 subrange_count = 0; + RDIM_Type *t = type; + for (DW_TagNode *n = cur_node->first_child; n != 0; n = n->sibling) { + if (n->tag.kind != DW_Tag_SubrangeType) { + // TODO: error handling + AssertAlways(!"unexpected tag"); + continue; + } + + if (subrange_count > 0) { + // init array type node + RDIM_Type *s = d2r_create_type(arena, type_table); + s->kind = RDI_TypeKind_Array; + s->direct_type = 0; + + // append new array type node + t->direct_type = s; + t = s; + } + + // resolve array lower bound + U64 lower_bound = 0; + if (dw_tag_has_attrib(&input, cu, n->tag, DW_Attrib_LowerBound)) { + lower_bound = dw_u64_from_attrib(&input, cu, n->tag, DW_Attrib_LowerBound); + } else { + lower_bound = dw_pick_default_lower_bound(cu_lang); + } + + // resolve array upper bound + U64 upper_bound = 0; + if (dw_tag_has_attrib(&input, cu, n->tag, DW_Attrib_Count)) { + U64 count = dw_u64_from_attrib(&input, cu, n->tag, DW_Attrib_Count); + upper_bound = lower_bound + count; + } else if (dw_tag_has_attrib(&input, cu, n->tag, DW_Attrib_UpperBound)) { + upper_bound = dw_u64_from_attrib(&input, cu, n->tag, DW_Attrib_UpperBound); + // turn upper bound into exclusive range + upper_bound += 1; + } else { + // zero size array + } + + t->count = upper_bound - lower_bound; + ++subrange_count; + } + + Assert(t->direct_type == 0); + t->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + + visit_children = 0; + } break; + case DW_Tag_SubrangeType: { // TODO: error handling - AssertAlways(!"unexpected parent tag"); - } - - RDIM_Type *parent = tag_stack->next->type; - RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, parent->udt); - member->kind = RDI_MemberKind_Base; - member->type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - member->off = safe_cast_u32(dw_const_u32_from_attrib(&input, cu, tag, DW_Attrib_DataMemberLocation)); - } break; - case DW_Tag_Enumerator: { - DW_TagNode *parent_node = tag_stack->next->cur_node; - if (parent_node->tag.kind != DW_Tag_EnumerationType) { - // TODO: error handling - AssertAlways(!"unexpected parent tag"); - } - - RDIM_Type *type = tag_stack->next->type; - RDIM_UDTEnumVal *member = rdim_udt_push_enum_val(arena, &udts, type->udt); - member->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - member->val = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_ConstValue); - } break; - case DW_Tag_Member: { - DW_TagNode *parent_node = tag_stack->next->cur_node; - if (parent_node->tag.kind != DW_Tag_StructureType && - parent_node->tag.kind != DW_Tag_ClassType && - parent_node->tag.kind != DW_Tag_UnionType && - parent_node->tag.kind != DW_Tag_EnumerationType) { - // TODO: error handling - AssertAlways(!"unexpected parent tag"); - } - - DW_Attrib *data_member_location = dw_attrib_from_tag(&input, cu, tag, DW_Attrib_DataMemberLocation); - DW_AttribClass data_member_location_class = dw_value_class_from_attrib(cu, data_member_location); - if (data_member_location_class == DW_AttribClass_LocList) { - AssertAlways(!"UDT member with multiple locations are not supported"); - } - - RDIM_Type *type = tag_stack->next->type; - RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, type->udt); - member->kind = RDI_MemberKind_DataField; - member->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - member->type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - member->off = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_DataMemberLocation); - } break; - case DW_Tag_SubProgram: { - DW_InlKind inl = dw_u64_from_attrib(&input, cu, tag, DW_Attrib_Inline); - switch (inl) { - case DW_Inl_NotInlined: { + AssertAlways(!"unexpected tag"); + } break; + case DW_Tag_Inheritance: { + DW_TagNode *parent_node = tag_stack->next->cur_node; + if (parent_node->tag.kind != DW_Tag_StructureType && + parent_node->tag.kind != DW_Tag_ClassType) { + // TODO: error handling + AssertAlways(!"unexpected parent tag"); + } + + RDIM_Type *parent = tag_stack->next->type; + RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, parent->udt); + member->kind = RDI_MemberKind_Base; + member->type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + member->off = safe_cast_u32(dw_const_u32_from_attrib(&input, cu, tag, DW_Attrib_DataMemberLocation)); + } break; + case DW_Tag_Enumerator: { + DW_TagNode *parent_node = tag_stack->next->cur_node; + if (parent_node->tag.kind != DW_Tag_EnumerationType) { + // TODO: error handling + AssertAlways(!"unexpected parent tag"); + } + + RDIM_Type *type = tag_stack->next->type; + RDIM_UDTEnumVal *member = rdim_udt_push_enum_val(arena, &udts, type->udt); + member->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + member->val = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_ConstValue); + } break; + case DW_Tag_Member: { + DW_TagNode *parent_node = tag_stack->next->cur_node; + if (parent_node->tag.kind != DW_Tag_StructureType && + parent_node->tag.kind != DW_Tag_ClassType && + parent_node->tag.kind != DW_Tag_UnionType && + parent_node->tag.kind != DW_Tag_EnumerationType) { + // TODO: error handling + AssertAlways(!"unexpected parent tag"); + } + + DW_Attrib *data_member_location = dw_attrib_from_tag(&input, cu, tag, DW_Attrib_DataMemberLocation); + DW_AttribClass data_member_location_class = dw_value_class_from_attrib(cu, data_member_location); + if (data_member_location_class == DW_AttribClass_LocList) { + AssertAlways(!"UDT member with multiple locations are not supported"); + } + + RDIM_Type *type = tag_stack->next->type; + RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, type->udt); + member->kind = RDI_MemberKind_DataField; + member->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + member->type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + member->off = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_DataMemberLocation); + } break; + case DW_Tag_SubProgram: { + DW_InlKind inl = dw_u64_from_attrib(&input, cu, tag, DW_Attrib_Inline); + switch (inl) { + case DW_Inl_NotInlined: { + U64 param_count = 0; + RDIM_Type **params = d2r_collect_proc_params(arena, type_table, &input, cu, cur_node, ¶m_count); + + // get return type + RDIM_Type *ret_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + + // fill out proc type + RDIM_Type *proc_type = d2r_create_type(arena, type_table); + proc_type->kind = RDI_TypeKind_Function; + proc_type->byte_size = arch_addr_size; + proc_type->direct_type = ret_type; + proc_type->count = param_count; + proc_type->param_types = params; + + // get container type + RDIM_Type *container_type = 0; + if (dw_tag_has_attrib(&input, cu, tag, DW_Attrib_ContainingType)) { + container_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_ContainingType); + } + + // get frame base expression + String8 frame_base_expr = dw_exprloc_from_attrib(&input, cu, tag, DW_Attrib_FrameBase); + + // get proc container symbol + RDIM_Symbol *proc = rdim_symbol_chunk_list_push(arena, &procs, PROC_CHUNK_CAP ); + + // make scope + Rng1U64List ranges = d2r_range_list_from_tag(comp_temp.arena, &input, cu, image_base, tag); + RDIM_Scope *root_scope = d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, tag_stack, ranges); + root_scope->symbol = proc; + + // fill out proc + proc->is_extern = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_External); + proc->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + proc->link_name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_LinkageName); + proc->type = proc_type; + proc->container_symbol = 0; + proc->container_type = container_type; + proc->root_scope = root_scope; + proc->frame_base = d2r_locset_from_attrib(arena, &input, cu, &scopes, root_scope, image_base, arch, tag, DW_Attrib_FrameBase); + + // sub program with user-defined parent tag is a method + DW_TagKind parent_tag_kind = tag_stack->next->cur_node->tag.kind; + if (parent_tag_kind == DW_Tag_ClassType || parent_tag_kind == DW_Tag_StructureType) { + RDI_MemberKind member_kind = RDI_MemberKind_NULL; + DW_VirtualityKind virtuality = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_Virtuality); + switch (virtuality) { + case DW_VirtualityKind_None: member_kind = RDI_MemberKind_Method; break; + case DW_VirtualityKind_Virtual: member_kind = RDI_MemberKind_VirtualMethod; break; + case DW_VirtualityKind_PureVirtual: member_kind = RDI_MemberKind_VirtualMethod; break; // TODO: create kind for pure virutal + //default: InvalidPath; break; + } + + RDIM_Type *type = tag_stack->next->type; + RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, type->udt); + member->kind = member_kind; + member->type = type; + member->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + } else if (parent_tag_kind != DW_Tag_CompileUnit) { + //AssertAlways(!"unexpected tag"); + } + + tag_stack->scope = root_scope; + } break; + case DW_Inl_DeclaredNotInlined: + case DW_Inl_DeclaredInlined: + case DW_Inl_Inlined: { + visit_children = 0; + } break; + default: InvalidPath; break; + } + } break; + case DW_Tag_InlinedSubroutine: { U64 param_count = 0; - RDIM_Type **params = d2r_collect_proc_params(arena, type_table, &input, cu, cur_node, ¶m_count); - + RDIM_Type **params = d2r_collect_proc_params(arena, type_table, &input, cu, tag_stack->cur_node, ¶m_count); + // get return type RDIM_Type *ret_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - + // fill out proc type RDIM_Type *proc_type = d2r_create_type(arena, type_table); proc_type->kind = RDI_TypeKind_Function; @@ -1805,170 +1878,97 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) proc_type->direct_type = ret_type; proc_type->count = param_count; proc_type->param_types = params; - + // get container type - RDIM_Type *container_type = 0; + RDIM_Type *owner = 0; if (dw_tag_has_attrib(&input, cu, tag, DW_Attrib_ContainingType)) { - container_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_ContainingType); + owner = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_ContainingType); } - - // get frame base expression - String8 frame_base_expr = dw_exprloc_from_attrib(&input, cu, tag, DW_Attrib_FrameBase); - - // get proc container symbol - RDIM_Symbol *proc = rdim_symbol_chunk_list_push(arena, &procs, PROC_CHUNK_CAP ); - + + // fill out inline site + RDIM_InlineSite *inline_site = rdim_inline_site_chunk_list_push(arena, &inline_sites, INLINE_SITE_CHUNK_CAP); + inline_site->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + inline_site->type = proc_type; + inline_site->owner = owner; + inline_site->line_table = 0; + // make scope Rng1U64List ranges = d2r_range_list_from_tag(comp_temp.arena, &input, cu, image_base, tag); RDIM_Scope *root_scope = d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, tag_stack, ranges); - root_scope->symbol = proc; - - // fill out proc - proc->is_extern = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_External); - proc->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - proc->link_name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_LinkageName); - proc->type = proc_type; - proc->container_symbol = 0; - proc->container_type = container_type; - proc->root_scope = root_scope; - proc->frame_base = d2r_locset_from_attrib(arena, &input, cu, &scopes, root_scope, image_base, arch, tag, DW_Attrib_FrameBase); - - // sub program with user-defined parent tag is a method + root_scope->inline_site = inline_site; + } break; + case DW_Tag_Variable: { + String8 name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + RDIM_Type *type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + DW_TagKind parent_tag_kind = tag_stack->next->cur_node->tag.kind; - if (parent_tag_kind == DW_Tag_ClassType || parent_tag_kind == DW_Tag_StructureType) { - RDI_MemberKind member_kind = RDI_MemberKind_NULL; - DW_VirtualityKind virtuality = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_Virtuality); - switch (virtuality) { - case DW_VirtualityKind_None: member_kind = RDI_MemberKind_Method; break; - case DW_VirtualityKind_Virtual: member_kind = RDI_MemberKind_VirtualMethod; break; - case DW_VirtualityKind_PureVirtual: member_kind = RDI_MemberKind_VirtualMethod; break; // TODO: create kind for pure virutal - //default: InvalidPath; break; + if (parent_tag_kind == DW_Tag_SubProgram || + parent_tag_kind == DW_Tag_InlinedSubroutine || + parent_tag_kind == DW_Tag_LexicalBlock) { + RDIM_Scope *scope = tag_stack->next->scope; + RDIM_Local *local = rdim_scope_push_local(arena, &scopes, tag_stack->next->scope); + local->kind = RDI_LocalKind_Variable; + local->name = name; + local->type = type; + local->locset = d2r_var_locset_from_tag(arena, &input, cu, &scopes, scope, image_base, arch, tag); + } else { + + // NOTE: due to a bug in clang in stb_sprint.h local variables + // are declared in global scope without a name + if (name.size == 0) { + break; } - - RDIM_Type *type = tag_stack->next->type; - RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, type->udt); - member->kind = member_kind; - member->type = type; - member->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - } else if (parent_tag_kind != DW_Tag_CompileUnit) { - //AssertAlways(!"unexpected tag"); + + RDIM_Symbol *gvar = rdim_symbol_chunk_list_push(arena, &gvars, GVAR_CHUNK_CAP); + gvar->is_extern = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_External); + gvar->name = name; + gvar->link_name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_LinkageName); + gvar->type = type; + //gvar->locset = d2r_locset_from_attrib(arena, &input, cu, &scopes, global_scope, image_base, arch, tag, DW_Attrib_Location); + gvar->container_symbol = 0; + gvar->container_type = 0; // TODO: NotImplemented; } - - tag_stack->scope = root_scope; } break; - case DW_Inl_DeclaredNotInlined: - case DW_Inl_DeclaredInlined: - case DW_Inl_Inlined: { - visit_children = 0; - } break; - default: InvalidPath; break; - } - } break; - case DW_Tag_InlinedSubroutine: { - U64 param_count = 0; - RDIM_Type **params = d2r_collect_proc_params(arena, type_table, &input, cu, tag_stack->cur_node, ¶m_count); - - // get return type - RDIM_Type *ret_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - - // fill out proc type - RDIM_Type *proc_type = d2r_create_type(arena, type_table); - proc_type->kind = RDI_TypeKind_Function; - proc_type->byte_size = arch_addr_size; - proc_type->direct_type = ret_type; - proc_type->count = param_count; - proc_type->param_types = params; - - // get container type - RDIM_Type *owner = 0; - if (dw_tag_has_attrib(&input, cu, tag, DW_Attrib_ContainingType)) { - owner = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_ContainingType); - } - - // fill out inline site - RDIM_InlineSite *inline_site = rdim_inline_site_chunk_list_push(arena, &inline_sites, INLINE_SITE_CHUNK_CAP); - inline_site->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - inline_site->type = proc_type; - inline_site->owner = owner; - inline_site->line_table = 0; - - // make scope - Rng1U64List ranges = d2r_range_list_from_tag(comp_temp.arena, &input, cu, image_base, tag); - RDIM_Scope *root_scope = d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, tag_stack, ranges); - root_scope->inline_site = inline_site; - } break; - case DW_Tag_Variable: { - String8 name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - RDIM_Type *type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - - DW_TagKind parent_tag_kind = tag_stack->next->cur_node->tag.kind; - if (parent_tag_kind == DW_Tag_SubProgram || - parent_tag_kind == DW_Tag_InlinedSubroutine || - parent_tag_kind == DW_Tag_LexicalBlock) { - RDIM_Scope *scope = tag_stack->next->scope; - RDIM_Local *local = rdim_scope_push_local(arena, &scopes, tag_stack->next->scope); - local->kind = RDI_LocalKind_Variable; - local->name = name; - local->type = type; - local->locset = d2r_var_locset_from_tag(arena, &input, cu, &scopes, scope, image_base, arch, tag); - } else { - - // NOTE: due to a bug in clang in stb_sprint.h local variables - // are declared in global scope without a name - if (name.size == 0) { - break; + case DW_Tag_FormalParameter: { + DW_TagKind parent_tag_kind = tag_stack->next->cur_node->tag.kind; + if (parent_tag_kind == DW_Tag_SubProgram || parent_tag_kind == DW_Tag_InlinedSubroutine) { + RDIM_Scope *scope = tag_stack->next->scope; + RDIM_Local *param = rdim_scope_push_local(arena, &scopes, scope); + param->kind = RDI_LocalKind_Parameter; + param->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + param->type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + param->locset = d2r_var_locset_from_tag(arena, &input, cu, &scopes, scope, image_base, arch, tag); + } else { + // TODO: error handling + AssertAlways(!"this is a local variable"); } - - RDIM_Symbol *gvar = rdim_symbol_chunk_list_push(arena, &gvars, GVAR_CHUNK_CAP); - gvar->is_extern = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_External); - gvar->name = name; - gvar->link_name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_LinkageName); - gvar->type = type; - //gvar->locset = d2r_locset_from_attrib(arena, &input, cu, &scopes, global_scope, image_base, arch, tag, DW_Attrib_Location); - gvar->container_symbol = 0; - gvar->container_type = 0; // TODO: NotImplemented; - } - } break; - case DW_Tag_FormalParameter: { - DW_TagKind parent_tag_kind = tag_stack->next->cur_node->tag.kind; - if (parent_tag_kind == DW_Tag_SubProgram || parent_tag_kind == DW_Tag_InlinedSubroutine) { - RDIM_Scope *scope = tag_stack->next->scope; - RDIM_Local *param = rdim_scope_push_local(arena, &scopes, scope); - param->kind = RDI_LocalKind_Parameter; - param->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - param->type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - param->locset = d2r_var_locset_from_tag(arena, &input, cu, &scopes, scope, image_base, arch, tag); - } else { - // TODO: error handling - AssertAlways(!"this is a local variable"); - } - } break; - case DW_Tag_LexicalBlock: { - if (tag_stack->next->cur_node->tag.kind == DW_Tag_SubProgram || - tag_stack->next->cur_node->tag.kind == DW_Tag_InlinedSubroutine || - tag_stack->next->cur_node->tag.kind == DW_Tag_LexicalBlock) { - Rng1U64List ranges = d2r_range_list_from_tag(comp_temp.arena, &input, cu, image_base, tag); - d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, tag_stack, ranges); - } - } break; - case DW_Tag_CallSite: { - // TODO - } break; - case DW_Tag_CallSiteParameter: { - // TODO - } break; - case DW_Tag_Label: - case DW_Tag_CompileUnit: - case DW_Tag_UnspecifiedParameters: - break; - case DW_Tag_Namespace: break; - case DW_Tag_ImportedDeclaration: break; - case DW_Tag_PtrToMemberType: break; - case DW_Tag_TemplateTypeParameter: break; - case DW_Tag_ReferenceType: break; - default: NotImplemented; break; + } break; + case DW_Tag_LexicalBlock: { + if (tag_stack->next->cur_node->tag.kind == DW_Tag_SubProgram || + tag_stack->next->cur_node->tag.kind == DW_Tag_InlinedSubroutine || + tag_stack->next->cur_node->tag.kind == DW_Tag_LexicalBlock) { + Rng1U64List ranges = d2r_range_list_from_tag(comp_temp.arena, &input, cu, image_base, tag); + d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, tag_stack, ranges); + } + } break; + case DW_Tag_CallSite: { + // TODO + } break; + case DW_Tag_CallSiteParameter: { + // TODO + } break; + case DW_Tag_Label: + case DW_Tag_CompileUnit: + case DW_Tag_UnspecifiedParameters: + break; + case DW_Tag_Namespace: break; + case DW_Tag_ImportedDeclaration: break; + case DW_Tag_PtrToMemberType: break; + case DW_Tag_TemplateTypeParameter: break; + case DW_Tag_ReferenceType: break; + default: NotImplemented; break; } - + if (tag_stack->cur_node->first_child && visit_children) { D2R_TagNode *frame = free_tags; if (frame) { @@ -1983,22 +1983,22 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) tag_stack->cur_node = tag_stack->cur_node->sibling; } } - + // recycle free frame D2R_TagNode *frame = tag_stack; SLLStackPop(tag_stack); SLLStackPush(free_tags, frame); - + if (tag_stack) { tag_stack->cur_node = tag_stack->cur_node->sibling; } } - + temp_end(comp_temp); } - + ProfEnd(); - + { for (RDIM_TypeChunkNode *chunk_n = types.first; chunk_n != 0; chunk_n = chunk_n->next) { for (U64 i = 0; i < chunk_n->count; ++i) { @@ -2014,18 +2014,18 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) } } } - + { RDIM_TypeNode *type_stack = 0; RDIM_TypeNode *free_types = 0; - + for (RDIM_TypeChunkNode *chunk_n = types.first; chunk_n != 0; chunk_n = chunk_n->next) { for (U64 i = 0; i < chunk_n->count; ++i) { RDIM_Type *type = &chunk_n->v[i]; if (type->kind == RDI_TypeKind_Array) { if (type->byte_size != 0) continue; - + RDIM_Type *t; for (t = type; t != 0 && t->kind == RDI_TypeKind_Array; t = t->direct_type) { RDIM_TypeNode *f = free_types; @@ -2037,12 +2037,12 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) f->v = t; SLLStackPush(type_stack, f); } - + U64 base_type_size = 0; if (t) { base_type_size = t->byte_size; } - + U64 array_size = base_type_size; while (type_stack) { if (type_stack->v->count) { @@ -2052,10 +2052,10 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) } SLLStackPop(type_stack); } - + type->count = 0; type->byte_size = array_size; - + // recycle frames free_types = type_stack; type_stack = 0; @@ -2063,23 +2063,23 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) } } } - + //////////////////////////////// - - RDIM_BakeParams *bake_params = push_array(arena, RDIM_BakeParams, 1); - bake_params->top_level_info = top_level_info; - bake_params->binary_sections = binary_sections; - bake_params->units = units; - bake_params->types = types; - bake_params->udts = udts; - bake_params->src_files = src_files; - bake_params->line_tables = line_tables; - bake_params->global_variables = gvars; - bake_params->thread_variables = tvars; - bake_params->procedures = procs; - bake_params->scopes = scopes; - bake_params->inline_sites = inline_sites; - + + RDIM_BakeParams bake_params = {0}; + bake_params.top_level_info = top_level_info; + bake_params.binary_sections = binary_sections; + bake_params.units = units; + bake_params.types = types; + bake_params.udts = udts; + bake_params.src_files = src_files; + bake_params.line_tables = line_tables; + bake_params.global_variables = gvars; + bake_params.thread_variables = tvars; + bake_params.procedures = procs; + bake_params.scopes = scopes; + bake_params.inline_sites = inline_sites; + scratch_end(scratch); return bake_params; } @@ -2089,23 +2089,23 @@ rdi_language_from_dw_language(DW_Language v) { RDI_Language result = RDI_Language_NULL; switch (v) { - case DW_Language_Null: result = RDI_Language_NULL; break; - - case DW_Language_C89: - case DW_Language_C99: - case DW_Language_C11: - case DW_Language_C: + case DW_Language_Null: result = RDI_Language_NULL; break; + + case DW_Language_C89: + case DW_Language_C99: + case DW_Language_C11: + case DW_Language_C: result = RDI_Language_C; break; - - case DW_Language_CPlusPlus03: - case DW_Language_CPlusPlus11: - case DW_Language_CPlusPlus14: - case DW_Language_CPlusPlus: + + case DW_Language_CPlusPlus03: + case DW_Language_CPlusPlus11: + case DW_Language_CPlusPlus14: + case DW_Language_CPlusPlus: result = RDI_Language_CPlusPlus; break; - - default: NotImplemented; break; + + default: NotImplemented; break; } return result; } @@ -2118,7 +2118,7 @@ rdi_reg_from_dw_reg_x86(DW_RegX86 v) #define X(reg_dw, val_dw, reg_rdi, ...) case DW_RegX86_##reg_dw: result = RDI_RegCodeX86_##reg_rdi; break; DW_Regs_X86_XList(X) #undef X - default: NotImplemented; break; + default: NotImplemented; break; } return result; } @@ -2131,7 +2131,7 @@ rdi_reg_from_dw_reg_x64(DW_RegX64 v, RDI_RegCodeX64 *code_out, U64 *off_out, U64 #define X(reg_dw, val_dw, reg_rdi, off, size) case DW_RegX64_##reg_dw: result = RDI_RegCodeX64_##reg_rdi; *off_out = off; *size_out = size; break; DW_Regs_X64_XList(X) #undef X - default: NotImplemented; break; + default: NotImplemented; break; } return result; } @@ -2141,11 +2141,10 @@ rdi_reg_from_dw_reg(Arch arch, DW_Reg v, RDI_RegCode *code_out, U64 *off_out, U6 { RDI_RegCode result = RDI_RegCode_nil; switch (arch) { - case Arch_Null: break; - case Arch_x86: ; break; - case Arch_x64: return rdi_reg_from_dw_reg_x64(v, code_out, off_out, size_out); - default: NotImplemented; break; + case Arch_Null: break; + case Arch_x86: ; break; + case Arch_x64: return rdi_reg_from_dw_reg_x64(v, code_out, off_out, size_out); + default: NotImplemented; break; } return 0; } - diff --git a/src/radcon/radcon_dwarf.h b/src/radcon/radcon_dwarf.h index 3029b314..7e802ca6 100644 --- a/src/radcon/radcon_dwarf.h +++ b/src/radcon/radcon_dwarf.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADCON_DWARF_H @@ -22,9 +22,9 @@ typedef struct D2R_TagNode typedef struct D2R_CompUnitContribMap { - U64 count; - U64 *info_off_arr; - RDIM_Rng1U64List *voff_range_arr; + U64 count; + U64 *info_off_arr; + RDIM_Rng1U64ChunkList *voff_range_arr; } D2R_CompUnitContribMap; //////////////////////////////// diff --git a/src/radcon/radcon_elf.c b/src/radcon/radcon_elf.c index d5ab8333..4ff07e9f 100644 --- a/src/radcon/radcon_elf.c +++ b/src/radcon/radcon_elf.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal RDIM_BinarySectionList diff --git a/src/radcon/radcon_elf.h b/src/radcon/radcon_elf.h index dadb2ae2..9625ff18 100644 --- a/src/radcon/radcon_elf.h +++ b/src/radcon/radcon_elf.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADCON_ELF_H diff --git a/src/radcon/radcon_main.c b/src/radcon/radcon_main.c index 9f3c2b0a..38270579 100644 --- a/src/radcon/radcon_main.c +++ b/src/radcon/radcon_main.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #define BUILD_TITLE "Epic Games Tools (R) RAD Debug Info Converter" diff --git a/src/radcon/radcon_pdb.c b/src/radcon/radcon_pdb.c index 453c5b75..752b2286 100644 --- a/src/radcon/radcon_pdb.c +++ b/src/radcon/radcon_pdb.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) // TODO(rjf): eliminate redundant null checks, just always allocate @@ -400,12 +400,12 @@ ASYNC_WORK_DEF(p2r_units_convert_work) } // rjf: build line table, fill with parsed binary annotations - + if(inlinee_lines_parsed != 0) { // rjf: grab checksums sub-section CV_C13SubSectionNode *file_chksms = unit_c13->file_chksms_sub_section; - + // rjf: gathered lines typedef struct LineChunk LineChunk; struct LineChunk @@ -423,12 +423,12 @@ ASYNC_WORK_DEF(p2r_units_convert_work) U32 last_file_off = max_U32; U32 curr_file_off = max_U32; RDIM_LineTable* line_table = 0; - + CV_C13InlineSiteDecoder decoder = cv_c13_inline_site_decoder_init(inlinee_lines_parsed->file_off, inlinee_lines_parsed->first_source_ln, base_voff); for(;;) { CV_C13InlineSiteDecoderStep step = cv_c13_inline_site_decoder_step(&decoder, binary_annots); - + if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitFile) { last_file_off = curr_file_off; @@ -442,7 +442,7 @@ ASYNC_WORK_DEF(p2r_units_convert_work) if((last_file_off != max_U32 && last_file_off != curr_file_off)) { String8 seq_file_name = {0}; - + if(last_file_off + sizeof(CV_C13Checksum) <= file_chksms->size) { CV_C13Checksum *checksum = (CV_C13Checksum*)(unit_c13->data.str + file_chksms->off + last_file_off); @@ -514,7 +514,7 @@ ASYNC_WORK_DEF(p2r_units_convert_work) first_line_chunk = last_line_chunk = 0; total_line_chunk_line_count = 0; } - + if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitLine) { LineChunk *chunk = last_line_chunk; @@ -532,7 +532,7 @@ ASYNC_WORK_DEF(p2r_units_convert_work) chunk->count += 1; total_line_chunk_line_count += 1; } - + if(step.flags == 0) { break; @@ -1479,7 +1479,7 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work) { container_symbol = top_scope_node->scope->symbol; } - + // form a VOFF location #if 0 RDIM_LocationSet locset = {0}; @@ -1716,7 +1716,7 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work) RDIM_Location *tls_off_loc = rdim_push_location_tls_off(arena, tls_off); rdim_location_set_push_case(arena, &locset, (RDIM_Rng1U64){0,max_U64}, tls_off_loc); #endif - + // rjf: build symbol RDIM_Symbol *tvar = rdim_symbol_chunk_list_push(arena, &sym_thread_variables, sym_thread_variables_chunk_cap); tvar->name = name; @@ -2063,14 +2063,14 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work) for(;;) { CV_C13InlineSiteDecoderStep step = cv_c13_inline_site_decoder_step(&decoder, binary_annots); - + if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitRange) { // rjf: build new range & add to scope RDIM_Rng1U64 voff_range = { step.range.min, step.range.max }; rdim_scope_push_voff_range(arena, &sym_scopes, scope, voff_range); } - + if(step.flags & CV_C13InlineSiteDecoderStepFlag_ExtendLastRange) { if(scope->voff_ranges.last != 0) @@ -2078,7 +2078,7 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work) scope->voff_ranges.last->v.max = step.range.max; } } - + if(step.flags == 0) { break; @@ -2124,11 +2124,11 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work) //////////////////////////////// //~ rjf: Top-Level Conversion Entry Point -internal RDIM_BakeParams * +internal RDIM_BakeParams p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) { Temp scratch = scratch_begin(&arena, 1); - + g_p2r_local_state = local_state; ////////////////////////////////////////////////////////////// @@ -2153,7 +2153,7 @@ p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) named_streams = pdb_named_stream_table_from_info(arena, info); MemoryCopyStruct(&auth_guid, &info->auth_guid); scratch_end(scratch); - + if (info->features & PDB_FeatureFlag_MINIMAL_DBG_INFO) { fprintf(stderr, "ERROR: PDB was linked with /DEBUG:FASTLINK (partial debug info is not supported). Please relink using /DEBUG:FULL."); os_abort(1); @@ -2372,7 +2372,7 @@ p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) //- rjf: produce top-level-info // RDIM_TopLevelInfo top_level_info = rdim_make_top_level_info(in->image_name, arch_from_coff_machine(dbi->machine_type), exe_hash, binary_sections); - + ////////////////////////////////////////////////////////////// //- rjf: kick off unit conversion & source file collection // @@ -2450,7 +2450,7 @@ p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) if(in->flags & RC_Flag_Types) ProfScope("types pass 1: construct all root/stub types from TPI") { itype_type_ptrs = push_array(arena, RDIM_Type *, tpi_leaf->itype_opl); - + ////////////////////////// //- build basic types // @@ -2463,7 +2463,7 @@ p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) RDI_TypeKind ulong_type = rdim_unsigned_long_type_from_data_model(data_model); RDI_TypeKind ulong_long_type = rdim_unsigned_long_long_type_from_data_model(data_model); RDI_TypeKind ptr_type = rdim_pointer_size_t_type_from_data_model(data_model); - + struct { char * name; @@ -2518,7 +2518,7 @@ p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) { "char32_t" , RDI_TypeKind_Char32 , CV_BasicType_CHAR32 , 1, 1, 1 }, // always UTF-32 { "__pointer" , ptr_type , CV_BasicType_PTR , 0, 0, 0 } }; - + for(U64 i = 0; i < ArrayCount(table); i += 1) { RDIM_Type *type = rdim_type_chunk_list_push(arena, &all_types, tpi_leaf->itype_opl); @@ -2526,7 +2526,7 @@ p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) type->name = str8_cstring(table[i].name); type->direct_type = rdim_builtin_type_from_kind(all_types, table[i].kind_rdi); itype_type_ptrs[table[i].kind_cv] = type; - + if(table[i].make_pointer_near) { CV_TypeIndex near_ptr_itype = table[i].kind_cv | 0x100; @@ -2556,7 +2556,7 @@ p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) } } } - + ////////////////////////// //- rjf: build complex type // @@ -2566,7 +2566,7 @@ p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) CV_RecRange *range = &tpi_leaf->leaf_ranges.ranges[itype-tpi_leaf->itype_first]; CV_LeafKind kind = range->hdr.kind; U64 header_struct_size = cv_header_struct_size_from_leaf_kind(kind); - + if(range->off+range->hdr.size <= tpi_leaf->data.size && range->off+2+header_struct_size <= tpi_leaf->data.size && range->hdr.size >= 2) @@ -2823,7 +2823,7 @@ p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) { dst_type->kind = (kind == CV_LeafKind_CLASS ? RDI_TypeKind_Class : RDI_TypeKind_Struct); } - + B32 do_unique_name_lookup = (((lf->props & CV_TypeProp_Scoped) != 0) && ((lf->props & CV_TypeProp_HasUniqueName) != 0)); if(do_unique_name_lookup) @@ -2831,7 +2831,7 @@ p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) U8 *unique_name_ptr = name_ptr + name.size + 1; dst_type->link_name = str8_cstring_capped(unique_name_ptr, itype_leaf_opl); } - + dst_type->name = name; dst_type->byte_size = safe_cast_u32(size_u64); }break; @@ -2863,7 +2863,7 @@ p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) dst_type->byte_size = (U32)size_u64; dst_type->name = name; } - + B32 do_unique_name_lookup = (((lf->props & CV_TypeProp_Scoped) != 0) && ((lf->props & CV_TypeProp_HasUniqueName) != 0)); if(do_unique_name_lookup) @@ -2899,7 +2899,7 @@ p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) dst_type->byte_size = (U32)size_u64; dst_type->name = name; } - + B32 do_unique_name_lookup = (((lf->props & CV_TypeProp_Scoped) != 0) && ((lf->props & CV_TypeProp_HasUniqueName) != 0)); if(do_unique_name_lookup) @@ -2934,7 +2934,7 @@ p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in) dst_type->byte_size = direct_type ? direct_type->byte_size : 0; dst_type->name = name; } - + B32 do_unique_name_lookup = (((lf->props & CV_TypeProp_Scoped) != 0) && ((lf->props & CV_TypeProp_HasUniqueName) != 0)); if(do_unique_name_lookup) diff --git a/src/radcon/radcon_pdb.h b/src/radcon/radcon_pdb.h index 7f7aaf72..89c8472c 100644 --- a/src/radcon/radcon_pdb.h +++ b/src/radcon/radcon_pdb.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADCON_PDB_H @@ -226,7 +226,7 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work); //////////////////////////////// //~ rjf: Top-Level Conversion Entry Point -internal RDIM_BakeParams *p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in); +internal RDIM_BakeParams p2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in); //////////////////////////////// diff --git a/src/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index 89359b92..78607454 100644 --- a/src/raddbg/generated/raddbg.meta.c +++ b/src/raddbg/generated/raddbg.meta.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE @@ -60,7 +60,7 @@ str8_lit_comp(""), str8_lit_comp(""), }; -RD_VocabInfo rd_vocab_info_table[343] = +RD_VocabInfo rd_vocab_info_table[345] = { {str8_lit_comp("type_view"), str8_lit_comp("type_views"), str8_lit_comp("Type View"), str8_lit_comp("Type Views"), RD_IconKind_Binoculars}, {str8_lit_comp("file_path_map"), str8_lit_comp("file_path_maps"), str8_lit_comp("File Path Map"), str8_lit_comp("File Path Maps"), RD_IconKind_FileOutline}, @@ -275,6 +275,8 @@ RD_VocabInfo rd_vocab_info_table[343] = {str8_lit_comp("open_recent_project"), str8_lit_comp(""), str8_lit_comp("Open Recent Project"), str8_lit_comp(""), RD_IconKind_Briefcase}, {str8_lit_comp("save_user"), str8_lit_comp(""), str8_lit_comp("Save User"), str8_lit_comp(""), RD_IconKind_Save}, {str8_lit_comp("save_project"), str8_lit_comp(""), str8_lit_comp("Save Project"), str8_lit_comp(""), RD_IconKind_Save}, +{str8_lit_comp("record_user_as_last_opened"), str8_lit_comp(""), str8_lit_comp("Record User As Last Opened"), str8_lit_comp(""), RD_IconKind_Null}, +{str8_lit_comp("record_project_in_user"), str8_lit_comp(""), str8_lit_comp("Records Project In User"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("write_user_data"), str8_lit_comp(""), str8_lit_comp("Write User Data"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("write_project_data"), str8_lit_comp(""), str8_lit_comp("Write Project Data"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("user_settings"), str8_lit_comp(""), str8_lit_comp("User Settings"), str8_lit_comp(""), RD_IconKind_Gear}, @@ -410,15 +412,15 @@ RD_VocabInfo rd_vocab_info_table[343] = RD_NameSchemaInfo rd_name_schema_info_table[24] = { {str8_lit_comp("user"), str8_lit_comp("@expand_commands(edit_user_theme) x:\n{\n //- rjf: animations\n @display_name('Animations') @description(\"Enables animations.\")\n @default(1) 'animations': bool,\n @display_name('Scrolling Animations') @description(\"Enables scrolling animations.\")\n @expand_if(\"$.animations\") @default(1) 'scrolling_animations': bool,\n @display_name('Tooltip Animations') @description(\"Enables tooltip animations.\")\n @expand_if(\"$.animations\") @default(1) 'tooltip_animations': bool,\n @display_name('Menu Animations') @description(\"Enables menu animations.\")\n @expand_if(\"$.animations\") @default(1) 'menu_animations': bool,\n\n //- rjf: fonts\n @display_name('UI Font') @description(\"The name of, or path to, the font used when displaying non-code UI elements.\")\n @default('') 'main_font': string,\n @display_name('Code Font') @description(\"The name of, or path to, the font used when displaying code.\")\n @default('') 'code_font': string,\n\n //- rjf: theme\n @default(\"Default (Dark)\") @display_name('User Theme')\n @description(\"The user's theme, which describes all colors used throughout the UI.\")\n 'theme': string,\n @no_expand @display_name('User Theme')\n 'theme_colors': query,\n\n //- rjf: autocompletion\n @display_name('Autocompletion Lister') @description(\"Enables the autocompletion lister while typing expressions.\") @default(1)\n 'autocompletion_lister': bool,\n @display_name('View Call Argument Helper') @description(\"Enables the view call argument helper, which shows view arguments and documentation, while typing expressions.\") @default(1)\n 'view_call_argument_helper': bool,\n\n //- rjf: thread & breakpoint decorations\n @default(1) @display_name('Thread Lines') @description(\"Controls whether or not a long horizontal line is drawn before the next line or instruction that the selected thread will execute in source and disassembly views.\")\n 'thread_lines': bool,\n @default(1) @display_name('Thread Glow') @description(\"Controls whether or not a glowing effect is drawn on the selected thread in source and disassembly views.\")\n 'thread_glow': bool,\n @default(1) @display_name('Breakpoint Lines') @description(\"Controls whether or not a long horizontal line is drawn before the line or instruction at which a breakpoint is placed, in source and disassembly views.\")\n 'breakpoint_lines': bool,\n @default(1) @display_name('Breakpoint Glow') @description(\"Controls whether or not a glowing effect is drawn on breakpoints in source and disassembly views.\")\n 'breakpoint_glow': bool,\n\n //- rjf: occluding background settings\n @default(0) @display_name('Opaque Backgrounds') @description(\"Controls whether or not all floating background colors are forced to be fully opaque.\")\n 'opaque_backgrounds': bool,\n @default(1) @display_name('Background Blur') @description(\"Controls whether or not occluded regions behind floating elements are blurred.\")\n 'background_blur': bool,\n\n //- rjf: appearance settings\n @default(1) @display_name('Drop Shadows') @description(\"Controls whether or not drop shadows are drawn.\")\n 'drop_shadows': bool,\n @default(1.f) @display_name('Rounded Corner Amount') @description(\"Controls the degree to which UI corners are rounded.\")\n 'rounded_corner_amount': @range[0, 1] f32,\n\n //- rjf: code formatting settings\n @default(2) @display_name('User Tab Width') 'tab_width': @range[1, 32] u64,\n\n //- rjf: windows style menu bar\n @default(1) @display_name('Focus Menu Bar With Alt') @description(\"Mimics standard Windows behavior of focusing the menu bar using the Alt key.\")\n 'focus_menu_bar_with_alt': bool,\n\n //- rjf: native filesystem dialogues\n @default(0) @display_name('Use Native File System Dialog') @description(\"Uses the operating system's file system dialog box, rather than the debugger's built-in UI.\")\n 'use_native_file_system_dialog': bool,\n}\n")}, -{str8_lit_comp("project"), str8_lit_comp("@expand_commands(edit_project_theme) x:\n{\n @default(2) @display_name('Project Tab Width') 'tab_width': @range[1, 32] u64,\n\n //- rjf: visualizers\n @display_name('Use Default C++ STL Type Visualizers') @description(\"Enables the built-in type views for C++ STL types.\")\n @default(1) use_default_stl_type_views: bool,\n // @display_name('Use Default Unreal Engine Type Visualizers') @description(\"Enables the built-in type views for Unreal Engine types.\")\n // @default(1) use_default_ue_type_views: bool,\n\n //- rjf: theme\n @default(\"None\") @display_name('Project Theme') @description(\"The project's theme, which describes all colors used throughout the UI, and can override the user's theme.\")\n 'theme': string,\n @no_expand @display_name('Project Theme') @description(\"The project's theme, which describes all colors used throughout the UI, and can override the user's theme.\")\n 'theme_colors': query,\n\n //- rjf: exception settings\n @default(1) @display_name(\"Break On Win32 Control-C Exceptions\") @description(\"Code: 0x40010005\")\n win32_ctrl_c: bool;\n @default(1) @display_name(\"Break On Win32 Control-Break Exceptions\") @description(\"Code: 0x40010008\")\n win32_ctrl_break: bool;\n @default(0) @display_name(\"Break On Win32 WinRT Originate Error Exceptions\") @description(\"Code: 0x40080201\")\n win32_win_rt_originate_error: bool;\n @default(0) @display_name(\"Break On Win32 WinRT Transform Error Exceptions\") @description(\"Code: 0x40080202\")\n win32_win_rt_transform_error: bool;\n @default(0) @display_name(\"Break On Win32 RPC Call Cancelled Exceptions\") @description(\"Code: 0x0000071a\")\n win32_rpc_call_cancelled: bool;\n @default(0) @display_name(\"Break On Win32 Data Type Misalignment Exceptions\") @description(\"Code: 0x80000002\")\n win32_datatype_misalignment: bool;\n @default(1) @display_name(\"Break On Win32 Access Violation Exceptions\") @description(\"Code: 0xc0000005\")\n win32_access_violation: bool;\n @default(0) @display_name(\"Break On Win32 In Page Error Exceptions\") @description(\"Code: 0xc0000006\")\n win32_in_page_error: bool;\n @default(1) @display_name(\"Break On Win32 Invalid Handle Specified Exceptions\") @description(\"Code: 0xc0000008\")\n win32_invalid_handle: bool;\n @default(0) @display_name(\"Break On Win32 Not Enough Quota Exceptions\") @description(\"Code: 0xc0000017\")\n win32_not_enough_quota: bool;\n @default(0) @display_name(\"Break On Win32 Illegal Instruction Exceptions\") @description(\"Code: 0xc000001d\")\n win32_illegal_instruction: bool;\n @default(0) @display_name(\"Break On Win32 Cannot Continue From Exception Exceptions\") @description(\"Code: 0xc0000025\")\n win32_cannot_continue_exception: bool;\n @default(0) @display_name(\"Break On Win32 Invalid Exception Disposition Returned By Handler Exceptions\") @description(\"Code: 0xc0000026\")\n win32_invalid_exception_disposition: bool;\n @default(0) @display_name(\"Break On Win32 Array Bounds Exceeded Exceptions\") @description(\"Code: 0xc000008c\")\n win32_array_bounds_exceeded: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Denormal Operand Exceptions\") @description(\"Code: 0xc000008d\")\n win32_floating_point_denormal_operand: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Division By Zero Exceptions\") @description(\"Code: 0xc000008e\")\n win32_floating_point_division_by_zero: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Inexact Result Exceptions\") @description(\"Code: 0xc000008f\")\n win32_floating_point_inexact_result: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Invalid Operation Exceptions\") @description(\"Code: 0xc0000090\")\n win32_floating_point_invalid_operation: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Overflow Exceptions\") @description(\"Code: 0xc0000091\")\n win32_floating_point_overflow: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Stack Check Exceptions\") @description(\"Code: 0xc0000092\")\n win32_floating_point_stack_check: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Underflow Exceptions\") @description(\"Code: 0xc0000093\")\n win32_floating_point_underflow: bool;\n @default(0) @display_name(\"Break On Win32 Integer Division By Zero Exceptions\") @description(\"Code: 0xc0000094\")\n win32_integer_division_by_zero: bool;\n @default(0) @display_name(\"Break On Win32 Integer Overflow Exceptions\") @description(\"Code: 0xc0000095\")\n win32_integer_overflow: bool;\n @default(0) @display_name(\"Break On Win32 Privileged Instruction Exceptions\") @description(\"Code: 0xc0000096\")\n win32_privileged_instruction: bool;\n @default(0) @display_name(\"Break On Win32 Stack Overflow Exceptions\") @description(\"Code: 0xc00000fd\")\n win32_stack_overflow: bool;\n @default(0) @display_name(\"Break On Win32 Unable To Locate DLL Exceptions\") @description(\"Code: 0xc0000135\")\n win32_unable_to_locate_dll: bool;\n @default(0) @display_name(\"Break On Win32 Ordinal Not Found Exceptions\") @description(\"Code: 0xc0000138\")\n win32_ordinal_not_found: bool;\n @default(0) @display_name(\"Break On Win32 Entry Point Not Found Exceptions\") @description(\"Code: 0xc0000139\")\n win32_entry_point_not_found: bool;\n @default(0) @display_name(\"Break On Win32 DLL Initialization Failed Exceptions\") @description(\"Code: 0xc0000142\")\n win32_dll_initialization_failed: bool;\n @default(0) @display_name(\"Break On Win32 Floating Point SSE Multiple Faults Exceptions\") @description(\"Code: 0xc00002b4\")\n win32_floating_point_sse_multiple_faults: bool;\n @default(0) @display_name(\"Break On Win32 Floating Point SSE Multiple Traps Exceptions\") @description(\"Code: 0xc00002b5\")\n win32_floating_point_sse_multiple_traps: bool;\n @default(1) @display_name(\"Break On Win32 Assertion Failed Exceptions\") @description(\"Code: 0xc0000420\")\n win32_assertion_failed: bool;\n @default(0) @display_name(\"Break On Win32 Module Not Found Exceptions\") @description(\"Code: 0xc06d007e\")\n win32_module_not_found: bool;\n @default(0) @display_name(\"Break On Win32 Procedure Not Found Exceptions\") @description(\"Code: 0xc06d007f\")\n win32_procedure_not_found: bool;\n @default(1) @display_name(\"Break On Win32 Sanitizer Error Detected Exceptions\") @description(\"Code: 0xe073616e\")\n win32_sanitizer_error_detected: bool;\n @default(0) @display_name(\"Break On Win32 Sanitizer Raw Access Violation Exceptions\") @description(\"Code: 0xe0736171\")\n win32_sanitizer_raw_access_violation: bool;\n @default(1) @display_name(\"Break On Win32 DirectX Debug Layer Exceptions\") @description(\"Code: 0x0000087a\")\n win32_directx_debug_layer: bool;\n}\n")}, +{str8_lit_comp("project"), str8_lit_comp("@expand_commands(edit_project_theme) x:\n{\n @default(2) @display_name('Project Tab Width') 'tab_width': @range[1, 32] u64,\n\n //- rjf: visualizers\n @display_name('Use Default C++ STL Type Visualizers') @description(\"Enables the built-in type views for C++ STL types.\")\n @default(1) use_default_stl_type_views: bool,\n @display_name('Use Default Unreal Engine Type Visualizers') @description(\"Enables the built-in type views for Unreal Engine types.\")\n @default(1) use_default_ue_type_views: bool,\n\n //- rjf: theme\n @default(\"None\") @display_name('Project Theme') @description(\"The project's theme, which describes all colors used throughout the UI, and can override the user's theme.\")\n 'theme': string,\n @no_expand @display_name('Project Theme') @description(\"The project's theme, which describes all colors used throughout the UI, and can override the user's theme.\")\n 'theme_colors': query,\n\n //- rjf: exception settings\n @default(1) @display_name(\"Break On Win32 Control-C Exceptions\") @description(\"Code: 0x40010005\")\n win32_ctrl_c: bool;\n @default(1) @display_name(\"Break On Win32 Control-Break Exceptions\") @description(\"Code: 0x40010008\")\n win32_ctrl_break: bool;\n @default(0) @display_name(\"Break On Win32 WinRT Originate Error Exceptions\") @description(\"Code: 0x40080201\")\n win32_win_rt_originate_error: bool;\n @default(0) @display_name(\"Break On Win32 WinRT Transform Error Exceptions\") @description(\"Code: 0x40080202\")\n win32_win_rt_transform_error: bool;\n @default(0) @display_name(\"Break On Win32 RPC Call Cancelled Exceptions\") @description(\"Code: 0x0000071a\")\n win32_rpc_call_cancelled: bool;\n @default(0) @display_name(\"Break On Win32 Data Type Misalignment Exceptions\") @description(\"Code: 0x80000002\")\n win32_datatype_misalignment: bool;\n @default(1) @display_name(\"Break On Win32 Access Violation Exceptions\") @description(\"Code: 0xc0000005\")\n win32_access_violation: bool;\n @default(0) @display_name(\"Break On Win32 In Page Error Exceptions\") @description(\"Code: 0xc0000006\")\n win32_in_page_error: bool;\n @default(1) @display_name(\"Break On Win32 Invalid Handle Specified Exceptions\") @description(\"Code: 0xc0000008\")\n win32_invalid_handle: bool;\n @default(0) @display_name(\"Break On Win32 Not Enough Quota Exceptions\") @description(\"Code: 0xc0000017\")\n win32_not_enough_quota: bool;\n @default(0) @display_name(\"Break On Win32 Illegal Instruction Exceptions\") @description(\"Code: 0xc000001d\")\n win32_illegal_instruction: bool;\n @default(0) @display_name(\"Break On Win32 Cannot Continue From Exception Exceptions\") @description(\"Code: 0xc0000025\")\n win32_cannot_continue_exception: bool;\n @default(0) @display_name(\"Break On Win32 Invalid Exception Disposition Returned By Handler Exceptions\") @description(\"Code: 0xc0000026\")\n win32_invalid_exception_disposition: bool;\n @default(0) @display_name(\"Break On Win32 Array Bounds Exceeded Exceptions\") @description(\"Code: 0xc000008c\")\n win32_array_bounds_exceeded: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Denormal Operand Exceptions\") @description(\"Code: 0xc000008d\")\n win32_floating_point_denormal_operand: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Division By Zero Exceptions\") @description(\"Code: 0xc000008e\")\n win32_floating_point_division_by_zero: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Inexact Result Exceptions\") @description(\"Code: 0xc000008f\")\n win32_floating_point_inexact_result: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Invalid Operation Exceptions\") @description(\"Code: 0xc0000090\")\n win32_floating_point_invalid_operation: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Overflow Exceptions\") @description(\"Code: 0xc0000091\")\n win32_floating_point_overflow: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Stack Check Exceptions\") @description(\"Code: 0xc0000092\")\n win32_floating_point_stack_check: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Underflow Exceptions\") @description(\"Code: 0xc0000093\")\n win32_floating_point_underflow: bool;\n @default(0) @display_name(\"Break On Win32 Integer Division By Zero Exceptions\") @description(\"Code: 0xc0000094\")\n win32_integer_division_by_zero: bool;\n @default(0) @display_name(\"Break On Win32 Integer Overflow Exceptions\") @description(\"Code: 0xc0000095\")\n win32_integer_overflow: bool;\n @default(0) @display_name(\"Break On Win32 Privileged Instruction Exceptions\") @description(\"Code: 0xc0000096\")\n win32_privileged_instruction: bool;\n @default(0) @display_name(\"Break On Win32 Stack Overflow Exceptions\") @description(\"Code: 0xc00000fd\")\n win32_stack_overflow: bool;\n @default(0) @display_name(\"Break On Win32 Unable To Locate DLL Exceptions\") @description(\"Code: 0xc0000135\")\n win32_unable_to_locate_dll: bool;\n @default(0) @display_name(\"Break On Win32 Ordinal Not Found Exceptions\") @description(\"Code: 0xc0000138\")\n win32_ordinal_not_found: bool;\n @default(0) @display_name(\"Break On Win32 Entry Point Not Found Exceptions\") @description(\"Code: 0xc0000139\")\n win32_entry_point_not_found: bool;\n @default(0) @display_name(\"Break On Win32 DLL Initialization Failed Exceptions\") @description(\"Code: 0xc0000142\")\n win32_dll_initialization_failed: bool;\n @default(0) @display_name(\"Break On Win32 Floating Point SSE Multiple Faults Exceptions\") @description(\"Code: 0xc00002b4\")\n win32_floating_point_sse_multiple_faults: bool;\n @default(0) @display_name(\"Break On Win32 Floating Point SSE Multiple Traps Exceptions\") @description(\"Code: 0xc00002b5\")\n win32_floating_point_sse_multiple_traps: bool;\n @default(1) @display_name(\"Break On Win32 Assertion Failed Exceptions\") @description(\"Code: 0xc0000420\")\n win32_assertion_failed: bool;\n @default(0) @display_name(\"Break On Win32 Module Not Found Exceptions\") @description(\"Code: 0xc06d007e\")\n win32_module_not_found: bool;\n @default(0) @display_name(\"Break On Win32 Procedure Not Found Exceptions\") @description(\"Code: 0xc06d007f\")\n win32_procedure_not_found: bool;\n @default(1) @display_name(\"Break On Win32 Sanitizer Error Detected Exceptions\") @description(\"Code: 0xe073616e\")\n win32_sanitizer_error_detected: bool;\n @default(0) @display_name(\"Break On Win32 Sanitizer Raw Access Violation Exceptions\") @description(\"Code: 0xe0736171\")\n win32_sanitizer_raw_access_violation: bool;\n @default(1) @display_name(\"Break On Win32 DirectX Debug Layer Exceptions\") @description(\"Code: 0x0000087a\")\n win32_directx_debug_layer: bool;\n}\n")}, {str8_lit_comp("theme_color"), str8_lit_comp("@collection_commands(add_theme_color, fork_theme, save_theme, save_and_set_theme)\n@row_commands(duplicate_cfg, remove_cfg)\nx:\n{\n @display_name('Tags') tags: string,\n @display_name('Value') value: @color @hex u32,\n}\n")}, {str8_lit_comp("window"), str8_lit_comp("x:\n{\n //- rjf: text rasterization settings\n @default(1) @display_name('Smooth UI Text') @description(\"Controls whether or not UI text is fully anti-aliased, for a smoother appearance.\")\n 'smooth_ui_text': bool,\n @default(1) @display_name('Hint UI Text') @description(\"Controls whether or not UI text is hinted, for better text readability at small sizes.\")\n 'hint_ui_text': bool,\n @default(0) @display_name('Smooth Code Text') @description(\"Controls whether or not code text is fully anti-aliased, for a smoother appearance.\")\n 'smooth_code_text': bool,\n @default(1) @display_name('Hint Code Text') @description(\"Controls whether or not code text is hinted, for better text readability at small sizes.\")\n 'hint_code_text': bool,\n @default(11) @display_name('Window Font Size') @description(\"Controls the window's default font size. Does not apply to tabs with their own font size set.\")\n 'font_size': @range[6, 72] u64,\n\n //- rjf: size settings\n @default(3.f) @display_name('Window Row Height') @description(\"Controls the window's default row height, in multiples of the font size. Does not apply to tabs with their own row height set.\")\n 'row_height': @range[1.75f, 5.f] f32,\n @default(3.f) @description(\"Controls the height of tabs, in multiples of the font size.\")\n 'tab_height': @range[1.75f, 5.f] f32,\n\n //- rjf: theme settings\n @default(1) @display_name('Use Project Theme') @description(\"Prefer using the project theme for this window, if any. If off, only the user's theme settings will be used.\")\n 'use_project_theme': bool,\n}\n")}, {str8_lit_comp("tab"), str8_lit_comp("@row_commands(@file copy_tab_full_path, @file show_file_in_explorer, duplicate_tab, close_tab)\nx:\n{\n @override @display_name('Tab Font Size') @description(\"Controls the tab's font size.\") @no_callee_helper\n 'font_size': @range[6, 72] u64,\n}\n")}, {str8_lit_comp("watch"), str8_lit_comp("@inherit(tab) x:\n{\n @override @display_name('Tab Row Height') @description(\"Controls the tab's row height, in multiples of the font size.\")\n 'row_height': @range[1.75f, 5.f] f32,\n 'label': code_string,\n @description(\"The root expression which is evaluated to produce the watch window.\")\n 'expression': expr_string,\n @no_expand 'watches': query,\n}\n")}, {str8_lit_comp("text"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression to describe data which should be viewed as text or code.\")\n 'expression': expr_string,\n @description(\"The language that the text should be interpreted as being within. Used for syntax highlighting and other parsing features.\")\n 'lang': code_string,\n @default(1) @description(\"Controls whether or not line numbers are shown.\")\n 'show_line_numbers':bool,\n @no_callee_helper @default(0) @display_name('Scroll To Bottom On Change') @description(\"Scrolls to the bottom if the text is changed.\")\n 'scroll_to_bottom_on_change':bool,\n @no_callee_helper @no_revert @default(0) @display_name('Transient') @description(\"Controls whether or not this tab will be automatically replaced by the debugger when it snaps to new source code locations.\")\n 'auto': bool,\n}\n")}, {str8_lit_comp("disasm"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression to describe the base address or offset of the disassembly.\")\n 'expression': expr_string,\n 'arch': code_string,\n 'syntax': code_string,\n 'size': expr_string,\n @no_callee_helper @default(1) @description(\"Controls whether or not addresses are shown in the disassembly text.\")\n 'show_addresses': bool,\n @no_callee_helper @default(0) @description(\"Controls whether or not code bytes are shown in the disassembly text.\")\n 'show_code_bytes': bool,\n @no_callee_helper @default(1) @description(\"Controls whether or not source lines, corresponding to disassembly instruction ranges, are shown in the disassembly text.\")\n 'show_source_lines': bool,\n @no_callee_helper @default(1) @description(\"Controls whether or not disassembly text is decorated with symbol names.\")\n 'show_symbol_names': bool,\n @no_callee_helper @default(1) @description(\"Controls whether or not line numbers are shown.\")\n 'show_line_numbers': bool,\n}\n")}, -{str8_lit_comp("memory"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression which refers to the data which should be viewed as memory.\")\n 'expression': expr_string,\n @display_name(\"Address Range Size\") @description(\"The number of bytes of the viewed memory range.\")\n 'size': expr_string,\n @display_name(\"Cursor Address\") @description(\"The address of the cursor.\")\n 'cursor': expr_string,\n @display_name(\"Cursor Size\") @description(\"The size, in bytes, of the cursor.\")\n 'cursor_size': @range[1, 16] u64,\n @default(16) @description(\"The number of columns to build before building new rows.\")\n 'num_columns': @range[1, 64] u64,\n}\n")}, -{str8_lit_comp("bitmap"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression which refers to the data which should be viewed as a bitmap.\")\n 'expression': expr_string,\n @description(\"An expression describing the width of the bitmap, in pixels.\") @order(0) 'w': u64,\n @description(\"An expression describing the height of the bitmap, in pixels.\") @order(1) 'h': u64,\n @display_name(\"Bitmap Format\") @description(\"The pixel format that the bitmap data should be interpreted as being within.\")\n 'fmt': code_string,\n}\n")}, +{str8_lit_comp("memory"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression which refers to the base address of data which should be viewed as memory.\")\n 'expression': expr_string,\n @display_name(\"Address Range Size\") @description(\"The number of bytes of the viewed memory range.\")\n 'size': expr_string,\n @display_name(\"Cursor Address\") @description(\"The address of the cursor.\")\n 'cursor': expr_string,\n @display_name(\"Cursor Size\") @description(\"The size, in bytes, of the cursor.\")\n 'cursor_size': @range[1, 16] u64,\n @default(16) @description(\"The number of columns to build before building new rows.\")\n 'num_columns': @range[1, 64] u64,\n @default(1) @display_name(\"Track Mark To Cursor\") @description(\"Ensures that the mark always follows the cursor, if the cursor value is updated.\")\n 'track_mark_to_cursor': bool,\n}\n")}, +{str8_lit_comp("bitmap"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression which refers to the base address of data which should be viewed as a bitmap.\")\n 'expression': expr_string,\n @description(\"An expression describing the width of the bitmap, in pixels.\") @order(0) 'w': u64,\n @description(\"An expression describing the height of the bitmap, in pixels.\") @order(1) 'h': u64,\n @display_name(\"Bitmap Format\") @description(\"The pixel format that the bitmap data should be interpreted as being within.\")\n 'fmt': code_string,\n}\n")}, {str8_lit_comp("color"), str8_lit_comp("@inherit(tab) x:\n{\n @display_name(\"Value\") @description(\"An expression to describe the value or location of the color.\")\n 'expression': expr_string,\n}\n")}, {str8_lit_comp("geo3d"), str8_lit_comp("@inherit(tab) x:\n{\n @display_name(\"Expression\") @description(\"An expression to describe the base address of the index buffer.\")\n 'expression': expr_string,\n 'count': expr_string,\n 'vtx': expr_string,\n 'vtx_size': expr_string,\n 'yaw': @range[0, 1] f32,\n 'pitch': @range[-0.5, 0] f32,\n 'zoom': @range[0, 100] f32,\n}\n")}, {str8_lit_comp("getting_started"), str8_lit_comp("@inherit(tab) x:\n{\n}\n")}, @@ -435,7 +437,7 @@ RD_NameSchemaInfo rd_name_schema_info_table[24] = {str8_lit_comp("thread"), str8_lit_comp("x:{'label':code_string, 'id':u64, @no_expand 'active':bool, 'call_stack':query}")}, }; -Rng1U64 rd_reg_slot_range_table[44] = +Rng1U64 rd_reg_slot_range_table[48] = { {0}, {OffsetOf(RD_Regs, machine), OffsetOf(RD_Regs, machine) + sizeof(CTRL_Handle)}, @@ -451,6 +453,7 @@ Rng1U64 rd_reg_slot_range_table[44] = {OffsetOf(RD_Regs, dst_panel), OffsetOf(RD_Regs, dst_panel) + sizeof(RD_CfgID)}, {OffsetOf(RD_Regs, cfg), OffsetOf(RD_Regs, cfg) + sizeof(RD_CfgID)}, {OffsetOf(RD_Regs, cfg_list), OffsetOf(RD_Regs, cfg_list) + sizeof(RD_CfgIDList)}, +{OffsetOf(RD_Regs, eval_space), OffsetOf(RD_Regs, eval_space) + sizeof(E_Space)}, {OffsetOf(RD_Regs, unwind_count), OffsetOf(RD_Regs, unwind_count) + sizeof(U64)}, {OffsetOf(RD_Regs, inline_depth), OffsetOf(RD_Regs, inline_depth) + sizeof(U64)}, {OffsetOf(RD_Regs, file_path), OffsetOf(RD_Regs, file_path) + sizeof(String8)}, @@ -466,6 +469,7 @@ Rng1U64 rd_reg_slot_range_table[44] = {OffsetOf(RD_Regs, voff_range), OffsetOf(RD_Regs, voff_range) + sizeof(Rng1U64)}, {OffsetOf(RD_Regs, expr), OffsetOf(RD_Regs, expr) + sizeof(String8)}, {OffsetOf(RD_Regs, ui_key), OffsetOf(RD_Regs, ui_key) + sizeof(UI_Key)}, +{OffsetOf(RD_Regs, src_ui_key), OffsetOf(RD_Regs, src_ui_key) + sizeof(UI_Key)}, {OffsetOf(RD_Regs, off_px), OffsetOf(RD_Regs, off_px) + sizeof(Vec2F32)}, {OffsetOf(RD_Regs, reg_slot), OffsetOf(RD_Regs, reg_slot) + sizeof(RD_RegSlot)}, {OffsetOf(RD_Regs, pid), OffsetOf(RD_Regs, pid) + sizeof(U32)}, @@ -476,6 +480,8 @@ Rng1U64 rd_reg_slot_range_table[44] = {OffsetOf(RD_Regs, do_implicit_root), OffsetOf(RD_Regs, do_implicit_root) + sizeof(B32)}, {OffsetOf(RD_Regs, do_lister), OffsetOf(RD_Regs, do_lister) + sizeof(B32)}, {OffsetOf(RD_Regs, do_big_rows), OffsetOf(RD_Regs, do_big_rows) + sizeof(B32)}, +{OffsetOf(RD_Regs, all_windows), OffsetOf(RD_Regs, all_windows) + sizeof(B32)}, +{OffsetOf(RD_Regs, non_graphical), OffsetOf(RD_Regs, non_graphical) + sizeof(B32)}, {OffsetOf(RD_Regs, dir2), OffsetOf(RD_Regs, dir2) + sizeof(Dir2)}, {OffsetOf(RD_Regs, string), OffsetOf(RD_Regs, string) + sizeof(String8)}, {OffsetOf(RD_Regs, cmd_name), OffsetOf(RD_Regs, cmd_name) + sizeof(String8)}, @@ -483,7 +489,7 @@ Rng1U64 rd_reg_slot_range_table[44] = {OffsetOf(RD_Regs, os_event), OffsetOf(RD_Regs, os_event) + sizeof(OS_Event *)}, }; -RD_CmdKindInfo rd_cmd_kind_info_table[236] = +RD_CmdKindInfo rd_cmd_kind_info_table[238] = { {0}, { str8_lit_comp("launch_and_run"), str8_lit_comp("Starts debugging a new instance of a target, then runs."), str8_lit_comp("launch,start,run,target"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:targets"), str8_lit_comp(""), CTRL_EntityKind_Null}}, @@ -591,6 +597,8 @@ RD_CmdKindInfo rd_cmd_kind_info_table[236] = { str8_lit_comp("open_recent_project"), str8_lit_comp("Opens a recently used project file."), str8_lit_comp("project,project,session"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_Cfg, str8_lit_comp("query:recent_projects"), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("save_user"), str8_lit_comp("Saves user data to a file, and sets the current user path as that path."), str8_lit_comp("load,user,project,layout"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*1)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("save_project"), str8_lit_comp("Saves project data to a file, and sets the current project path as that path."), str8_lit_comp("project,project,session"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*1)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), CTRL_EntityKind_Null}}, +{ str8_lit_comp("record_user_as_last_opened"), str8_lit_comp("Records a file path as the last opened user."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, +{ str8_lit_comp("record_project_in_user"), str8_lit_comp("Records a file path as a recent project in user data."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("write_user_data"), str8_lit_comp("Writes user data to the active user file."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("write_project_data"), str8_lit_comp("Writes project data to the active project file."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, { str8_lit_comp("user_settings"), str8_lit_comp("Opens user settings."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), CTRL_EntityKind_Null}}, diff --git a/src/raddbg/generated/raddbg.meta.h b/src/raddbg/generated/raddbg.meta.h index 8d48807c..837729b0 100644 --- a/src/raddbg/generated/raddbg.meta.h +++ b/src/raddbg/generated/raddbg.meta.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE @@ -22,6 +22,7 @@ RD_RegSlot_PrevTab, RD_RegSlot_DstPanel, RD_RegSlot_Cfg, RD_RegSlot_CfgList, +RD_RegSlot_EvalSpace, RD_RegSlot_UnwindCount, RD_RegSlot_InlineDepth, RD_RegSlot_FilePath, @@ -37,6 +38,7 @@ RD_RegSlot_VaddrRange, RD_RegSlot_VoffRange, RD_RegSlot_Expr, RD_RegSlot_UIKey, +RD_RegSlot_SrcUIKey, RD_RegSlot_OffPx, RD_RegSlot_RegSlot, RD_RegSlot_PID, @@ -47,6 +49,8 @@ RD_RegSlot_NoRichTooltip, RD_RegSlot_DoImplicitRoot, RD_RegSlot_DoLister, RD_RegSlot_DoBigRows, +RD_RegSlot_AllWindows, +RD_RegSlot_NonGraphical, RD_RegSlot_Dir2, RD_RegSlot_String, RD_RegSlot_CmdName, @@ -163,6 +167,8 @@ RD_CmdKind_OpenProject, RD_CmdKind_OpenRecentProject, RD_CmdKind_SaveUser, RD_CmdKind_SaveProject, +RD_CmdKind_RecordUserAsLastOpened, +RD_CmdKind_RecordProjectInUser, RD_CmdKind_WriteUserData, RD_CmdKind_WriteProjectData, RD_CmdKind_UserSettings, @@ -445,6 +451,7 @@ RD_CfgID prev_tab; RD_CfgID dst_panel; RD_CfgID cfg; RD_CfgIDList cfg_list; +E_Space eval_space; U64 unwind_count; U64 inline_depth; String8 file_path; @@ -460,6 +467,7 @@ Rng1U64 vaddr_range; Rng1U64 voff_range; String8 expr; UI_Key ui_key; +UI_Key src_ui_key; Vec2F32 off_px; RD_RegSlot reg_slot; U32 pid; @@ -470,6 +478,8 @@ B32 no_rich_tooltip; B32 do_implicit_root; B32 do_lister; B32 do_big_rows; +B32 all_windows; +B32 non_graphical; Dir2 dir2; String8 string; String8 cmd_name; @@ -539,6 +549,7 @@ Z(getting_started)\ .dst_panel = rd_regs()->dst_panel,\ .cfg = rd_regs()->cfg,\ .cfg_list = rd_regs()->cfg_list,\ +.eval_space = rd_regs()->eval_space,\ .unwind_count = rd_regs()->unwind_count,\ .inline_depth = rd_regs()->inline_depth,\ .file_path = rd_regs()->file_path,\ @@ -554,6 +565,7 @@ Z(getting_started)\ .voff_range = rd_regs()->voff_range,\ .expr = rd_regs()->expr,\ .ui_key = rd_regs()->ui_key,\ +.src_ui_key = rd_regs()->src_ui_key,\ .off_px = rd_regs()->off_px,\ .reg_slot = rd_regs()->reg_slot,\ .pid = rd_regs()->pid,\ @@ -564,6 +576,8 @@ Z(getting_started)\ .do_implicit_root = rd_regs()->do_implicit_root,\ .do_lister = rd_regs()->do_lister,\ .do_big_rows = rd_regs()->do_big_rows,\ +.all_windows = rd_regs()->all_windows,\ +.non_graphical = rd_regs()->non_graphical,\ .dir2 = rd_regs()->dir2,\ .string = rd_regs()->string,\ .cmd_name = rd_regs()->cmd_name,\ @@ -573,9 +587,9 @@ Z(getting_started)\ C_LINKAGE_BEGIN extern String8 rd_tab_fast_path_view_name_table[24]; extern String8 rd_tab_fast_path_query_name_table[24]; -extern RD_VocabInfo rd_vocab_info_table[343]; +extern RD_VocabInfo rd_vocab_info_table[345]; extern RD_NameSchemaInfo rd_name_schema_info_table[24]; -extern Rng1U64 rd_reg_slot_range_table[44]; +extern Rng1U64 rd_reg_slot_range_table[48]; extern String8 rd_binding_version_remap_old_name_table[8]; extern String8 rd_binding_version_remap_new_name_table[8]; extern String8 rd_icon_kind_text_table[75]; diff --git a/src/raddbg/raddbg.mdesk b/src/raddbg/raddbg.mdesk index 0f70fa7b..d5fd675e 100644 --- a/src/raddbg/raddbg.mdesk +++ b/src/raddbg/raddbg.mdesk @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -300,8 +300,8 @@ RD_VocabTable: //- rjf: visualizers @display_name('Use Default C++ STL Type Visualizers') @description("Enables the built-in type views for C++ STL types.") @default(1) use_default_stl_type_views: bool, - // @display_name('Use Default Unreal Engine Type Visualizers') @description("Enables the built-in type views for Unreal Engine types.") - // @default(1) use_default_ue_type_views: bool, + @display_name('Use Default Unreal Engine Type Visualizers') @description("Enables the built-in type views for Unreal Engine types.") + @default(1) use_default_ue_type_views: bool, //- rjf: theme @default("None") @display_name('Project Theme') @description("The project's theme, which describes all colors used throughout the UI, and can override the user's theme.") @@ -507,7 +507,7 @@ RD_VocabTable: ``` @inherit(tab) x: { - @description("An expression which refers to the data which should be viewed as memory.") + @description("An expression which refers to the base address of data which should be viewed as memory.") 'expression': expr_string, @display_name("Address Range Size") @description("The number of bytes of the viewed memory range.") 'size': expr_string, @@ -517,6 +517,8 @@ RD_VocabTable: 'cursor_size': @range[1, 16] u64, @default(16) @description("The number of columns to build before building new rows.") 'num_columns': @range[1, 64] u64, + @default(1) @display_name("Track Mark To Cursor") @description("Ensures that the mark always follows the cursor, if the cursor value is updated.") + 'track_mark_to_cursor': bool, } ``` } @@ -525,7 +527,7 @@ RD_VocabTable: ``` @inherit(tab) x: { - @description("An expression which refers to the data which should be viewed as a bitmap.") + @description("An expression which refers to the base address of data which should be viewed as a bitmap.") 'expression': expr_string, @description("An expression describing the width of the bitmap, in pixels.") @order(0) 'w': u64, @description("An expression describing the height of the bitmap, in pixels.") @order(1) 'h': u64, @@ -708,6 +710,9 @@ RD_RegTable: {RD_CfgID cfg Cfg } {RD_CfgIDList cfg_list CfgList } + // rjf: evaluation space + {E_Space eval_space EvalSpace } + // rjf: frame selection {U64 unwind_count UnwindCount } {U64 inline_depth InlineDepth } @@ -730,6 +735,7 @@ RD_RegTable: // rjf: ui context {UI_Key ui_key UIKey } + {UI_Key src_ui_key SrcUIKey } {Vec2F32 off_px OffPx } {RD_RegSlot reg_slot RegSlot } @@ -742,6 +748,8 @@ RD_RegTable: {B32 do_implicit_root DoImplicitRoot} {B32 do_lister DoLister } {B32 do_big_rows DoBigRows } + {B32 all_windows AllWindows } + {B32 non_graphical NonGraphical } {Dir2 dir2 Dir2 } {String8 string String } {String8 cmd_name CmdName } @@ -894,6 +902,8 @@ RD_CmdTable: // | | | | {OpenRecentProject 1 1 0 0 "query:recent_projects" Cfg null RecentProject Null 0 0 0 0 0 1 1 Briefcase "open_recent_project" "Open Recent Project" "Opens a recently used project file." "project,project,session" "" } {SaveUser 1 1 0 0 `folder:\\"$input\\"` FilePath null Nil Null 1 0 0 0 0 1 1 Save "save_user" "Save User" "Saves user data to a file, and sets the current user path as that path." "load,user,project,layout" "" } {SaveProject 1 1 0 0 `folder:\\"$input\\"` FilePath null Nil Null 1 0 0 0 0 1 1 Save "save_project" "Save Project" "Saves project data to a file, and sets the current project path as that path." "project,project,session" "" } + {RecordUserAsLastOpened 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "record_user_as_last_opened" "Record User As Last Opened" "Records a file path as the last opened user." "" "" } + {RecordProjectInUser 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "record_project_in_user" "Records Project In User" "Records a file path as a recent project in user data." "" "" } //- rjf: writing config changes {WriteUserData 0 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "write_user_data" "Write User Data" "Writes user data to the active user file." "" "" } diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 0c639e56..b0f64205 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR @@ -4439,6 +4439,7 @@ rd_view_ui(Rng2F32 rect) // ProfScope("build table") { + UI_Key watch_rich_hover_key = ui_key_from_string(ui_active_seed_key(), str8_lit("###rich_hover")); F32 row_y_px = rect.y0; U64 local_row_idx = 0; U64 global_row_idx = rows.count_before_semantic; @@ -4619,8 +4620,12 @@ rd_view_ui(Rng2F32 rect) //- rjf: determine if cell evaluation's data is fresh and/or bad // ProfBegin("determine if cell evaluation's data is fresh and/or bad"); + B32 cell_is_rich_hovered = 0; B32 cell_is_fresh = 0; B32 cell_is_bad = 0; + U64 cell_vaddr_rng_size = e_type_byte_size_from_key(cell->eval.irtree.type_key); + cell_vaddr_rng_size = Min(cell_vaddr_rng_size, 64); + Rng1U64 cell_vaddr_rng = r1u64(cell->eval.value.u64, cell->eval.value.u64+cell_vaddr_rng_size); if(!(cell_info.flags & RD_WatchCellFlag_NoEval)) { switch(cell->eval.irtree.mode) @@ -4628,13 +4633,17 @@ rd_view_ui(Rng2F32 rect) default:{}break; case E_Mode_Offset: { + if(rd_state->hover_regs_slot == RD_RegSlot_VaddrRange && + e_space_match(cell->eval.space, rd_get_hover_regs()->eval_space) && + !ui_key_match(rd_get_hover_regs()->src_ui_key, watch_rich_hover_key)) + { + Rng1U64 intersection = intersect_1u64(cell_vaddr_rng, rd_get_hover_regs()->vaddr_range); + cell_is_rich_hovered = (intersection.max > intersection.min); + } CTRL_Entity *space_entity = rd_ctrl_entity_from_eval_space(cell->eval.space); if(cell->eval.space.kind == RD_EvalSpaceKind_CtrlEntity && space_entity->kind == CTRL_EntityKind_Process) { - U64 size = e_type_byte_size_from_key(cell->eval.irtree.type_key); - size = Min(size, 64); - Rng1U64 vaddr_rng = r1u64(cell->eval.value.u64, cell->eval.value.u64+size); - CTRL_ProcessMemorySlice slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, space_entity->handle, vaddr_rng, rd_state->frame_eval_memread_endt_us); + CTRL_ProcessMemorySlice slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, space_entity->handle, cell_vaddr_rng, rd_state->frame_eval_memread_endt_us); for(U64 idx = 0; idx < (slice.data.size+63)/64; idx += 1) { if(slice.byte_changed_flags[idx] != 0) @@ -4723,6 +4732,13 @@ rd_view_ui(Rng2F32 rect) rgba.w *= ui_anim(ui_key_from_stringf(ui_key_zero(), "###entity_hover_t_%p", entity), 1.f, .rate = entity_hover_t_rate); cell_background_color_override = rgba; } + else if(cell_is_rich_hovered) + { + UI_TagF(".") UI_TagF("pop") + { + cell_background_color_override = ui_color_from_name(str8_lit("background")); + } + } else if(cell_is_fresh) { UI_TagF(".") UI_TagF("fresh") @@ -5064,17 +5080,23 @@ rd_view_ui(Rng2F32 rect) } // rjf: hover -> rich hover entities - if(ui_hovering(sig) && cell_info.entity != &ctrl_entity_nil) + else if(ui_hovering(sig) && cell_info.entity != &ctrl_entity_nil) { RD_RegsScope(.ctrl_entity = cell_info.entity->handle, .no_rich_tooltip = 1) rd_set_hover_regs(RD_RegSlot_CtrlEntity); } // rjf: hover -> rich hover commands (mini only) - if(ui_hovering(sig) && cell_info.cmd_name.size != 0 && cell->px != 0) + else if(ui_hovering(sig) && cell_info.cmd_name.size != 0 && cell->px != 0) { RD_RegsScope(.cmd_name = cell_info.cmd_name, .ui_key = sig.box->key) rd_set_hover_regs(RD_RegSlot_CmdName); } + // rjf: hover -> rich hover address ranges + else if(ui_hovering(sig) && !(cell_info.flags & RD_WatchCellFlag_Expr)) + { + RD_RegsScope(.eval_space = cell->eval.space, .vaddr_range = cell_vaddr_rng, .src_ui_key = watch_rich_hover_key) rd_set_hover_regs(RD_RegSlot_VaddrRange); + } + // rjf: dragging -> drag/drop if(ui_dragging(sig) && !contains_2f32(sig.box->rect, ui_mouse()) && (!cell_selected || !ewv->text_editing)) @@ -8539,6 +8561,7 @@ rd_window_frame(void) panel_rect_pct.x1*content_rect_dim.x, panel_rect_pct.y1*content_rect_dim.y); panel_rect = pad_2f32(panel_rect, floor_f32(-ui_top_font_size()*0.15f)); + panel_rect = r2f32p(round_f32(panel_rect.x0), round_f32(panel_rect.y0), round_f32(panel_rect.x1), round_f32(panel_rect.y1)); F32 tab_bar_rheight = floor_f32(ui_top_font_size()*3.5f); F32 tab_bar_vheight = floor_f32(ui_top_font_size()*rd_setting_f32_from_name(str8_lit("tab_height"))); F32 tab_bar_rv_diff = tab_bar_rheight - tab_bar_vheight; @@ -9706,7 +9729,7 @@ rd_window_frame(void) // rjf: draw border if(b->flags & UI_BoxFlag_DrawBorder) { - Vec4F32 border_color = ui_color_from_tags_key_name(box->tags_key, str8_lit("border")); + Vec4F32 border_color = b->border_color; Rng2F32 b_border_rect = pad_2f32(b->rect, 1.f); R_Rect2DInst *inst = dr_rect(b_border_rect, border_color, 0, 1.f, border_softness*1.f); MemoryCopyArray(inst->corner_radii, b_corner_radii); @@ -9736,7 +9759,7 @@ rd_window_frame(void) // rjf: draw sides if(b->flags & (UI_BoxFlag_DrawSideTop|UI_BoxFlag_DrawSideBottom|UI_BoxFlag_DrawSideLeft|UI_BoxFlag_DrawSideRight)) { - Vec4F32 border_color = ui_color_from_tags_key_name(box->tags_key, str8_lit("border")); + Vec4F32 border_color = b->border_color; Rng2F32 r = b->rect; F32 half_thickness = 1.f; F32 softness = 0.f; @@ -9960,7 +9983,7 @@ rd_set_autocomp_regs_(E_Eval dst_eval, RD_Regs *regs) // rjf: calculate most general list expression, given the dst_eval space B32 force_allow = 0; B32 expr_based_replace = 1; - String8 list_expr = str8_lit("query:locals, query:globals, query:thread_locals, query:procedures, query:types"); + String8 list_expr = str8_lit("query:locals, query:globals, query:thread_locals, query:procedures, query:types, query:constants"); { E_TypeKey maybe_enum_type = e_type_key_unwrap(dst_eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative & ~E_TypeUnwrapFlag_Enums); if(dst_eval.space.kind == RD_EvalSpaceKind_MetaCfg) @@ -10588,6 +10611,13 @@ rd_regs_fill_slot_from_string(RD_RegSlot slot, String8 string) rd_regs()->cursor = pair.pt; } }break; + case RD_RegSlot_Cfg: + if(str8_match(str8_prefix(string, 1), str8_lit("$"), 0)) + { + String8 numeric_part = str8_skip(string, 1); + RD_CfgID id = u64_from_str8(numeric_part, 16); + rd_regs()->cfg = id; + }break; case RD_RegSlot_Expr: { rd_regs()->expr = push_str8_copy(rd_frame_arena(), string); @@ -10782,6 +10812,7 @@ rd_init(CmdLine *cmdln) { rd_state->cmds_arenas[idx] = arena_alloc(); } + rd_state->cmd_output_arena = arena_alloc(); rd_state->popup_arena = arena_alloc(); rd_state->ctx_menu_key = ui_key_from_string(ui_key_zero(), str8_lit("top_level_ctx_menu")); rd_state->drop_completion_key = ui_key_from_string(ui_key_zero(), str8_lit("drop_completion_ctx_menu")); @@ -11086,6 +11117,11 @@ rd_frame(void) } B32 allow_text_hotkeys = !rd_state->text_edit_mode; rd_state->text_edit_mode = 0; + if(rd_state->frame_depth == 1) + { + arena_clear(rd_state->cmd_output_arena); + MemoryZeroStruct(&rd_state->cmd_outputs); + } ////////////////////////////// //- rjf: iterate all tabs, touch their view-states @@ -11262,15 +11298,12 @@ rd_frame(void) } ////////////////////////////// - //- rjf: open frame scopes + //- rjf: push frame scopes // - if(rd_state->frame_depth == 1) - { - if(rd_state->frame_di_scope) { di_scope_close(rd_state->frame_di_scope); } - if(rd_state->frame_ctrl_scope) { ctrl_scope_close(rd_state->frame_ctrl_scope); } - rd_state->frame_di_scope = di_scope_open(); - rd_state->frame_ctrl_scope = ctrl_scope_open(); - } + DI_Scope *frame_di_scope_restore = rd_state->frame_di_scope; + CTRL_Scope *frame_ctrl_scope_restore = rd_state->frame_ctrl_scope; + rd_state->frame_di_scope = di_scope_open(); + rd_state->frame_ctrl_scope = ctrl_scope_open(); ////////////////////////////// //- rjf: calculate avg length in us of last many frames @@ -12172,6 +12205,7 @@ rd_frame(void) { str8_lit_comp("procedures"), str8_lit_comp("thread_locals"), + str8_lit_comp("constants"), str8_lit_comp("globals"), str8_lit_comp("types"), }; @@ -12367,10 +12401,21 @@ rd_frame(void) } type_views[] = { - { 1, 0, str8_lit_comp("std::vector"), str8_lit_comp("slice(_Mypair._Myval2)") }, - { 1, 0, str8_lit_comp("std::unique_ptr"), str8_lit_comp("_Mypair._Myval2") }, - { 1, 0, str8_lit_comp("std::basic_string"), str8_lit_comp("_Mypair._Myval2._Myres <= 15 ? _Mypair._Myval2._Bx._Buf : array(_Mypair._Myval2._Bx._Ptr, _Mypair._Myval2._Mysize)") }, - { 1, 0, str8_lit_comp("std::basic_string_view"), str8_lit_comp("array(_Mydata, _Mysize)") }, + { 1, 0, str8_lit_comp("std::vector"), str8_lit_comp("slice(_Mypair._Myval2)") }, + { 1, 0, str8_lit_comp("std::unique_ptr"), str8_lit_comp("_Mypair._Myval2") }, + { 1, 0, str8_lit_comp("std::basic_string"), str8_lit_comp("_Mypair._Myval2._Myres <= 15 ? _Mypair._Myval2._Bx._Buf : array(_Mypair._Myval2._Bx._Ptr, _Mypair._Myval2._Mysize)") }, + { 1, 0, str8_lit_comp("std::basic_string_view"), str8_lit_comp("array(_Mydata, _Mysize)") }, + { 0, 1, str8_lit_comp("FString"), str8_lit_comp("(TCHAR *)Data.AllocatorInstance.Data, Data.ArrayNum") }, + { 0, 1, str8_lit_comp("FAnsiString"), str8_lit_comp("(ANSICHAR *)Data.AllocatorInstance.Data, Data.ArrayNum") }, + { 0, 1, str8_lit_comp("FUtf8String"), str8_lit_comp("(UTF8CHAR *)Data.AllocatorInstance.Data, Data.ArrayNum") }, + { 0, 1, str8_lit_comp("TStringView"), str8_lit_comp("DataPtr, Size") }, + { 0, 1, str8_lit_comp("TArray"), str8_lit_comp("array(cast(element_type *)AllocatorInstance.Data, ArrayNum)") }, + { 0, 1, str8_lit_comp("TSharedRef"), str8_lit_comp("Object") }, + { 0, 1, str8_lit_comp("TRefCountPtr"), str8_lit_comp("Reference") }, + { 0, 1, str8_lit_comp("FNameEntry"), str8_lit_comp("AnsiName, Header.Len") }, + { 0, 1, str8_lit_comp("FNameEntryId"), str8_lit_comp("*(cast(FNameEntry *)(&GNameBlocksDebug[Value >> FNameDebugVisualizer::OffsetBits][FNameDebugVisualizer::EntryStride * (Value & FNameDebugVisualizer::OffsetMask)]))") }, + { 0, 1, str8_lit_comp("TObjectPtr"), str8_lit_comp("DebugPtr") }, + { 0, 1, str8_lit_comp("FColor"), str8_lit_comp("hex(color(Bits))") }, }; if(rd_state->use_default_stl_type_views) { @@ -12379,7 +12424,7 @@ rd_frame(void) if((type_views[idx].stl && rd_state->use_default_stl_type_views) || (type_views[idx].ue && rd_state->use_default_ue_type_views)) { - RD_Cfg *immediate_root = rd_immediate_cfg_from_keyf("default_stl_type_vis_%I64x", idx); + RD_Cfg *immediate_root = rd_immediate_cfg_from_keyf("default_type_vis_%I64x", idx); RD_Cfg *type_view = rd_cfg_child_from_string_or_alloc(immediate_root, str8_lit("type_view")); RD_Cfg *type = rd_cfg_child_from_string_or_alloc(type_view, str8_lit("type")); RD_Cfg *expr = rd_cfg_child_from_string_or_alloc(type_view, str8_lit("expr")); @@ -12958,37 +13003,13 @@ rd_frame(void) //- rjf: record last-opened user in config directory if(file_is_okay && kind == RD_CmdKind_OpenUser) { - String8 last_user_path = push_str8f(scratch.arena, "%S/raddbg/last_user", os_get_process_info()->user_program_data_path); - os_write_data_to_file_path(last_user_path, file_path); + rd_cmd(RD_CmdKind_RecordUserAsLastOpened); } //- rjf: record recently-opened projects in the user if(file_is_okay && kind == RD_CmdKind_OpenProject) { - RD_Cfg *user = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("user")); - RD_CfgList recent_projects = rd_cfg_child_list_from_string(scratch.arena, user, str8_lit("recent_project")); - RD_Cfg *recent_project = &rd_nil_cfg; - for(RD_CfgNode *n = recent_projects.first; n != 0; n = n->next) - { - if(path_match_normalized(rd_path_from_cfg(n->v), file_path)) - { - recent_project = n->v; - break; - } - } - if(recent_project == &rd_nil_cfg) - { - recent_project = rd_cfg_new(user, str8_lit("recent_project")); - RD_Cfg *path_root = rd_cfg_new(recent_project, str8_lit("path")); - rd_cfg_new(path_root, path_absolute_dst_from_relative_dst_src(scratch.arena, file_path, str8_chop_last_slash(rd_state->user_path))); - } - rd_cfg_unhook(user, recent_project); - rd_cfg_insert_child(user, &rd_nil_cfg, recent_project); - recent_projects = rd_cfg_child_list_from_string(scratch.arena, user, str8_lit("recent_project")); - if(recent_projects.count > 32) - { - rd_cfg_release(recent_projects.last->v); - } + rd_cmd(RD_CmdKind_RecordProjectInUser); } //- rjf: eliminate all project-filtered tab focuses @@ -13103,15 +13124,51 @@ rd_frame(void) arena_clear(rd_state->user_path_arena); rd_state->user_path = push_str8_copy(rd_state->user_path_arena, new_path); rd_cmd(RD_CmdKind_WriteUserData); + rd_cmd(RD_CmdKind_RecordUserAsLastOpened); }break; case RD_CmdKind_SaveProject: { arena_clear(rd_state->project_path_arena); rd_state->project_path = push_str8_copy(rd_state->project_path_arena, new_path); rd_cmd(RD_CmdKind_WriteProjectData); + rd_cmd(RD_CmdKind_RecordProjectInUser); }break; } }break; + case RD_CmdKind_RecordProjectInUser: + { + String8 file_path = rd_regs()->file_path; + RD_Cfg *user = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("user")); + RD_CfgList recent_projects = rd_cfg_child_list_from_string(scratch.arena, user, str8_lit("recent_project")); + RD_Cfg *recent_project = &rd_nil_cfg; + for(RD_CfgNode *n = recent_projects.first; n != 0; n = n->next) + { + if(path_match_normalized(rd_path_from_cfg(n->v), file_path)) + { + recent_project = n->v; + break; + } + } + if(recent_project == &rd_nil_cfg) + { + recent_project = rd_cfg_new(user, str8_lit("recent_project")); + RD_Cfg *path_root = rd_cfg_new(recent_project, str8_lit("path")); + rd_cfg_new(path_root, file_path); + } + rd_cfg_unhook(user, recent_project); + rd_cfg_insert_child(user, &rd_nil_cfg, recent_project); + recent_projects = rd_cfg_child_list_from_string(scratch.arena, user, str8_lit("recent_project")); + if(recent_projects.count > 32) + { + rd_cfg_release(recent_projects.last->v); + } + }break; + case RD_CmdKind_RecordUserAsLastOpened: + { + String8 file_path = rd_regs()->file_path; + String8 last_user_path = push_str8f(scratch.arena, "%S/raddbg/last_user", os_get_process_info()->user_program_data_path); + os_write_data_to_file_path(last_user_path, file_path); + }break; //- rjf: writing config changes case RD_CmdKind_WriteUserData: dst_path = rd_state->user_path; bucket_name = str8_lit("user"); goto write; @@ -14335,81 +14392,73 @@ rd_frame(void) //- rjf: thread finding case RD_CmdKind_FindThread: - for(RD_WindowState *ws = rd_state->first_window_state; ws != &rd_nil_window_state; ws = ws->order_next) - RD_RegsScope(.window = ws->cfg_id) { DI_Scope *scope = di_scope_open(); + + //- rjf: unpack thread info CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread); U64 unwind_index = rd_regs()->unwind_count; U64 inline_depth = rd_regs()->inline_depth; - if(thread->kind == CTRL_EntityKind_Thread) + U64 rip_vaddr = d_query_cached_rip_from_thread_unwind(thread, unwind_index); + CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process); + CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr); + DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); + RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); + U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr); + D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, rip_voff); + D_Line line = {0}; { - // rjf: grab rip - U64 rip_vaddr = d_query_cached_rip_from_thread_unwind(thread, unwind_index); - - // rjf: extract thread/rip info - CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process); - CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr); - DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); - RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); - U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr); - D_LineList lines = d_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, rip_voff); - D_Line line = {0}; + U64 idx = 0; + for(D_LineNode *n = lines.first; n != 0; n = n->next, idx += 1) { - U64 idx = 0; - for(D_LineNode *n = lines.first; n != 0; n = n->next, idx += 1) + line = n->v; + if(idx == inline_depth) { - line = n->v; - if(idx == inline_depth) - { - break; - } + break; } } - - // rjf: snap to resolved line - B32 missing_rip = (rip_vaddr == 0); - B32 dbgi_missing = (dbgi_key.min_timestamp == 0 || dbgi_key.path.size == 0); - B32 dbgi_pending = !dbgi_missing && rdi == &rdi_parsed_nil; - B32 has_line_info = (line.voff_range.max != 0); - B32 has_module = (module != &ctrl_entity_nil); - B32 has_dbg_info = has_module && !dbgi_missing; - if(!dbgi_pending && (has_line_info || has_module)) - { - rd_cmd(RD_CmdKind_FindCodeLocation, - .file_path = line.file_path, - .cursor = line.pt, - .process = process->handle, - .voff = rip_voff, - .vaddr = rip_vaddr, - .unwind_count = unwind_index, - .inline_depth = inline_depth); - } - - // rjf: snap to resolved address w/o line info - if(!missing_rip && !dbgi_pending && !has_line_info && !has_module) - { - rd_cmd(RD_CmdKind_FindCodeLocation, - .file_path = str8_zero(), - .process = process->handle, - .module = module->handle, - .voff = rip_voff, - .vaddr = rip_vaddr, - .unwind_count = unwind_index, - .inline_depth = inline_depth); - } - - // rjf: retry on stopped, pending debug info - if(!d_ctrl_targets_running() && (dbgi_pending || missing_rip)) - { - find_thread_retry = thread->handle; - } + } + B32 missing_rip = (rip_vaddr == 0); + B32 dbgi_missing = (dbgi_key.min_timestamp == 0 || dbgi_key.path.size == 0); + B32 dbgi_pending = !dbgi_missing && rdi == &rdi_parsed_nil; + B32 has_line_info = (line.voff_range.max != 0); + B32 has_module = (module != &ctrl_entity_nil); + B32 has_dbg_info = has_module && !dbgi_missing; + + //- rjf: find-code-location on each affected window + if(!dbgi_pending && (has_line_info || has_module)) + { + rd_cmd(RD_CmdKind_FindCodeLocation, + .file_path = line.file_path, + .cursor = line.pt, + .process = process->handle, + .voff = rip_voff, + .vaddr = rip_vaddr, + .unwind_count = unwind_index, + .inline_depth = inline_depth, + .all_windows = 1); + } + if(!missing_rip && !dbgi_pending && !has_line_info && !has_module) + { + rd_cmd(RD_CmdKind_FindCodeLocation, + .file_path = str8_zero(), + .process = process->handle, + .module = module->handle, + .voff = rip_voff, + .vaddr = rip_vaddr, + .unwind_count = unwind_index, + .inline_depth = inline_depth, + .all_windows = 1); + } + + // rjf: retry on stopped, pending debug info + if(!d_ctrl_targets_running() && (dbgi_pending || missing_rip)) + { + find_thread_retry = thread->handle; } di_scope_close(scope); }break; case RD_CmdKind_FindSelectedThread: - for(RD_WindowState *ws = rd_state->first_window_state; ws != &rd_nil_window_state; ws = ws->order_next) - RD_RegsScope(.window = ws->cfg_id) { CTRL_Entity *selected_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_base_regs()->thread); rd_cmd(RD_CmdKind_FindThread, @@ -14582,10 +14631,8 @@ rd_frame(void) // the biggest empty panel. // 4. If there is no empty panel, then we will pick the biggest // panel. - RD_Cfg *window = rd_cfg_from_id(rd_regs()->window); - RD_PanelTree panel_tree = rd_panel_tree_from_cfg(scratch.arena, window); - // rjf: grab things to find. path * point, process * address, etc. + //- rjf: grab things to find. path * point, process * address, etc. String8 file_path = {0}; TxtPt point = {0}; CTRL_Entity *thread = &ctrl_entity_nil; @@ -14604,7 +14651,7 @@ rd_frame(void) } } - // rjf: given a src code location, if no vaddr is specified, + //- rjf: given a src code location, if no vaddr is specified, // try to map the src coordinates to a vaddr via line info if(vaddr == 0 && file_path.size != 0) { @@ -14618,68 +14665,62 @@ rd_frame(void) } } - // rjf: first, try to find panel/view pair that already has the src file open - RD_PanelNode *panel_w_this_src_code = &rd_nil_panel_node; - RD_Cfg *view_w_this_src_code = &rd_nil_cfg; - for(RD_PanelNode *panel = panel_tree.root; - panel != &rd_nil_panel_node; - panel = rd_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) + //- rjf: build task list for all windows we want to apply to + typedef struct WindowTask WindowTask; + struct WindowTask { - if(panel->first != &rd_nil_panel_node) + WindowTask *next; + RD_Cfg *window; + }; + WindowTask start_window_task = {0, rd_cfg_from_id(rd_regs()->window)}; + WindowTask *first_window_task = &start_window_task; + WindowTask *last_window_task = first_window_task; + if(rd_regs()->all_windows) + { + for(RD_WindowState *ws = rd_state->first_window_state; ws != &rd_nil_window_state; ws = ws->order_next) { - continue; - } - for(RD_CfgNode *tab_n = panel->tabs.first; tab_n != 0; tab_n = tab_n->next) - { - RD_Cfg *tab = tab_n->v; - if(rd_cfg_is_project_filtered(tab)) { continue; } - String8 tab_expr = rd_expr_from_cfg(tab); - String8 tab_file_path = rd_file_path_from_eval_string(scratch.arena, tab_expr); - if((str8_match(tab->string, str8_lit("text"), 0) || str8_match(tab->string, str8_lit("pending"), 0)) && - path_match_normalized(tab_file_path, file_path)) + if(ws->cfg_id == rd_regs()->window) { - panel_w_this_src_code = panel; - view_w_this_src_code = tab; - if(tab == panel->selected_tab) - { - break; - } + continue; } + WindowTask *t = push_array(scratch.arena, WindowTask, 1); + SLLQueuePush(first_window_task, last_window_task, t); + t->window = rd_cfg_from_id(ws->cfg_id); } } - // rjf: try to find panel/view pair that has any *auto* source code tab open - RD_PanelNode *panel_w_auto = &rd_nil_panel_node; - RD_Cfg *view_w_auto = &rd_nil_cfg; - for(RD_PanelNode *panel = panel_tree.root; - panel != &rd_nil_panel_node; - panel = rd_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) + //- rjf: for each window, determine how what it's viewing corresponds to the + // location we need to be finding. + typedef struct WindowInfo WindowInfo; + struct WindowInfo { - if(panel->first != &rd_nil_panel_node) - { - continue; - } - for(RD_CfgNode *tab_n = panel->tabs.first; tab_n != 0; tab_n = tab_n->next) - { - RD_Cfg *tab = tab_n->v; - if(rd_cfg_is_project_filtered(tab)) { continue; } - RD_RegsScope(.tab = tab->id, .view = tab->id) - { - if(str8_match(tab->string, str8_lit("text"), 0) && - rd_view_setting_b32_from_name(str8_lit("auto"))) - { - panel_w_auto = panel; - view_w_auto = tab; - } - } - } - } - - // rjf: find a panel that already has *any* code open (prioritize largest) - RD_PanelNode *panel_w_any_src_code = &rd_nil_panel_node; + WindowInfo *next; + RD_Cfg *window; + RD_PanelTree panel_tree; + RD_PanelNode *panel_w_this_src_code; + RD_Cfg *view_w_this_src_code; + RD_PanelNode *panel_w_auto; + RD_Cfg *view_w_auto; + RD_PanelNode *panel_w_any_src_code; + RD_PanelNode *panel_w_disasm; + RD_Cfg *view_w_disasm; + RD_PanelNode *biggest_panel; + RD_PanelNode *biggest_empty_panel; + }; + WindowInfo *first_window_info = 0; + WindowInfo *last_window_info = 0; + for(WindowTask *t = first_window_task; t != 0; t = t->next) { - Rng2F32 root_rect = r2f32(v2f32(0, 0), v2f32(1000, 1000)); - F32 best_panel_area = 0; + RD_Cfg *window = t->window; + RD_PanelTree panel_tree = rd_panel_tree_from_cfg(scratch.arena, window); + WindowInfo *info = push_array(scratch.arena, WindowInfo, 1); + SLLQueuePush(first_window_info, last_window_info, info); + info->window = window; + info->panel_tree = panel_tree; + + // rjf: first, try to find panel/view pair that already has the src file open + info->panel_w_this_src_code = &rd_nil_panel_node; + info->view_w_this_src_code = &rd_nil_cfg; for(RD_PanelNode *panel = panel_tree.root; panel != &rd_nil_panel_node; panel = rd_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) @@ -14688,258 +14729,470 @@ rd_frame(void) { continue; } - Rng2F32 panel_rect = rd_target_rect_from_panel_node(root_rect, panel_tree.root, panel); - Vec2F32 panel_rect_dim = dim_2f32(panel_rect); - F32 panel_area = panel_rect_dim.x*panel_rect_dim.y; for(RD_CfgNode *tab_n = panel->tabs.first; tab_n != 0; tab_n = tab_n->next) { RD_Cfg *tab = tab_n->v; if(rd_cfg_is_project_filtered(tab)) { continue; } - String8 view_expr = rd_expr_from_cfg(tab); - String8 file_path = rd_file_path_from_eval_string(scratch.arena, view_expr); - if(str8_match(tab->string, str8_lit("text"), 0) && file_path.size != 0 && panel_area > best_panel_area) + String8 tab_expr = rd_expr_from_cfg(tab); + String8 tab_file_path = rd_file_path_from_eval_string(scratch.arena, tab_expr); + if((str8_match(tab->string, str8_lit("text"), 0) || str8_match(tab->string, str8_lit("pending"), 0)) && + path_match_normalized(tab_file_path, file_path)) { - panel_w_any_src_code = panel; - best_panel_area = panel_area; - break; - } - } - } - } - - // rjf: try to find panel/view pair that has disassembly open (prioritize largest) - RD_PanelNode *panel_w_disasm = &rd_nil_panel_node; - RD_Cfg *view_w_disasm = &rd_nil_cfg; - { - Rng2F32 root_rect = r2f32(v2f32(0, 0), v2f32(1000, 1000)); - F32 best_panel_area = 0; - for(RD_PanelNode *panel = panel_tree.root; - panel != &rd_nil_panel_node; - panel = rd_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) - { - if(panel->first != &rd_nil_panel_node) - { - continue; - } - Rng2F32 panel_rect = rd_target_rect_from_panel_node(root_rect, panel_tree.root, panel); - Vec2F32 panel_rect_dim = dim_2f32(panel_rect); - F32 panel_area = panel_rect_dim.x*panel_rect_dim.y; - for(RD_CfgNode *tab_n = panel->tabs.first; tab_n != 0; tab_n = tab_n->next) - { - RD_Cfg *tab = tab_n->v; - if(rd_cfg_is_project_filtered(tab)) { continue; } - RD_RegsScope(.view = tab->id, .tab = tab->id) - { - B32 tab_is_selected = (tab == panel->selected_tab); - String8 expr_string = rd_expr_from_cfg(tab); - if(str8_match(tab->string, str8_lit("disasm"), 0) && expr_string.size == 0 && panel_area > best_panel_area) + info->panel_w_this_src_code = panel; + info->view_w_this_src_code = tab; + if(tab == panel->selected_tab) { - panel_w_disasm = panel; - view_w_disasm = tab; + break; + } + } + } + } + + // rjf: try to find panel/view pair that has any *auto* source code tab open + info->panel_w_auto = &rd_nil_panel_node; + info->view_w_auto = &rd_nil_cfg; + for(RD_PanelNode *panel = panel_tree.root; + panel != &rd_nil_panel_node; + panel = rd_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) + { + if(panel->first != &rd_nil_panel_node) + { + continue; + } + for(RD_CfgNode *tab_n = panel->tabs.first; tab_n != 0; tab_n = tab_n->next) + { + RD_Cfg *tab = tab_n->v; + if(rd_cfg_is_project_filtered(tab)) { continue; } + RD_RegsScope(.tab = tab->id, .view = tab->id) + { + if(str8_match(tab->string, str8_lit("text"), 0) && + rd_view_setting_b32_from_name(str8_lit("auto"))) + { + info->panel_w_auto = panel; + info->view_w_auto = tab; + } + } + } + } + + // rjf: find a panel that already has *any* code open (prioritize largest) + info->panel_w_any_src_code = &rd_nil_panel_node; + { + Rng2F32 root_rect = r2f32(v2f32(0, 0), v2f32(1000, 1000)); + F32 best_panel_area = 0; + for(RD_PanelNode *panel = panel_tree.root; + panel != &rd_nil_panel_node; + panel = rd_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) + { + if(panel->first != &rd_nil_panel_node) + { + continue; + } + Rng2F32 panel_rect = rd_target_rect_from_panel_node(root_rect, panel_tree.root, panel); + Vec2F32 panel_rect_dim = dim_2f32(panel_rect); + F32 panel_area = panel_rect_dim.x*panel_rect_dim.y; + for(RD_CfgNode *tab_n = panel->tabs.first; tab_n != 0; tab_n = tab_n->next) + { + RD_Cfg *tab = tab_n->v; + if(rd_cfg_is_project_filtered(tab)) { continue; } + String8 view_expr = rd_expr_from_cfg(tab); + String8 file_path = rd_file_path_from_eval_string(scratch.arena, view_expr); + if(str8_match(tab->string, str8_lit("text"), 0) && file_path.size != 0 && panel_area > best_panel_area) + { + info->panel_w_any_src_code = panel; best_panel_area = panel_area; - if(tab_is_selected) + break; + } + } + } + } + + // rjf: try to find panel/view pair that has disassembly open (prioritize largest) + info->panel_w_disasm = &rd_nil_panel_node; + info->view_w_disasm = &rd_nil_cfg; + { + Rng2F32 root_rect = r2f32(v2f32(0, 0), v2f32(1000, 1000)); + F32 best_panel_area = 0; + for(RD_PanelNode *panel = panel_tree.root; + panel != &rd_nil_panel_node; + panel = rd_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) + { + if(panel->first != &rd_nil_panel_node) + { + continue; + } + Rng2F32 panel_rect = rd_target_rect_from_panel_node(root_rect, panel_tree.root, panel); + Vec2F32 panel_rect_dim = dim_2f32(panel_rect); + F32 panel_area = panel_rect_dim.x*panel_rect_dim.y; + for(RD_CfgNode *tab_n = panel->tabs.first; tab_n != 0; tab_n = tab_n->next) + { + RD_Cfg *tab = tab_n->v; + if(rd_cfg_is_project_filtered(tab)) { continue; } + RD_RegsScope(.view = tab->id, .tab = tab->id) + { + B32 tab_is_selected = (tab == panel->selected_tab); + String8 expr_string = rd_expr_from_cfg(tab); + if(str8_match(tab->string, str8_lit("disasm"), 0) && expr_string.size == 0 && panel_area > best_panel_area) { - break; + info->panel_w_disasm = panel; + info->view_w_disasm = tab; + best_panel_area = panel_area; + if(tab_is_selected) + { + break; + } } } } } } - } - - // rjf: find the biggest panel - RD_PanelNode *biggest_panel = &rd_nil_panel_node; - { - Rng2F32 root_rect = r2f32(v2f32(0, 0), v2f32(1000, 1000)); - F32 best_panel_area = 0; - for(RD_PanelNode *panel = panel_tree.root; - panel != &rd_nil_panel_node; - panel = rd_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) + + // rjf: find the biggest panel + info->biggest_panel = &rd_nil_panel_node; { - if(panel->first != &rd_nil_panel_node) + Rng2F32 root_rect = r2f32(v2f32(0, 0), v2f32(1000, 1000)); + F32 best_panel_area = 0; + for(RD_PanelNode *panel = panel_tree.root; + panel != &rd_nil_panel_node; + panel = rd_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) { - continue; - } - Rng2F32 panel_rect = rd_target_rect_from_panel_node(root_rect, panel_tree.root, panel); - Vec2F32 panel_rect_dim = dim_2f32(panel_rect); - F32 panel_area = panel_rect_dim.x*panel_rect_dim.y; - if((best_panel_area == 0 || panel_area > best_panel_area)) - { - best_panel_area = panel_area; - biggest_panel = panel; - } - } - } - - // rjf: find the biggest empty panel - RD_PanelNode *biggest_empty_panel = &rd_nil_panel_node; - { - Rng2F32 root_rect = r2f32(v2f32(0, 0), v2f32(1000, 1000)); - F32 best_panel_area = 0; - for(RD_PanelNode *panel = panel_tree.root; - panel != &rd_nil_panel_node; - panel = rd_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) - { - if(panel->first != &rd_nil_panel_node) - { - continue; - } - Rng2F32 panel_rect = rd_target_rect_from_panel_node(root_rect, panel_tree.root, panel); - Vec2F32 panel_rect_dim = dim_2f32(panel_rect); - F32 panel_area = panel_rect_dim.x*panel_rect_dim.y; - B32 panel_is_empty = 1; - for(RD_CfgNode *n = panel->tabs.first; n != 0; n = n->next) - { - RD_Cfg *tab = n->v; - if(!rd_cfg_is_project_filtered(tab)) + if(panel->first != &rd_nil_panel_node) { - panel_is_empty = 0; - break; + continue; + } + Rng2F32 panel_rect = rd_target_rect_from_panel_node(root_rect, panel_tree.root, panel); + Vec2F32 panel_rect_dim = dim_2f32(panel_rect); + F32 panel_area = panel_rect_dim.x*panel_rect_dim.y; + if((best_panel_area == 0 || panel_area > best_panel_area)) + { + best_panel_area = panel_area; + info->biggest_panel = panel; } } - if(panel_is_empty && (best_panel_area == 0 || panel_area > best_panel_area)) + } + + // rjf: find the biggest empty panel + info->biggest_empty_panel = &rd_nil_panel_node; + { + Rng2F32 root_rect = r2f32(v2f32(0, 0), v2f32(1000, 1000)); + F32 best_panel_area = 0; + for(RD_PanelNode *panel = panel_tree.root; + panel != &rd_nil_panel_node; + panel = rd_panel_node_rec__depth_first_pre(panel_tree.root, panel).next) { - best_panel_area = panel_area; - biggest_empty_panel = panel; + if(panel->first != &rd_nil_panel_node) + { + continue; + } + Rng2F32 panel_rect = rd_target_rect_from_panel_node(root_rect, panel_tree.root, panel); + Vec2F32 panel_rect_dim = dim_2f32(panel_rect); + F32 panel_area = panel_rect_dim.x*panel_rect_dim.y; + B32 panel_is_empty = 1; + for(RD_CfgNode *n = panel->tabs.first; n != 0; n = n->next) + { + RD_Cfg *tab = n->v; + if(!rd_cfg_is_project_filtered(tab)) + { + panel_is_empty = 0; + break; + } + } + if(panel_is_empty && (best_panel_area == 0 || panel_area > best_panel_area)) + { + best_panel_area = panel_area; + info->biggest_empty_panel = panel; + } } } } - // rjf: choose panel for source code - RD_PanelNode *src_code_dst_panel = &rd_nil_panel_node; - if(file_path.size != 0) + //- rjf: build find-code-location tasks for windows which we *definitely* want + // to snap - in other words, windows with the destination things focused. + typedef struct FindCodeLocTask FindCodeLocTask; + struct FindCodeLocTask { - if(src_code_dst_panel == &rd_nil_panel_node) { src_code_dst_panel = panel_w_this_src_code; } - if(src_code_dst_panel == &rd_nil_panel_node) { src_code_dst_panel = panel_w_auto; } - if(src_code_dst_panel == &rd_nil_panel_node) { src_code_dst_panel = panel_w_any_src_code; } - if(src_code_dst_panel == &rd_nil_panel_node) { src_code_dst_panel = biggest_empty_panel; } - if(src_code_dst_panel == &rd_nil_panel_node) { src_code_dst_panel = biggest_panel; } - } - - // rjf: choose panel for disassembly - RD_PanelNode *disasm_dst_panel = &rd_nil_panel_node; - if(vaddr != 0) + FindCodeLocTask *next; + RD_Cfg *window; + RD_PanelNode *src_code_dst_panel; + RD_PanelNode *disasm_dst_panel; + RD_PanelNode *panel_w_this_src_code; + RD_Cfg *view_w_this_src_code; + RD_PanelNode *panel_w_auto; + RD_Cfg *view_w_auto; + RD_PanelNode *panel_w_disasm; + RD_Cfg *view_w_disasm; + }; + FindCodeLocTask *first_task = 0; + FindCodeLocTask *last_task = 0; + B32 did_src_code_snap = 0; + B32 did_disasm_snap = 0; + for(WindowInfo *info = first_window_info; info != 0; info = info->next) { - if(disasm_dst_panel == &rd_nil_panel_node) { disasm_dst_panel = panel_w_disasm; } - if(disasm_dst_panel == &rd_nil_panel_node) { disasm_dst_panel = biggest_empty_panel; } - if(disasm_dst_panel == &rd_nil_panel_node) { disasm_dst_panel = biggest_panel; } - } - - // rjf: if disasm and source code match: - // if disasm preferred, cancel source - // if source preferred, cancel disasm - if(disasm_dst_panel == src_code_dst_panel) - { - if(rd_regs()->prefer_disasm) + // rjf: choose panel for source code + RD_PanelNode *src_code_dst_panel = &rd_nil_panel_node; + if(file_path.size != 0 && info->panel_w_this_src_code->selected_tab == info->view_w_this_src_code) { - src_code_dst_panel = &rd_nil_panel_node; + src_code_dst_panel = info->panel_w_this_src_code; } - else + + // rjf: choose panel for disassembly + RD_PanelNode *disasm_dst_panel = &rd_nil_panel_node; + if(vaddr != 0 && info->panel_w_disasm->selected_tab == info->view_w_disasm) + { + disasm_dst_panel = info->panel_w_disasm; + } + + // rjf: push task + if(src_code_dst_panel != &rd_nil_panel_node || disasm_dst_panel != &rd_nil_panel_node) + { + FindCodeLocTask *t = push_array(scratch.arena, FindCodeLocTask, 1); + SLLQueuePush(first_task, last_task, t); + t->window = info->window; + t->src_code_dst_panel = src_code_dst_panel; + t->disasm_dst_panel = disasm_dst_panel; + t->panel_w_this_src_code= info->panel_w_this_src_code; + t->view_w_this_src_code = info->view_w_this_src_code; + t->panel_w_auto = info->panel_w_auto; + t->view_w_auto = info->view_w_auto; + t->panel_w_disasm = info->panel_w_disasm; + t->view_w_disasm = info->view_w_disasm; + if(src_code_dst_panel != &rd_nil_panel_node) { did_src_code_snap = 1; } + if(disasm_dst_panel != &rd_nil_panel_node) { did_disasm_snap = 1; } + } + } + + //- rjf: fallback: build find-code-location tasks for windows which have the + // right things, but they're not focused. + for(WindowInfo *info = first_window_info; info != 0; info = info->next) + { + // rjf: choose panel for source code + RD_PanelNode *src_code_dst_panel = &rd_nil_panel_node; + if(!did_src_code_snap && file_path.size != 0) + { + if(src_code_dst_panel == &rd_nil_panel_node) { src_code_dst_panel = info->panel_w_this_src_code; } + if(src_code_dst_panel == &rd_nil_panel_node) { src_code_dst_panel = info->panel_w_auto; } + } + + // rjf: choose panel for disassembly + RD_PanelNode *disasm_dst_panel = &rd_nil_panel_node; + if(!did_disasm_snap && vaddr != 0) + { + if(disasm_dst_panel == &rd_nil_panel_node) { disasm_dst_panel = info->panel_w_disasm; } + } + + // rjf: push task + if(src_code_dst_panel != &rd_nil_panel_node || disasm_dst_panel != &rd_nil_panel_node) + { + FindCodeLocTask *t = push_array(scratch.arena, FindCodeLocTask, 1); + SLLQueuePush(first_task, last_task, t); + t->window = info->window; + t->src_code_dst_panel = src_code_dst_panel; + t->disasm_dst_panel = disasm_dst_panel; + t->panel_w_this_src_code= info->panel_w_this_src_code; + t->view_w_this_src_code = info->view_w_this_src_code; + t->panel_w_auto = info->panel_w_auto; + t->view_w_auto = info->view_w_auto; + t->panel_w_disasm = info->panel_w_disasm; + t->view_w_disasm = info->view_w_disasm; + if(src_code_dst_panel != &rd_nil_panel_node) { did_src_code_snap = 1; } + if(disasm_dst_panel != &rd_nil_panel_node) { did_disasm_snap = 1; } + } + } + + //- rjf: fallback: build find-code-location tasks for windows w/ auto tabs + for(WindowInfo *info = first_window_info; info != 0; info = info->next) + { + // rjf: choose panel for source code + RD_PanelNode *src_code_dst_panel = &rd_nil_panel_node; + if(!did_src_code_snap && file_path.size != 0) + { + if(src_code_dst_panel == &rd_nil_panel_node) { src_code_dst_panel = info->panel_w_auto; } + } + + // rjf: push task + if(src_code_dst_panel != &rd_nil_panel_node) + { + FindCodeLocTask *t = push_array(scratch.arena, FindCodeLocTask, 1); + SLLQueuePush(first_task, last_task, t); + t->window = info->window; + t->src_code_dst_panel = src_code_dst_panel; + t->disasm_dst_panel = &rd_nil_panel_node; + t->panel_w_this_src_code= info->panel_w_this_src_code; + t->view_w_this_src_code = info->view_w_this_src_code; + t->panel_w_auto = info->panel_w_auto; + t->view_w_auto = info->view_w_auto; + t->panel_w_disasm = info->panel_w_disasm; + t->view_w_disasm = info->view_w_disasm; + if(src_code_dst_panel != &rd_nil_panel_node) { did_src_code_snap = 1; } + } + } + + //- rjf: fallback: build find-code-location tasks for windows which did not + // have the right things at all, but have reasonable candidate panels for + // snapping. + for(WindowInfo *info = first_window_info; info != 0; info = info->next) + { + // rjf: choose panel for source code + RD_PanelNode *src_code_dst_panel = &rd_nil_panel_node; + if(!did_src_code_snap && file_path.size != 0) + { + if(src_code_dst_panel == &rd_nil_panel_node) { src_code_dst_panel = info->panel_w_this_src_code; } + if(src_code_dst_panel == &rd_nil_panel_node) { src_code_dst_panel = info->panel_w_auto; } + if(src_code_dst_panel == &rd_nil_panel_node) { src_code_dst_panel = info->panel_w_any_src_code; } + if(src_code_dst_panel == &rd_nil_panel_node) { src_code_dst_panel = info->biggest_empty_panel; } + if(src_code_dst_panel == &rd_nil_panel_node) { src_code_dst_panel = info->biggest_panel; } + } + + // rjf: choose panel for disassembly + RD_PanelNode *disasm_dst_panel = &rd_nil_panel_node; + if(!did_disasm_snap && vaddr != 0) + { + if(disasm_dst_panel == &rd_nil_panel_node) { disasm_dst_panel = info->panel_w_disasm; } + if(disasm_dst_panel == &rd_nil_panel_node) { disasm_dst_panel = info->biggest_empty_panel; } + if(disasm_dst_panel == &rd_nil_panel_node) { disasm_dst_panel = info->biggest_panel; } + } + + // rjf: push task + if(src_code_dst_panel != &rd_nil_panel_node || disasm_dst_panel != &rd_nil_panel_node) + { + FindCodeLocTask *t = push_array(scratch.arena, FindCodeLocTask, 1); + SLLQueuePush(first_task, last_task, t); + t->window = info->window; + t->src_code_dst_panel = src_code_dst_panel; + t->disasm_dst_panel = disasm_dst_panel; + t->panel_w_this_src_code= info->panel_w_this_src_code; + t->view_w_this_src_code = info->view_w_this_src_code; + t->panel_w_auto = info->panel_w_auto; + t->view_w_auto = info->view_w_auto; + t->panel_w_disasm = info->panel_w_disasm; + t->view_w_disasm = info->view_w_disasm; + } + } + + //- rjf: perform the find-code-location for each task + for(FindCodeLocTask *t = first_task; t != 0; t = t->next) + { + RD_PanelNode *src_code_dst_panel = t->src_code_dst_panel; + RD_PanelNode *disasm_dst_panel = t->disasm_dst_panel; + + // rjf: if disasm and source code match: + // if disasm preferred, cancel source + // if source preferred, cancel disasm + if(disasm_dst_panel == src_code_dst_panel) + { + if(rd_regs()->prefer_disasm) + { + src_code_dst_panel = &rd_nil_panel_node; + } + else + { + disasm_dst_panel = &rd_nil_panel_node; + } + } + + // rjf: if disasm is not preferred, and we have no disassembly view + // open at all, cancel disasm, so that it doesn't open if the user + // doesn't want it. + if(!rd_regs()->prefer_disasm && t->panel_w_disasm == &rd_nil_panel_node && file_path.size != 0) { disasm_dst_panel = &rd_nil_panel_node; } - } - - // rjf: if disasm is not preferred, and we have no disassembly view - // open at all, cancel disasm, so that it doesn't open if the user - // doesn't want it. - if(!rd_regs()->prefer_disasm && panel_w_disasm == &rd_nil_panel_node && file_path.size != 0) - { - disasm_dst_panel = &rd_nil_panel_node; - } - - // rjf: if disasm is not preferred, and we have no disassembly view - // *selected* at all, cancel disasm, so that it doesn't open if the user - // doesn't want it. - if(!rd_regs()->prefer_disasm && view_w_disasm != &rd_nil_cfg && rd_cfg_child_from_string(view_w_disasm, str8_lit("selected")) == &rd_nil_cfg && - file_path.size != 0) - { - disasm_dst_panel = &rd_nil_panel_node; - } - - // rjf: given the above, find source code location. - if(file_path.size != 0 && src_code_dst_panel != &rd_nil_panel_node) - { - RD_PanelNode *dst_panel = src_code_dst_panel; - // rjf: construct new view if needed - RD_Cfg *dst_tab = view_w_this_src_code; - if(dst_tab == &rd_nil_cfg && dst_panel == panel_w_auto && view_w_auto != &rd_nil_cfg) + // rjf: if disasm is not preferred, and we have no disassembly view + // *selected* at all, cancel disasm, so that it doesn't open if the user + // doesn't want it. + if(!rd_regs()->prefer_disasm && t->view_w_disasm != &rd_nil_cfg && rd_cfg_child_from_string(t->view_w_disasm, str8_lit("selected")) == &rd_nil_cfg && + file_path.size != 0) { - dst_tab = view_w_auto; - RD_ViewState *vs = rd_view_state_from_cfg(dst_tab); - vs->last_frame_index_built = 0; - RD_Cfg *expr = rd_cfg_child_from_string_or_alloc(dst_tab, str8_lit("expression")); - rd_cfg_new_replace(expr, rd_eval_string_from_file_path(scratch.arena, file_path)); - rd_cfg_new_replace(rd_cfg_child_from_string(dst_tab, str8_lit("cursor_line")), str8_lit("1")); - rd_cfg_new_replace(rd_cfg_child_from_string(dst_tab, str8_lit("cursor_column")), str8_lit("1")); - rd_cfg_new_replace(rd_cfg_child_from_string(dst_tab, str8_lit("mark_line")), str8_lit("1")); - rd_cfg_new_replace(rd_cfg_child_from_string(dst_tab, str8_lit("mark_column")), str8_lit("1")); - } - else if(dst_panel != &rd_nil_panel_node && dst_tab == &rd_nil_cfg) - { - dst_tab = rd_cfg_new(dst_panel->cfg, str8_lit("text")); - RD_Cfg *expr = rd_cfg_new(dst_tab, str8_lit("expression")); - rd_cfg_new(expr, rd_eval_string_from_file_path(scratch.arena, file_path)); - RD_Cfg *auto_root = rd_cfg_new(dst_tab, str8_lit("auto")); - rd_cfg_new(auto_root, str8_lit("1")); + disasm_dst_panel = &rd_nil_panel_node; } - // rjf: determine if we need a contain or center - RD_CmdKind cursor_snap_kind = RD_CmdKind_CenterCursor; - if(dst_panel != &rd_nil_panel_node && dst_tab == view_w_this_src_code && dst_panel->selected_tab == dst_tab) + // rjf: snap to source code + if(file_path.size != 0 && src_code_dst_panel != &rd_nil_panel_node) { - cursor_snap_kind = RD_CmdKind_ContainCursor; - } - - // rjf: move cursor & snap-to-cursor - if(dst_panel != &rd_nil_panel_node) RD_RegsScope(.panel = dst_panel->cfg->id, - .view = dst_tab->id, - .tab = dst_tab->id) - { - if(rd_regs()->force_focus) + RD_PanelNode *dst_panel = src_code_dst_panel; + + // rjf: construct new view if needed + RD_Cfg *dst_tab = t->view_w_this_src_code; + if(dst_tab == &rd_nil_cfg && dst_panel == t->panel_w_auto && t->view_w_auto != &rd_nil_cfg) { - rd_cmd(RD_CmdKind_FocusPanel); + dst_tab = t->view_w_auto; + RD_ViewState *vs = rd_view_state_from_cfg(dst_tab); + vs->last_frame_index_built = 0; + RD_Cfg *expr = rd_cfg_child_from_string_or_alloc(dst_tab, str8_lit("expression")); + rd_cfg_new_replace(expr, rd_eval_string_from_file_path(scratch.arena, file_path)); + rd_cfg_new_replace(rd_cfg_child_from_string(dst_tab, str8_lit("cursor_line")), str8_lit("1")); + rd_cfg_new_replace(rd_cfg_child_from_string(dst_tab, str8_lit("cursor_column")), str8_lit("1")); + rd_cfg_new_replace(rd_cfg_child_from_string(dst_tab, str8_lit("mark_line")), str8_lit("1")); + rd_cfg_new_replace(rd_cfg_child_from_string(dst_tab, str8_lit("mark_column")), str8_lit("1")); } - rd_cmd(RD_CmdKind_FocusTab); - if(point.line != 0) + else if(dst_panel != &rd_nil_panel_node && dst_tab == &rd_nil_cfg) { - rd_cmd(RD_CmdKind_GoToLine, .cursor = point); + dst_tab = rd_cfg_new(dst_panel->cfg, str8_lit("text")); + RD_Cfg *expr = rd_cfg_new(dst_tab, str8_lit("expression")); + rd_cfg_new(expr, rd_eval_string_from_file_path(scratch.arena, file_path)); + RD_Cfg *auto_root = rd_cfg_new(dst_tab, str8_lit("auto")); + rd_cfg_new(auto_root, str8_lit("1")); } - rd_cmd(cursor_snap_kind); + + // rjf: determine if we need a contain or center + RD_CmdKind cursor_snap_kind = RD_CmdKind_CenterCursor; + if(dst_panel != &rd_nil_panel_node && dst_tab == t->view_w_this_src_code && dst_panel->selected_tab == dst_tab) + { + cursor_snap_kind = RD_CmdKind_ContainCursor; + } + + // rjf: move cursor & snap-to-cursor + if(dst_panel != &rd_nil_panel_node) RD_RegsScope(.window = t->window->id, + .panel = dst_panel->cfg->id, + .view = dst_tab->id, + .tab = dst_tab->id) + { + if(rd_regs()->force_focus) + { + rd_cmd(RD_CmdKind_FocusPanel); + } + rd_cmd(RD_CmdKind_FocusTab); + if(point.line != 0) + { + rd_cmd(RD_CmdKind_GoToLine, .cursor = point); + } + rd_cmd(cursor_snap_kind); + } + + // rjf: record + rd_cmd(RD_CmdKind_RecordFileInProject, .file_path = file_path); } - // rjf: record - rd_cmd(RD_CmdKind_RecordFileInProject, .file_path = file_path); - } - - // rjf: given the above, find disassembly location. - if(process != &ctrl_entity_nil && vaddr != 0 && disasm_dst_panel != &rd_nil_panel_node) - { - RD_PanelNode *dst_panel = disasm_dst_panel; - - // rjf: construct new tab if needed - RD_Cfg *dst_tab = view_w_disasm; - if(dst_panel != &rd_nil_panel_node && view_w_disasm == &rd_nil_cfg) + // rjf: snap to disasm + if(process != &ctrl_entity_nil && vaddr != 0 && disasm_dst_panel != &rd_nil_panel_node) { - dst_tab = rd_cfg_new(dst_panel->cfg, str8_lit("disasm")); - } - - // rjf: determine if we need a contain or center - RD_CmdKind cursor_snap_kind = RD_CmdKind_CenterCursor; - if(dst_tab == view_w_disasm && dst_panel->selected_tab == dst_tab) - { - cursor_snap_kind = RD_CmdKind_ContainCursor; - } - - // rjf: move cursor & snap-to-cursor - if(dst_panel != &rd_nil_panel_node) RD_RegsScope(.panel = dst_panel->cfg->id, - .tab = dst_tab->id, - .view = dst_tab->id) - { - rd_cmd(RD_CmdKind_FocusTab); - rd_cmd(RD_CmdKind_GoToAddress, .process = process->handle, .vaddr = vaddr); - rd_cmd(cursor_snap_kind); + RD_PanelNode *dst_panel = disasm_dst_panel; + + // rjf: construct new tab if needed + RD_Cfg *dst_tab = t->view_w_disasm; + if(dst_panel != &rd_nil_panel_node && t->view_w_disasm == &rd_nil_cfg) + { + dst_tab = rd_cfg_new(dst_panel->cfg, str8_lit("disasm")); + } + + // rjf: determine if we need a contain or center + RD_CmdKind cursor_snap_kind = RD_CmdKind_CenterCursor; + if(dst_tab == t->view_w_disasm && dst_panel->selected_tab == dst_tab) + { + cursor_snap_kind = RD_CmdKind_ContainCursor; + } + + // rjf: move cursor & snap-to-cursor + if(dst_panel != &rd_nil_panel_node) RD_RegsScope(.window = t->window->id, + .panel = dst_panel->cfg->id, + .tab = dst_tab->id, + .view = dst_tab->id) + { + rd_cmd(RD_CmdKind_FocusTab); + rd_cmd(RD_CmdKind_GoToAddress, .process = process->handle, .vaddr = vaddr); + rd_cmd(cursor_snap_kind); + } } } }break; @@ -15276,10 +15529,11 @@ rd_frame(void) RD_Cfg *project = rd_cfg_child_from_string(rd_state->root_cfg, str8_lit("project")); RD_Cfg *bp = rd_cfg_new(project, str8_lit("breakpoint")); rd_cmd(RD_CmdKind_RelocateCfg, .cfg = bp->id); - if(rd_regs()->do_lister) + if(rd_regs()->do_lister && !rd_regs()->non_graphical) { rd_cmd(RD_CmdKind_PushQuery, .expr = push_str8f(scratch.arena, "query:config.$%I64x", bp->id), .do_lister = 0); } + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, "$%I64x", bp->id); } } }break; @@ -15581,7 +15835,11 @@ rd_frame(void) rd_cfg_newf(wdir, "%S/", working_directory); } rd_cmd(RD_CmdKind_SelectTarget, .cfg = target->id); - rd_cmd(RD_CmdKind_PushQuery, .expr = push_str8f(scratch.arena, "query:config.$%I64x", target->id)); + if(!rd_regs()->non_graphical) + { + rd_cmd(RD_CmdKind_PushQuery, .expr = push_str8f(scratch.arena, "query:config.$%I64x", target->id)); + } + str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, "$%I64x", target->id); }break; //- rjf: jit-debugger registration @@ -16749,6 +17007,14 @@ rd_frame(void) rd_state->num_frames_requested -= 1; } + ////////////////////////////// + //- rjf: close frame scopes + // + di_scope_close(rd_state->frame_di_scope); + ctrl_scope_close(rd_state->frame_ctrl_scope); + rd_state->frame_di_scope = frame_di_scope_restore; + rd_state->frame_ctrl_scope = frame_ctrl_scope_restore; + ////////////////////////////// //- rjf: submit rendering to all windows // diff --git a/src/raddbg/raddbg_core.h b/src/raddbg/raddbg_core.h index 6468fbc6..f202ca7f 100644 --- a/src/raddbg/raddbg_core.h +++ b/src/raddbg/raddbg_core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDBG_CORE_H @@ -634,6 +634,8 @@ struct RD_State Arena *cmds_arenas[2]; RD_CmdList cmds[2]; U64 cmds_gen; + Arena *cmd_output_arena; + String8List cmd_outputs; // rjf: popup state UI_Key popup_key; diff --git a/src/raddbg/raddbg_eval.c b/src/raddbg/raddbg_eval.c index f67da862..dd45dcd7 100644 --- a/src/raddbg/raddbg_eval.c +++ b/src/raddbg/raddbg_eval.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -1553,6 +1553,7 @@ E_TYPE_EXPAND_INFO_FUNCTION_DEF(debug_info_table) else if(str8_match(lhs_type->name, str8_lit("procedures"), 0)) {section = RDI_SectionKind_Procedures;} else if(str8_match(lhs_type->name, str8_lit("globals"), 0)) {section = RDI_SectionKind_GlobalVariables;} else if(str8_match(lhs_type->name, str8_lit("thread_locals"), 0)) {section = RDI_SectionKind_ThreadVariables;} + else if(str8_match(lhs_type->name, str8_lit("constants"), 0)) {section = RDI_SectionKind_Constants;} else if(str8_match(lhs_type->name, str8_lit("types"), 0)) {section = RDI_SectionKind_UDTs;} } @@ -1646,6 +1647,13 @@ E_TYPE_EXPAND_RANGE_FUNCTION_DEF(debug_info_table) symbol_name.str = rdi_string_from_idx(module->rdi, tvar->name_string_idx, &symbol_name.size); item_string = symbol_name; }break; + case RDI_SectionKind_Constants: + { + RDI_Constant *cnst = rdi_element_from_name_idx(module->rdi, Constants, element_idx); + String8 symbol_name = {0}; + symbol_name.str = rdi_string_from_idx(module->rdi, cnst->name_string_idx, &symbol_name.size); + item_string = symbol_name; + }break; case RDI_SectionKind_UDTs: { RDI_UDT *udt = rdi_element_from_name_idx(module->rdi, UDTs, element_idx); diff --git a/src/raddbg/raddbg_eval.h b/src/raddbg/raddbg_eval.h index c866f317..b5980a03 100644 --- a/src/raddbg/raddbg_eval.h +++ b/src/raddbg/raddbg_eval.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDBG_EVAL_H diff --git a/src/raddbg/raddbg_inc.c b/src/raddbg/raddbg_inc.c index ece449df..0a693fae 100644 --- a/src/raddbg/raddbg_inc.c +++ b/src/raddbg/raddbg_inc.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "raddbg_core.c" diff --git a/src/raddbg/raddbg_inc.h b/src/raddbg/raddbg_inc.h index deca7cb0..3109a527 100644 --- a/src/raddbg/raddbg_inc.h +++ b/src/raddbg/raddbg_inc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDBG_INC_H diff --git a/src/raddbg/raddbg_legacy_config.c b/src/raddbg/raddbg_legacy_config.c index 119ea215..fb5af05c 100644 --- a/src/raddbg/raddbg_legacy_config.c +++ b/src/raddbg/raddbg_legacy_config.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal RD_CfgList diff --git a/src/raddbg/raddbg_legacy_config.h b/src/raddbg/raddbg_legacy_config.h index 31d2f8da..384d2fc6 100644 --- a/src/raddbg/raddbg_legacy_config.h +++ b/src/raddbg/raddbg_legacy_config.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDBG_LEGACY_CONFIG_H diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index 9243b825..be6d8406 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -1,32 +1,22 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// -//~ rjf: 0.9.18 Release Notes -/* -- Adjusted identifier resolution rules in the evaluation language to prefer visualizer names when used in a call expression. For example, even if you have a variable named `bitmap`, if you evaluate `bitmap(...)`, it will prefer resolving `bitmap` to the visualizer. You can still always disambiguate with qualifiers, e.g. `local:bitmap` or `type:bitmap`. -- Adjusted the `only` view to allow arbitrary derivative expressions, rather than only member names. This allows custom expansions to insert rows for arbitrary expressions. These expressions are derivative from the expanded expression, meaning they can refer to the expanded expression via `$`, or implicitly, its member names. -- Renamed the `table` view to `columns`, and the `only` view to `rows`, since these more directly reflect the way these views are used in the evaluation visualization pipeline. -- Added an option to all text views to scroll to the bottom if the textual content changes at all. Can be used with the `Output` tab. -- Improved toggle switches to allow clicking and dragging to toggle many switches in a single operation. -- The debugger now records the last user file which was loaded while it was opened, and reopens that file on startup, if no user is explicitly specified. (#482) - - The debugger now unfocuses query bars (e.g. that opened by `Ctrl + F` in a source view) if the main view content is clicked by the mouse. The query bar can be refocused also by clicking. - - Moved call stack evaluation to occur asynchronously, so that deeper call stacks (which can be expensive to compute) do not block the UI. - - Stopped the debugger from running the default Windows message handling path for most `Alt`-based keybindings, which was causing a Windows beep sound to play. -- Fixed a bug where RDI files would sometimes fail to generate, resulting in no debug info being available on some runs. - - Fixed a bug which was preventing backslashes from working in file system querying interfaces correctly. - - Fixed a bug which was preventing some recursive call stacks from fully displaying in the debugger. - - Fixed a bug which prevented `Space` from being used as a keybinding. Bound `Space` by default to the `Accept` command (to which `Enter` / `Return` is also defaultly bound). - - Fixed a bug which was preventing conditional breakpoints from correctly being placed, if the condition expression did not evaluate when the debuggees were resumed. - - Fixed the debugger applying too much path processing, which was causing relative paths in debug info to be interpreted incorrectly. The debugger should now work much better with relative paths (e.g. produced via `/d1trimfile`). In these cases, the debugger may still not be able to fully compute the correct absolute paths, because this information is not stored within debug information. But once the debugger is redirected to the correct file once through the UI, it should work with relative paths correctly. - - If the debugger crashes, the message box which opens and displays the crash call stack now also allows the creation of crash dump files. Please submit these, if possible, with crash reports; it will help us to debug crashes more effectively. - - Fixed a bug which was causing text rendering to fail both when running the debugger on WINE and also on Windows 7. -- Fixed a bug where exception information inlined in source code would overlap the source code text. -- The debugger now correctly correctly interprets relative per-target `stdout`, `stderr`, and `stdin` paths. -*/ - -//////////////////////////////// -//~ rjf: post-0.9.16 TODO notes +//~ rjf: post-0.9.19 TODO notes +// +//- memory view +// [ ] have smaller visible range than entire memory +// space, within some bounds (e.g. 64KB) +// [ ] dynamically expand memory space, based on +// scrolling +// [ ] fix clicking through occluded panels etc. +// [ ] disambiguate . character in ASCII columns +// [ ] fix type intepretations of cursor in bottom pane +// +//- bug fixes +// [ ] disassembly sometimes has a problem where source line annotations are +// periodically removed/inserted... maybe updating on fs change when we +// shouldn't, non-deterministic line annotation path? // //- watch improvements // [ ] *ALL* expressions in watch windows need to be editable. @@ -37,14 +27,14 @@ // [ ] back/forward, using cfg wins // [ ] mouse back button should make view to go back after I double clicked // on function to open it +// [ ] expand %environment_variables% in target environment strings - is there +// a way we can defer to the underlying shell in a non-horrible way...? // //- stepping or breakpoint oddness/fixes // [ ] stepping-onto a line with a conditional breakpoint, which fails, causes a // single step over the first instruction of that line, even if the thread // would've stopped at the first instruction due to the step, were that bp not // there. -// [ ] if a breakpoint matches the entry point's starting address, its hit count -// is not correctly incremented. // [ ] breakpoints in optimized code? maybe early-terminating bp resolution loop? @bpmiss // - actually this seems to be potentially because of incomplete src-line-map info... // [ ] Mohit-reported breakpoint not hitting - may be similar thing to @bpmiss @@ -109,7 +99,6 @@ //- visualizer improvements // [ ] disasm starting address - need to use debug info for more correct results... // [ ] linked list view -// [ ] output: add option for scroll-to-bottom - ensure this shows up in universal ctx menu // [ ] multidimensional `array` // [ ] 2-vector, 3-vector, quaternion // [ ] audio waveform views @@ -186,6 +175,11 @@ //////////////////////////////// //~ rjf: Recently Completed Task Log +// +// [x] if a breakpoint matches the entry point's starting address, its hit count +// is not correctly incremented. +// [x] output: add option for scroll-to-bottom - ensure this shows up in universal ctx menu +// [x] auto-annotations for non-locals //////////////////////////////// //~ rjf: Build Options @@ -199,7 +193,6 @@ #define FNT_INIT_MANUAL 1 #define D_INIT_MANUAL 1 #define RD_INIT_MANUAL 1 -#define P2R_INIT_MANUAL 1 //////////////////////////////// //~ rjf: Includes @@ -210,6 +203,7 @@ //- rjf: [h] #include "base/base_inc.h" +#include "linker/hash_table.h" #include "os/os_inc.h" #include "async/async.h" #include "rdi_format/rdi_format_local.h" @@ -223,6 +217,8 @@ #include "coff/coff.h" #include "coff/coff_parse.h" #include "pe/pe.h" +#include "elf/elf.h" +#include "elf/elf_parse.h" #include "codeview/codeview.h" #include "codeview/codeview_parse.h" #include "msf/msf.h" @@ -230,7 +226,16 @@ #include "pdb/pdb.h" #include "pdb/pdb_parse.h" #include "pdb/pdb_stringize.h" +#include "dwarf/dwarf.h" +#include "dwarf/dwarf_parse.h" +#include "dwarf/dwarf_coff.h" +#include "dwarf/dwarf_elf.h" +#include "rdi_from_coff/rdi_from_coff.h" +#include "rdi_from_elf/rdi_from_elf.h" #include "rdi_from_pdb/rdi_from_pdb.h" +#include "rdi_from_dwarf/rdi_from_dwarf.h" +#include "rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.h" +#include "radbin/radbin.h" #include "regs/regs.h" #include "regs/rdi/regs_rdi.h" #include "dbgi/dbgi.h" @@ -252,6 +257,7 @@ //- rjf: [c] #include "base/base_inc.c" +#include "linker/hash_table.c" #include "os/os_inc.c" #include "async/async.c" #include "rdi_format/rdi_format_local.c" @@ -265,6 +271,8 @@ #include "coff/coff.c" #include "coff/coff_parse.c" #include "pe/pe.c" +#include "elf/elf.c" +#include "elf/elf_parse.c" #include "codeview/codeview.c" #include "codeview/codeview_parse.c" #include "msf/msf.c" @@ -272,7 +280,16 @@ #include "pdb/pdb.c" #include "pdb/pdb_parse.c" #include "pdb/pdb_stringize.c" +#include "dwarf/dwarf.c" +#include "dwarf/dwarf_parse.c" +#include "dwarf/dwarf_coff.c" +#include "dwarf/dwarf_elf.c" +#include "rdi_from_coff/rdi_from_coff.c" +#include "rdi_from_elf/rdi_from_elf.c" #include "rdi_from_pdb/rdi_from_pdb.c" +#include "rdi_from_dwarf/rdi_from_dwarf.c" +#include "rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.c" +#include "radbin/radbin.c" #include "regs/regs.c" #include "regs/rdi/regs_rdi.c" #include "dbgi/dbgi.c" @@ -299,7 +316,7 @@ typedef enum ExecMode { ExecMode_Normal, ExecMode_IPCSender, - ExecMode_Converter, + ExecMode_BinaryUtility, ExecMode_Help, } ExecMode; @@ -316,9 +333,12 @@ struct IPCInfo //- rjf: IPC resources #define IPC_SHARED_MEMORY_BUFFER_SIZE MB(4) StaticAssert(IPC_SHARED_MEMORY_BUFFER_SIZE > sizeof(IPCInfo), ipc_buffer_size_requirement); -global OS_Handle ipc_signal_semaphore = {0}; -global OS_Handle ipc_lock_semaphore = {0}; -global U8 *ipc_shared_memory_base = 0; +global OS_Handle ipc_sender2main_signal_semaphore = {0}; +global OS_Handle ipc_sender2main_lock_semaphore = {0}; +global U8 *ipc_sender2main_shared_memory_base = 0; +global OS_Handle ipc_main2sender_signal_semaphore = {0}; +global OS_Handle ipc_main2sender_lock_semaphore = {0}; +global U8 *ipc_main2sender_shared_memory_base = 0; global U8 ipc_s2m_ring_buffer[MB(4)] = {0}; global U64 ipc_s2m_ring_write_pos = 0; global U64 ipc_s2m_ring_read_pos = 0; @@ -334,11 +354,11 @@ ipc_signaler_thread__entry_point(void *p) ThreadNameF("[rd] ipc signaler thread"); for(;;) { - if(os_semaphore_take(ipc_signal_semaphore, max_U64)) + if(os_semaphore_take(ipc_sender2main_signal_semaphore, max_U64)) { - if(os_semaphore_take(ipc_lock_semaphore, max_U64)) + if(os_semaphore_take(ipc_sender2main_lock_semaphore, max_U64)) { - IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base; + IPCInfo *ipc_info = (IPCInfo *)ipc_sender2main_shared_memory_base; String8 msg = str8((U8 *)(ipc_info+1), ipc_info->msg_size); msg.size = Min(msg.size, IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo)); OS_MutexScope(ipc_s2m_ring_mutex) for(;;) @@ -356,7 +376,7 @@ ipc_signaler_thread__entry_point(void *p) os_condition_variable_broadcast(ipc_s2m_ring_cv); os_send_wakeup_event(); ipc_info->msg_size = 0; - os_semaphore_drop(ipc_lock_semaphore); + os_semaphore_drop(ipc_sender2main_lock_semaphore); } } } @@ -388,42 +408,6 @@ entry_point(CmdLine *cmd_line) { Temp scratch = scratch_begin(0, 0); - //- rjf: windows -> turn off output handles, as we need to control those for target processes -#if OS_WINDOWS - HANDLE output_handles[3] = - { - GetStdHandle(STD_INPUT_HANDLE), - GetStdHandle(STD_OUTPUT_HANDLE), - GetStdHandle(STD_ERROR_HANDLE), - }; - for(U64 idx = 0; idx < ArrayCount(output_handles); idx += 1) - { - B32 duplicate = 0; - for(U64 idx2 = 0; idx2 < idx; idx2 += 1) - { - if(output_handles[idx2] == output_handles[idx]) - { - duplicate = 1; - break; - } - } - if(duplicate) - { - output_handles[idx] = 0; - } - } - for(U64 idx = 0; idx < ArrayCount(output_handles); idx += 1) - { - if(output_handles[idx] != 0) - { - CloseHandle(output_handles[idx]); - } - } - SetStdHandle(STD_INPUT_HANDLE, 0); - SetStdHandle(STD_OUTPUT_HANDLE, 0); - SetStdHandle(STD_ERROR_HANDLE, 0); -#endif - //- rjf: unpack command line arguments ExecMode exec_mode = ExecMode_Normal; B32 auto_run = 0; @@ -437,9 +421,9 @@ entry_point(CmdLine *cmd_line) { exec_mode = ExecMode_IPCSender; } - else if(cmd_line_has_flag(cmd_line, str8_lit("convert"))) + else if(cmd_line_has_flag(cmd_line, str8_lit("bin"))) { - exec_mode = ExecMode_Converter; + exec_mode = ExecMode_BinaryUtility; } else if(cmd_line_has_flag(cmd_line, str8_lit("?")) || cmd_line_has_flag(cmd_line, str8_lit("help"))) @@ -467,6 +451,42 @@ entry_point(CmdLine *cmd_line) default: case ExecMode_Normal: { + //- rjf: windows -> turn off output handles, as we need to control those for target processes +#if OS_WINDOWS + HANDLE output_handles[3] = + { + GetStdHandle(STD_INPUT_HANDLE), + GetStdHandle(STD_OUTPUT_HANDLE), + GetStdHandle(STD_ERROR_HANDLE), + }; + for(U64 idx = 0; idx < ArrayCount(output_handles); idx += 1) + { + B32 duplicate = 0; + for(U64 idx2 = 0; idx2 < idx; idx2 += 1) + { + if(output_handles[idx2] == output_handles[idx]) + { + duplicate = 1; + break; + } + } + if(duplicate) + { + output_handles[idx] = 0; + } + } + for(U64 idx = 0; idx < ArrayCount(output_handles); idx += 1) + { + if(output_handles[idx] != 0) + { + CloseHandle(output_handles[idx]); + } + } + SetStdHandle(STD_INPUT_HANDLE, 0); + SetStdHandle(STD_OUTPUT_HANDLE, 0); + SetStdHandle(STD_ERROR_HANDLE, 0); +#endif + //- rjf: manual layer initialization { r_init(cmd_line); @@ -479,20 +499,36 @@ entry_point(CmdLine *cmd_line) //- rjf: setup initial target from command line args { - String8List args = cmd_line->inputs; - if(args.node_count > 0 && args.first->string.size != 0) + Temp scratch = scratch_begin(0, 0); + String8List target_args = {0}; + { + B32 after_first_non_flag = 0; + for(U64 idx = 1; idx < cmd_line->argc; idx += 1) + { + String8 arg = str8_cstring(cmd_line->argv[idx]); + if(!str8_match(str8_prefix(arg, 1), str8_lit("-"), 0) && + !str8_match(str8_prefix(arg, 1), str8_lit("--"), 0) && + !str8_match(str8_prefix(arg, 1), str8_lit("/"), 0)) + { + after_first_non_flag = 1; + } + if(after_first_non_flag) + { + str8_list_push(scratch.arena, &target_args, arg); + } + } + } + if(target_args.node_count > 0 && target_args.first->string.size != 0) { - Temp scratch = scratch_begin(0, 0); - //- rjf: unpack command line inputs String8 executable_name_string = {0}; String8 arguments_string = {0}; String8 working_directory_string = {0}; { // rjf: unpack full executable path - if(args.first->string.size != 0) + if(target_args.first->string.size != 0) { - String8 exe_name = args.first->string; + String8 exe_name = target_args.first->string; PathStyle style = path_style_from_str8(exe_name); if(style == PathStyle_Relative) { @@ -504,9 +540,9 @@ entry_point(CmdLine *cmd_line) } // rjf: unpack working directory - if(args.first->string.size != 0) + if(target_args.first->string.size != 0) { - String8 path_part_of_arg = str8_chop_last_slash(args.first->string); + String8 path_part_of_arg = str8_chop_last_slash(target_args.first->string); if(path_part_of_arg.size != 0) { String8 path = push_str8f(scratch.arena, "%S/", path_part_of_arg); @@ -516,7 +552,7 @@ entry_point(CmdLine *cmd_line) // rjf: unpack arguments String8List passthrough_args_list = {0}; - for(String8Node *n = args.first->next; n != 0; n = n->next) + for(String8Node *n = target_args.first->next; n != 0; n = n->next) { str8_list_push(scratch.arena, &passthrough_args_list, n->string); } @@ -533,30 +569,44 @@ entry_point(CmdLine *cmd_line) rd_cfg_new(exe, executable_name_string); rd_cfg_new(args, arguments_string); rd_cfg_new(wdir, working_directory_string); - - scratch_end(scratch); + rd_cmd(RD_CmdKind_SelectTarget, .cfg = target->id); } + scratch_end(scratch); } //- rjf: set up shared resources for ipc to this instance; launch IPC signaler thread { Temp scratch = scratch_begin(0, 0); U32 instance_pid = os_get_process_info()->pid; - String8 ipc_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_shared_memory_%i_", instance_pid); - String8 ipc_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_signal_semaphore_%i_", instance_pid); - String8 ipc_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_lock_semaphore_%i_", instance_pid); - OS_Handle ipc_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_shared_memory_name); - ipc_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); - ipc_signal_semaphore = os_semaphore_alloc(0, 1, ipc_signal_semaphore_name); - ipc_lock_semaphore = os_semaphore_alloc(1, 1, ipc_lock_semaphore_name); + + // rjf: set up cross-process sender -> main ring buffer + String8 ipc_sender2main_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_shared_memory_%i_", instance_pid); + String8 ipc_sender2main_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_signal_semaphore_%i_", instance_pid); + String8 ipc_sender2main_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_lock_semaphore_%i_", instance_pid); + OS_Handle ipc_sender2main_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_sender2main_shared_memory_name); + ipc_sender2main_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_sender2main_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); + ipc_sender2main_signal_semaphore = os_semaphore_alloc(0, 1, ipc_sender2main_signal_semaphore_name); + ipc_sender2main_lock_semaphore = os_semaphore_alloc(1, 1, ipc_sender2main_lock_semaphore_name); + + // rjf: set up cross-process main -> sender ring buffer + String8 ipc_main2sender_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_shared_memory_%i_", instance_pid); + String8 ipc_main2sender_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_signal_semaphore_%i_", instance_pid); + String8 ipc_main2sender_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_lock_semaphore_%i_", instance_pid); + OS_Handle ipc_main2sender_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_main2sender_shared_memory_name); + ipc_main2sender_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_main2sender_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); + ipc_main2sender_signal_semaphore = os_semaphore_alloc(0, 1, ipc_main2sender_signal_semaphore_name); + ipc_main2sender_lock_semaphore = os_semaphore_alloc(1, 1, ipc_main2sender_lock_semaphore_name); + + // rjf: set up ipc-receiver -> main thread ring buffer; launch signaler thread ipc_s2m_ring_mutex = os_mutex_alloc(); ipc_s2m_ring_cv = os_condition_variable_alloc(); - IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base; - if(ipc_shared_memory_base != 0) + IPCInfo *ipc_info = (IPCInfo *)ipc_sender2main_shared_memory_base; + if(ipc_sender2main_shared_memory_base != 0) { MemoryZeroStruct(ipc_info); os_thread_launch(ipc_signaler_thread__entry_point, 0, 0); } + scratch_end(scratch); } @@ -565,6 +615,7 @@ entry_point(CmdLine *cmd_line) for(B32 quit = 0; !quit;) { //- rjf: consume IPC messages, dispatch UI commands + B32 ipc_command_frame = 0; { Temp scratch = scratch_begin(0, 0); B32 consumed = 0; @@ -575,6 +626,7 @@ entry_point(CmdLine *cmd_line) if(unconsumed_size >= sizeof(U64)) { consumed = 1; + ipc_command_frame = 1; ipc_s2m_ring_read_pos += ring_read_struct(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_read_pos, &msg.size); msg.size = Min(msg.size, unconsumed_size); msg.str = push_array(scratch.arena, U8, msg.size); @@ -653,6 +705,24 @@ entry_point(CmdLine *cmd_line) jit_attach = 0; rd_cmd(RD_CmdKind_Attach, .pid = jit_pid); } + + //- rjf: gather command outputs & write them + if(ipc_command_frame) + { + if(ipc_main2sender_shared_memory_base != 0 && + os_semaphore_take(ipc_main2sender_lock_semaphore, os_now_microseconds()+5000000)) + { + IPCInfo *ipc_info = (IPCInfo *)ipc_main2sender_shared_memory_base; + U8 *buffer = (U8 *)(ipc_info+1); + U64 buffer_max = IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo); + StringJoin join = {str8_lit(""), str8_lit("\0"), str8_lit("")}; + String8 msg = str8_list_join(scratch.arena, &rd_state->cmd_outputs, &join); + ipc_info->msg_size = Min(buffer_max, msg.size); + MemoryCopy(buffer, msg.str, ipc_info->msg_size); + os_semaphore_drop(ipc_main2sender_signal_semaphore); + os_semaphore_drop(ipc_main2sender_lock_semaphore); + } + } } } @@ -695,100 +765,69 @@ entry_point(CmdLine *cmd_line) } //- rjf: grab destination instance's shared memory resources - String8 ipc_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_shared_memory_%i_", dst_pid); - String8 ipc_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_signal_semaphore_%i_", dst_pid); - String8 ipc_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_lock_semaphore_%i_", dst_pid); - OS_Handle ipc_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_shared_memory_name); - ipc_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); - ipc_signal_semaphore = os_semaphore_alloc(0, 1, ipc_signal_semaphore_name); - ipc_lock_semaphore = os_semaphore_alloc(1, 1, ipc_lock_semaphore_name); + String8 ipc_sender2main_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_shared_memory_%i_", dst_pid); + String8 ipc_sender2main_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_signal_semaphore_%i_", dst_pid); + String8 ipc_sender2main_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_sender2main_lock_semaphore_%i_", dst_pid); + OS_Handle ipc_sender2main_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_sender2main_shared_memory_name); + ipc_sender2main_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_sender2main_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); + ipc_sender2main_signal_semaphore = os_semaphore_alloc(0, 1, ipc_sender2main_signal_semaphore_name); + ipc_sender2main_lock_semaphore = os_semaphore_alloc(1, 1, ipc_sender2main_lock_semaphore_name); + String8 ipc_main2sender_shared_memory_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_shared_memory_%i_", dst_pid); + String8 ipc_main2sender_signal_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_signal_semaphore_%i_", dst_pid); + String8 ipc_main2sender_lock_semaphore_name = push_str8f(scratch.arena, "_raddbg_ipc_main2sender_lock_semaphore_%i_", dst_pid); + OS_Handle ipc_main2sender_shared_memory = os_shared_memory_alloc(IPC_SHARED_MEMORY_BUFFER_SIZE, ipc_main2sender_shared_memory_name); + ipc_main2sender_shared_memory_base = (U8 *)os_shared_memory_view_open(ipc_main2sender_shared_memory, r1u64(0, IPC_SHARED_MEMORY_BUFFER_SIZE)); + ipc_main2sender_signal_semaphore = os_semaphore_alloc(0, 1, ipc_main2sender_signal_semaphore_name); + ipc_main2sender_lock_semaphore = os_semaphore_alloc(1, 1, ipc_main2sender_lock_semaphore_name); //- rjf: got resources -> write message - if(ipc_shared_memory_base != 0 && - os_semaphore_take(ipc_lock_semaphore, max_U64)) + B32 wrote_message = 0; + if(ipc_sender2main_shared_memory_base != 0 && + os_semaphore_take(ipc_sender2main_lock_semaphore, max_U64)) { - IPCInfo *ipc_info = (IPCInfo *)ipc_shared_memory_base; + wrote_message = 1; + IPCInfo *ipc_info = (IPCInfo *)ipc_sender2main_shared_memory_base; U8 *buffer = (U8 *)(ipc_info+1); U64 buffer_max = IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo); StringJoin join = {str8_lit(""), str8_lit(" "), str8_lit("")}; String8 msg = str8_list_join(scratch.arena, &cmd_line->inputs, &join); ipc_info->msg_size = Min(buffer_max, msg.size); MemoryCopy(buffer, msg.str, ipc_info->msg_size); - os_semaphore_drop(ipc_signal_semaphore); - os_semaphore_drop(ipc_lock_semaphore); + os_semaphore_drop(ipc_sender2main_signal_semaphore); + os_semaphore_drop(ipc_sender2main_lock_semaphore); } + //- rjf: wrote message -> wait for outputs, read outputs + String8List outputs = {0}; + if(wrote_message && + ipc_main2sender_shared_memory_base != 0 && + os_semaphore_take(ipc_main2sender_signal_semaphore, os_now_microseconds()+10000000)) + { + if(os_semaphore_take(ipc_main2sender_lock_semaphore, max_U64)) + { + IPCInfo *ipc_info = (IPCInfo *)ipc_main2sender_shared_memory_base; + String8 msg = str8((U8 *)(ipc_info+1), ipc_info->msg_size); + msg.size = Min(msg.size, IPC_SHARED_MEMORY_BUFFER_SIZE - sizeof(IPCInfo)); + U8 split_char = 0; + outputs = str8_split(scratch.arena, msg, &split_char, 1, 0); + os_semaphore_drop(ipc_main2sender_lock_semaphore); + } + } + + //- rjf: write outputs to stdout + for(String8Node *n = outputs.first; n != 0; n = n->next) + { + fwrite(n->string.str, 1, n->string.size, stdout); + } + fflush(stdout); + scratch_end(scratch); }break; - //- rjf: built-in pdb/dwarf -> rdi converter mode - case ExecMode_Converter: + //- rjf: built-in binary utility mode + case ExecMode_BinaryUtility: { - Temp scratch = scratch_begin(0, 0); - - //- rjf: initializer pdb -> rdi conversion layer - p2r_init(); - - //- rjf: parse arguments - P2R_User2Convert *user2convert = p2r_user2convert_from_cmdln(scratch.arena, cmd_line); - - //- rjf: open output file - String8 output_name = push_str8_copy(scratch.arena, user2convert->output_name); - OS_Handle out_file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Write, output_name); - B32 out_file_is_good = !os_handle_match(out_file, os_handle_zero()); - - //- rjf: convert - P2R_Convert2Bake *convert2bake = 0; - if(out_file_is_good) ProfScope("convert") - { - convert2bake = p2r_convert(scratch.arena, user2convert); - } - - //- rjf: bake - P2R_Bake2Serialize *bake2srlz = 0; - if(out_file_is_good) ProfScope("bake") - { - bake2srlz = p2r_bake(scratch.arena, convert2bake); - } - - //- rjf: serialize - P2R_Serialize2File *srlz2file = 0; - if(out_file_is_good) ProfScope("serialize") - { - srlz2file = push_array(scratch.arena, P2R_Serialize2File, 1); - srlz2file->bundle = rdim_serialized_section_bundle_from_bake_results(&bake2srlz->bake_results); - } - - //- rjf: compress - P2R_Serialize2File *srlz2file_compressed = srlz2file; - if(out_file_is_good) if(cmd_line_has_flag(cmd_line, str8_lit("compress"))) ProfScope("compress") - { - srlz2file_compressed = push_array(scratch.arena, P2R_Serialize2File, 1); - srlz2file_compressed = p2r_compress(scratch.arena, srlz2file); - } - - //- rjf: serialize - String8List blobs = {0}; - if(out_file_is_good) - { - blobs = rdim_file_blobs_from_section_bundle(scratch.arena, &srlz2file_compressed->bundle); - } - - //- rjf: write - if(out_file_is_good) - { - U64 off = 0; - for(String8Node *n = blobs.first; n != 0; n = n->next) - { - os_file_write(out_file, r1u64(off, off+n->string.size), n->string.str); - off += n->string.size; - } - } - - //- rjf: close output file - os_file_close(out_file); - - scratch_end(scratch); + rb_entry_point(cmd_line); }break; //- rjf: help message box diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index 80fd780b..b3468ba9 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -2490,9 +2490,14 @@ typedef struct RD_MemoryViewState RD_MemoryViewState; struct RD_MemoryViewState { Rng1U64 last_view_range; + B32 last_view_range_inited; Rng1U64 last_cursor_range; + B32 last_cursor_range_inited; + U64 last_num_of_columns; + B32 last_num_of_columns_inited; B32 center_cursor; B32 contain_cursor; + B32 snap_scroll; }; EV_EXPAND_RULE_INFO_FUNCTION_DEF(memory) @@ -2512,6 +2517,10 @@ RD_VIEW_UI_FUNCTION_DEF(memory) ////////////////////////////// //- rjf: unpack parameterization info // + Vec4F32 main_bg_color_rgba = ui_color_from_name(str8_lit("background")); + Vec4F32 main_bg_color_hsva = hsva_from_rgba(main_bg_color_rgba); + Vec4F32 main_tx_color_rgba = ui_color_from_name(str8_lit("text")); + Vec4F32 main_tx_color_hsva = hsva_from_rgba(main_tx_color_rgba); F32 main_font_size = ui_bottom_font_size(); U64 base_offset = e_base_offset_from_eval(eval); U64 size = rd_view_setting_value_from_name(str8_lit("size")).u64; @@ -2536,6 +2545,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory) U64 initial_cursor_base_vaddr = cursor_base_vaddr; U64 initial_mark_base_vaddr = mark_base_vaddr; U64 num_columns = rd_view_setting_u64_from_name(str8_lit("num_columns")); + B32 track_mark_to_cursor = rd_view_setting_b32_from_name(str8_lit("track_mark_to_cursor")); if(num_columns == 0) { num_columns = 16; @@ -2545,6 +2555,18 @@ RD_VIEW_UI_FUNCTION_DEF(memory) Vec4F32 selection_color = ui_color_from_name(str8_lit("selection")); Vec4F32 border_color = ui_color_from_name(str8_lit("selection")); + ////////////////////////////// + //- rjf: unpack rich hover info + // + UI_Key memory_rich_hover_key = ui_key_from_string(ui_active_seed_key(), str8_lit("###rich_hover")); + Rng1U64 rich_hover_range = {0}; + if(rd_state->hover_regs_slot == RD_RegSlot_VaddrRange && + e_space_match(eval.space, rd_get_hover_regs()->eval_space) && + !ui_key_match(rd_get_hover_regs()->src_ui_key, memory_rich_hover_key)) + { + rich_hover_range = rd_get_hover_regs()->vaddr_range; + } + ////////////////////////////// //- rjf: process commands // @@ -2580,29 +2602,6 @@ RD_VIEW_UI_FUNCTION_DEF(memory) F32 row_height_px = floor_f32(font_size*2.f); F32 cell_width_px = floor_f32(font_size*2.f); - ////////////////////////////// - //- rjf: determine legal scroll range - // - U64 view_range_last = view_range.max; - if(view_range_last != 0) - { - view_range_last -= 1; - } - Rng1S64 scroll_idx_rng = r1s64(0, (view_range_last - view_range.min) / num_columns); - - ////////////////////////////// - //- rjf: determine visible range of rows - // - Rng1S64 viz_range_rows = {0}; - S64 num_possible_visible_rows = 0; - { - num_possible_visible_rows = dim_2f32(rect).y/row_height_px; - viz_range_rows.min = scroll_pos.y.idx + (S64)scroll_pos.y.off - !!(scroll_pos.y.off<0); - viz_range_rows.max = scroll_pos.y.idx + (S64)scroll_pos.y.off + num_possible_visible_rows, - viz_range_rows.min = clamp_1s64(scroll_idx_rng, viz_range_rows.min); - viz_range_rows.max = clamp_1s64(scroll_idx_rng, viz_range_rows.max); - } - ////////////////////////////// //- rjf: calculate rectangles // @@ -2614,183 +2613,250 @@ RD_VIEW_UI_FUNCTION_DEF(memory) Rng2F32 content_rect = r2f32p(0, row_height_px, panel_dim.x-scroll_bar_dim, panel_dim.y); ////////////////////////////// + //- rjf: determine visible range of rows (occluded & non-occluded) + // + S64 num_possible_visible_rows = num_possible_visible_rows = dim_2f32(rect).y/row_height_px;; + S64 num_possible_nonoccluded_visible_rows = (dim_2f32(content_rect).y - dim_2f32(footer_rect).y) / row_height_px; + + ////////////////////////////// + //- rjf: determine legal scroll range + // + U64 view_range_last = view_range.max; + if(view_range_last != 0) + { + view_range_last -= 1; + } + Rng1S64 scroll_idx_rng = r1s64(0, (view_range_last - view_range.min) / num_columns); + + ////////////////////////////// + //- rjf: on cursor rugpull -> update mark if needed + // + { + Rng1U64 cursor_range = r1u64(cursor_base_vaddr, cursor_base_vaddr+cursor_size); + if(mv->last_cursor_range_inited && + (mv->last_cursor_range.min != cursor_range.min || + mv->last_cursor_range.max != cursor_range.max)) + { + mv->contain_cursor = 1; + if(track_mark_to_cursor) + { + mark_base_vaddr = cursor_base_vaddr; + } + } + } + + ////////////////////////////// + //- rjf: on num of columns rugpull -> update scroll position + // + if(mv->last_num_of_columns != num_columns && mv->last_num_of_columns_inited) + { + mv->center_cursor = 1; + mv->snap_scroll = 1; + } + mv->last_num_of_columns_inited = 1; + mv->last_num_of_columns = num_columns; + + ////////////////////////////// + //- rjf: loop: compute boundaries, take events, repeat + // + B32 need_update = 1; + Rng1U64 cursor_valid_rng = {0}; + for(;;) + { + //- rjf: break if no further updates needed + if(!need_update) + { + break; + } + need_update = 0; + + //- rjf: take keyboard controls + UI_Focus(UI_FocusKind_On) if(ui_is_focus_active()) + { + U64 next_cursor_base_vaddr = cursor_base_vaddr; + U64 next_mark_base_vaddr = mark_base_vaddr; + for(UI_Event *evt = 0; ui_next_event(&evt);) + { + Vec2S64 cell_delta = {0}; + switch(evt->delta_unit) + { + default:{}break; + case UI_EventDeltaUnit_Char: + { + cell_delta.x = (S64)evt->delta_2s32.x; + cell_delta.y = (S64)evt->delta_2s32.y; + }break; + case UI_EventDeltaUnit_Word: + case UI_EventDeltaUnit_Page: + { + if(evt->delta_2s32.x < 0) + { + cell_delta.x = -(S64)(cursor_base_vaddr%num_columns); + } + else if(evt->delta_2s32.x > 0) + { + cell_delta.x = (num_columns-1) - (S64)(cursor_base_vaddr%num_columns); + } + if(evt->delta_2s32.y < 0) + { + cell_delta.y = -4; + } + else if(evt->delta_2s32.y > 0) + { + cell_delta.y = +4; + } + }break; + } + B32 good_action = 0; + if(evt->delta_2s32.x != 0 || evt->delta_2s32.y != 0) + { + good_action = 1; + } + if(good_action && evt->flags & UI_EventFlag_ZeroDeltaOnSelect && cursor_base_vaddr != mark_base_vaddr) + { + MemoryZeroStruct(&cell_delta); + } + if(good_action) + { + cell_delta.x = ClampBot(cell_delta.x, (S64)-next_cursor_base_vaddr); + cell_delta.y = ClampBot(cell_delta.y, (S64)-(next_cursor_base_vaddr/num_columns)); + next_cursor_base_vaddr += cell_delta.x; + next_cursor_base_vaddr += cell_delta.y*num_columns; + } + if(good_action && evt->flags & UI_EventFlag_PickSelectSide && cursor_base_vaddr != mark_base_vaddr) + { + if(evt->delta_2s32.x < 0 || evt->delta_2s32.y < 0) + { + next_cursor_base_vaddr = Min(cursor_base_vaddr, mark_base_vaddr); + } + else + { + next_cursor_base_vaddr = Max(cursor_base_vaddr, mark_base_vaddr); + } + } + if(good_action && !(evt->flags & UI_EventFlag_KeepMark)) + { + next_mark_base_vaddr = next_cursor_base_vaddr; + } + if(good_action) + { + need_update = 1; + mv->contain_cursor = 1; + ui_eat_event(evt); + } + } + cursor_base_vaddr = next_cursor_base_vaddr; + mark_base_vaddr = next_mark_base_vaddr; + } + + //- rjf: clamp cursor + cursor_valid_rng = view_range; + if(cursor_valid_rng.max != 0) + { + cursor_valid_rng.max -= 1; + } + if(cursor_base_vaddr != initial_cursor_base_vaddr) + { + cursor_base_vaddr = clamp_1u64(cursor_valid_rng, cursor_base_vaddr); + } + if(mark_base_vaddr != initial_mark_base_vaddr) + { + mark_base_vaddr = clamp_1u64(cursor_valid_rng, mark_base_vaddr); + } + + //- rjf: center cursor if range has changed + if(mv->last_view_range_inited && + (mv->last_view_range.max != view_range.max || + mv->last_view_range.min != view_range.min)) + { + mv->center_cursor = 1; + } + mv->last_view_range_inited = 1; + mv->last_view_range = view_range; + + //- rjf: center cursor + if(mv->center_cursor && contains_1u64(view_range, cursor_base_vaddr)) + { + mv->center_cursor = 0; + S64 cursor_row_idx = (cursor_base_vaddr - view_range.min) / num_columns; + S64 new_idx = (cursor_row_idx-num_possible_nonoccluded_visible_rows/2+1); + new_idx = clamp_1s64(scroll_idx_rng, new_idx); + ui_scroll_pt_target_idx(&scroll_pos.y, new_idx); + } + + //- rjf: contain cursor + if(mv->contain_cursor && contains_1u64(view_range, cursor_base_vaddr)) + { + mv->contain_cursor = 0; + Rng1S64 viz_range_nonoccluded_rows = {0}; + viz_range_nonoccluded_rows.min = scroll_pos.y.idx + (S64)(content_rect.y0 / row_height_px); + viz_range_nonoccluded_rows.max = viz_range_nonoccluded_rows.min + num_possible_nonoccluded_visible_rows; + viz_range_nonoccluded_rows.min = clamp_1s64(scroll_idx_rng, viz_range_nonoccluded_rows.min); + viz_range_nonoccluded_rows.max = clamp_1s64(scroll_idx_rng, viz_range_nonoccluded_rows.max); + S64 cursor_row_idx = (cursor_base_vaddr - view_range.min) / num_columns; + Rng1S64 cursor_viz_range = r1s64(clamp_1s64(scroll_idx_rng, cursor_row_idx-2), clamp_1s64(scroll_idx_rng, cursor_row_idx+3)); + S64 min_delta = Min(0, cursor_viz_range.min-viz_range_nonoccluded_rows.min); + S64 max_delta = Max(0, cursor_viz_range.max-viz_range_nonoccluded_rows.max); + S64 new_idx = scroll_pos.y.idx+min_delta+max_delta; + new_idx = clamp_1s64(scroll_idx_rng, new_idx); + ui_scroll_pt_target_idx(&scroll_pos.y, new_idx); + } + + //- rjf: snap scroll + if(mv->snap_scroll) + { + mv->snap_scroll = 0; + scroll_pos.y.off = 0; + } + } + + //////////////////////////// + //- rjf: determine selection + // + Rng1U64 selection = union_1u64(r1u64(cursor_base_vaddr, cursor_base_vaddr+cursor_size-1), + r1u64(mark_base_vaddr, mark_base_vaddr+cursor_size-1)); + + //////////////////////////// + //- rjf: determine visible range of rows (including occluded) + // + Rng1S64 viz_range_rows = {0}; + { + viz_range_rows.min = scroll_pos.y.idx + (S64)scroll_pos.y.off - !!(scroll_pos.y.off<0); + viz_range_rows.max = scroll_pos.y.idx + (S64)scroll_pos.y.off + num_possible_visible_rows, + viz_range_rows.min = clamp_1s64(scroll_idx_rng, viz_range_rows.min); + viz_range_rows.max = clamp_1s64(scroll_idx_rng, viz_range_rows.max); + } + + //////////////////////////// //- rjf: bump backwards if we are past the first + // if(viz_range_rows.min > 0) { viz_range_rows.min -= 1; content_rect.y0 -= row_height_px; } - ////////////////////////////// + //////////////////////////// //- rjf: determine visible range of bytes // Rng1U64 viz_range_bytes = {0}; - viz_range_bytes.min = view_range.min + (viz_range_rows.min)*num_columns; - viz_range_bytes.max = view_range.min + (viz_range_rows.max+1)*num_columns+1; - if(viz_range_bytes.min > viz_range_bytes.max) { - Swap(U64, viz_range_bytes.min, viz_range_bytes.max); - } - viz_range_bytes = intersect_1u64(view_range, viz_range_bytes); - - ////////////////////////////// - //- rjf: take keyboard controls - // - UI_Focus(UI_FocusKind_On) if(ui_is_focus_active()) - { - U64 next_cursor_base_vaddr = cursor_base_vaddr; - U64 next_mark_base_vaddr = mark_base_vaddr; - for(UI_Event *evt = 0; ui_next_event(&evt);) + viz_range_bytes.min = view_range.min + (viz_range_rows.min)*num_columns; + viz_range_bytes.max = view_range.min + (viz_range_rows.max+1)*num_columns+1; + if(viz_range_bytes.min > viz_range_bytes.max) { - Vec2S64 cell_delta = {0}; - switch(evt->delta_unit) - { - default:{}break; - case UI_EventDeltaUnit_Char: - { - cell_delta.x = (S64)evt->delta_2s32.x; - cell_delta.y = (S64)evt->delta_2s32.y; - }break; - case UI_EventDeltaUnit_Word: - case UI_EventDeltaUnit_Page: - { - if(evt->delta_2s32.x < 0) - { - cell_delta.x = -(S64)(cursor_base_vaddr%num_columns); - } - else if(evt->delta_2s32.x > 0) - { - cell_delta.x = (num_columns-1) - (S64)(cursor_base_vaddr%num_columns); - } - if(evt->delta_2s32.y < 0) - { - cell_delta.y = -4; - } - else if(evt->delta_2s32.y > 0) - { - cell_delta.y = +4; - } - }break; - } - B32 good_action = 0; - if(evt->delta_2s32.x != 0 || evt->delta_2s32.y != 0) - { - good_action = 1; - } - if(good_action && evt->flags & UI_EventFlag_ZeroDeltaOnSelect && cursor_base_vaddr != mark_base_vaddr) - { - MemoryZeroStruct(&cell_delta); - } - if(good_action) - { - cell_delta.x = ClampBot(cell_delta.x, (S64)-next_cursor_base_vaddr); - cell_delta.y = ClampBot(cell_delta.y, (S64)-(next_cursor_base_vaddr/num_columns)); - next_cursor_base_vaddr += cell_delta.x; - next_cursor_base_vaddr += cell_delta.y*num_columns; - } - if(good_action && evt->flags & UI_EventFlag_PickSelectSide && cursor_base_vaddr != mark_base_vaddr) - { - if(evt->delta_2s32.x < 0 || evt->delta_2s32.y < 0) - { - next_cursor_base_vaddr = Min(cursor_base_vaddr, mark_base_vaddr); - } - else - { - next_cursor_base_vaddr = Max(cursor_base_vaddr, mark_base_vaddr); - } - } - if(good_action && !(evt->flags & UI_EventFlag_KeepMark)) - { - next_mark_base_vaddr = next_cursor_base_vaddr; - } - if(good_action) - { - mv->contain_cursor = 1; - ui_eat_event(evt); - } + Swap(U64, viz_range_bytes.min, viz_range_bytes.max); } - cursor_base_vaddr = next_cursor_base_vaddr; - mark_base_vaddr = next_mark_base_vaddr; - } - - ////////////////////////////// - //- rjf: clamp cursor - // - Rng1U64 cursor_valid_rng = view_range; - if(cursor_valid_rng.max != 0) - { - cursor_valid_rng.max -= 1; - } - if(cursor_base_vaddr != initial_cursor_base_vaddr) - { - cursor_base_vaddr = clamp_1u64(cursor_valid_rng, cursor_base_vaddr); - } - if(mark_base_vaddr != initial_mark_base_vaddr) - { - mark_base_vaddr = clamp_1u64(cursor_valid_rng, mark_base_vaddr); - } - - ////////////////////////////// - //- rjf: unpack post-move cursor/mark info - // - Rng1U64 cursor_range = r1u64(cursor_base_vaddr, cursor_base_vaddr + cursor_size); - Rng1U64 mark_range = r1u64(mark_base_vaddr, mark_base_vaddr + cursor_size); - Rng1U64 selection = union_1u64(r1u64(cursor_base_vaddr, cursor_base_vaddr+cursor_size-1), - r1u64(mark_base_vaddr, mark_base_vaddr+cursor_size-1)); - - ////////////////////////////// - //- rjf: center cursor if range has changed - // - if(mv->last_view_range.max != view_range.max || - mv->last_view_range.min != view_range.min) - { - mv->center_cursor = 1; - mv->last_view_range = view_range; - } - - ////////////////////////////// - //- rjf: match mark to cursor if cursor has changed - // - if(mv->last_cursor_range.min != cursor_range.min || - mv->last_cursor_range.max != cursor_range.max) - { - mv->contain_cursor = 1; - mv->last_cursor_range = cursor_range; - mark_range = cursor_range; - } - - ////////////////////////////// - //- rjf: center cursor - // - if(mv->center_cursor) - { - mv->center_cursor = 0; - S64 cursor_row_idx = (cursor_base_vaddr - view_range.min) / num_columns; - S64 new_idx = (cursor_row_idx-num_possible_visible_rows/2+1); - new_idx = clamp_1s64(scroll_idx_rng, new_idx); - ui_scroll_pt_target_idx(&scroll_pos.y, new_idx); - } - - ////////////////////////////// - //- rjf: contain cursor - // - if(mv->contain_cursor) - { - mv->contain_cursor = 0; - S64 cursor_row_idx = (cursor_base_vaddr - view_range.min) / num_columns; - Rng1S64 cursor_viz_range = r1s64(clamp_1s64(scroll_idx_rng, cursor_row_idx-2), clamp_1s64(scroll_idx_rng, cursor_row_idx+3)); - S64 min_delta = Min(0, cursor_viz_range.min-viz_range_rows.min); - S64 max_delta = Max(0, cursor_viz_range.max-viz_range_rows.max); - S64 new_idx = scroll_pos.y.idx+min_delta+max_delta; - new_idx = clamp_1s64(scroll_idx_rng, new_idx); - ui_scroll_pt_target_idx(&scroll_pos.y, new_idx); + viz_range_bytes = intersect_1u64(view_range, viz_range_bytes); } ////////////////////////////// //- rjf: produce fancy strings for all possible byte values in all cells // DR_FStrList byte_fstrs[256] = {0}; + DR_FStrList byte_fstrs_selected[256] = {0}; { + Vec4F32 selected_color = ui_color_from_name(str8_lit("text")); Vec4F32 full_color = {0}; UI_TagF("neutral") full_color = ui_color_from_name(str8_lit("text")); Vec4F32 zero_color = full_color; @@ -2804,8 +2870,14 @@ RD_VIEW_UI_FUNCTION_DEF(memory) { text_color.w *= 0.5f; } - DR_FStr fstr = {push_str8f(scratch.arena, "%02x", byte), {font, font_raster_flags, text_color, font_size, 0, 0}}; - dr_fstrs_push(scratch.arena, &byte_fstrs[idx], &fstr); + { + DR_FStr fstr = {push_str8f(scratch.arena, "%02x", byte), {font, font_raster_flags, text_color, font_size, 0, 0}}; + dr_fstrs_push(scratch.arena, &byte_fstrs[idx], &fstr); + } + { + DR_FStr fstr = {push_str8f(scratch.arena, "%02x", byte), {font, font_raster_flags, selected_color, font_size, 0, 0}}; + dr_fstrs_push(scratch.arena, &byte_fstrs_selected[idx], &fstr); + } } } @@ -2814,9 +2886,21 @@ RD_VIEW_UI_FUNCTION_DEF(memory) // U64 visible_memory_size = dim_1u64(viz_range_bytes); U8 *visible_memory = push_array(scratch.arena, U8, visible_memory_size); + U64 *visible_memory_change_flags = push_array(scratch.arena, U64, (visible_memory_size+63)/64); + U64 *visible_memory_bad_flags = push_array(scratch.arena, U64, (visible_memory_size+63)/64); { e_space_read(eval.space, visible_memory, viz_range_bytes); } + if(eval.space.kind == RD_EvalSpaceKind_CtrlEntity) + { + CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(eval.space); + if(entity->kind == CTRL_EntityKind_Process) + { + CTRL_ProcessMemorySlice slice = ctrl_process_memory_slice_from_vaddr_range(scratch.arena, entity->handle, viz_range_bytes, 0); + visible_memory_change_flags = slice.byte_changed_flags; + visible_memory_bad_flags = slice.byte_bad_flags; + } + } ////////////////////////////// //- rjf: grab annotations for windowed range of memory @@ -2824,110 +2908,115 @@ RD_VIEW_UI_FUNCTION_DEF(memory) typedef struct Annotation Annotation; struct Annotation { - Annotation *next; String8 name_string; String8 kind_string; String8 type_string; Vec4F32 color; Rng1U64 vaddr_range; }; + typedef struct AnnotationNode AnnotationNode; + struct AnnotationNode + { + AnnotationNode *next; + Annotation *v; + }; typedef struct AnnotationList AnnotationList; struct AnnotationList { - Annotation *first; - Annotation *last; + AnnotationNode *first; + AnnotationNode *last; }; AnnotationList *visible_memory_annotations = push_array(scratch.arena, AnnotationList, visible_memory_size); { CTRL_Scope *ctrl_scope = ctrl_scope_open(); - CTRL_Entity *thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread); - CTRL_Entity *process = ctrl_entity_ancestor_from_kind(thread, CTRL_EntityKind_Process); - CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, &d_state->ctrl_entity_store->ctx, thread, 1, 0); + CTRL_Entity *selected_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->thread); + CTRL_Entity *selected_process = ctrl_entity_ancestor_from_kind(selected_thread, CTRL_EntityKind_Process); + CTRL_CallStack selected_call_stack = ctrl_call_stack_from_thread(ctrl_scope, &d_state->ctrl_entity_store->ctx, selected_thread, 1, 0); + CTRL_Entity *eval_process = &ctrl_entity_nil; + if(eval.space.kind == RD_EvalSpaceKind_CtrlEntity) + { + eval_process = rd_ctrl_entity_from_eval_space(eval.space); + } //- rjf: fill unwind frame annotations - if(call_stack.concrete_frames_count != 0) UI_Tag(str8_lit("weak")) + if(selected_call_stack.concrete_frames_count != 0) UI_Tag(str8_lit("weak")) { - U64 last_stack_top = regs_rsp_from_arch_block(thread->arch, call_stack.concrete_frames[0]->regs); - for(U64 idx = 1; idx < call_stack.concrete_frames_count; idx += 1) + U64 last_stack_top = regs_rsp_from_arch_block(selected_thread->arch, selected_call_stack.concrete_frames[0]->regs); + for(U64 idx = 1; idx < selected_call_stack.concrete_frames_count; idx += 1) { - CTRL_CallStackFrame *f = call_stack.concrete_frames[idx]; - U64 f_stack_top = regs_rsp_from_arch_block(thread->arch, f->regs); + CTRL_CallStackFrame *f = selected_call_stack.concrete_frames[idx]; + U64 f_stack_top = regs_rsp_from_arch_block(selected_thread->arch, f->regs); Rng1U64 frame_vaddr_range = r1u64(last_stack_top, f_stack_top); Rng1U64 frame_vaddr_range_in_viz = intersect_1u64(frame_vaddr_range, viz_range_bytes); last_stack_top = f_stack_top; if(dim_1u64(frame_vaddr_range_in_viz) != 0) { - U64 f_rip = regs_rip_from_arch_block(thread->arch, f->regs); - CTRL_Entity *module = ctrl_module_from_process_vaddr(process, f_rip); + DI_Scope *scope = di_scope_open(); + U64 f_rip_vaddr = regs_rip_from_arch_block(selected_thread->arch, f->regs); + CTRL_Entity *module = ctrl_module_from_process_vaddr(selected_process, f_rip_vaddr); + U64 f_rip_voff = ctrl_voff_from_vaddr(module, f_rip_vaddr); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); - U64 rip_voff = ctrl_voff_from_vaddr(module, f_rip); - String8 symbol_name = {0}; + RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); + RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, f_rip_voff); + String8 procedure_name = {0}; + procedure_name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &procedure_name.size); + di_scope_close(scope); + if(procedure_name.size != 0) { - U64 vaddr = eval.value.u64; - CTRL_Entity *process = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->process); - CTRL_Entity *module = ctrl_module_from_process_vaddr(process, vaddr); - DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); - U64 voff = ctrl_voff_from_vaddr(module, vaddr); + Annotation *annotation = push_array(scratch.arena, Annotation, 1); + annotation->name_string = push_str8_copy(scratch.arena, procedure_name); + annotation->kind_string = str8_lit("Call Stack Frame"); + annotation->color = v4f32(0, 0, 0, 0); + annotation->vaddr_range = frame_vaddr_range; + for(U64 vaddr = frame_vaddr_range_in_viz.min; vaddr < frame_vaddr_range_in_viz.max; vaddr += 1) { - DI_Scope *scope = di_scope_open(); - RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); - if(symbol_name.size == 0) - { - RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, voff); - symbol_name.str = rdi_name_from_procedure(rdi, procedure, &symbol_name.size); - } - if(symbol_name.size == 0) - { - RDI_GlobalVariable *gvar = rdi_global_variable_from_voff(rdi, voff); - symbol_name.str = rdi_string_from_idx(rdi, gvar->name_string_idx, &symbol_name.size); - } - di_scope_close(scope); + U64 visible_byte_idx = vaddr - viz_range_bytes.min; + AnnotationNode *n = push_array(scratch.arena, AnnotationNode, 1); + n->v = annotation; + SLLQueuePush(visible_memory_annotations[visible_byte_idx].first, visible_memory_annotations[visible_byte_idx].last, n); } } - Annotation *annotation = push_array(scratch.arena, Annotation, 1); - annotation->name_string = symbol_name.size != 0 ? symbol_name : str8_lit("[external code]"); - annotation->kind_string = str8_lit("Call Stack Frame"); - annotation->color = symbol_name.size != 0 ? ui_color_from_name(str8_lit("code_symbol")) : ui_color_from_name(str8_lit("text")); - annotation->vaddr_range = frame_vaddr_range; - for(U64 vaddr = frame_vaddr_range_in_viz.min; vaddr < frame_vaddr_range_in_viz.max; vaddr += 1) - { - U64 visible_byte_idx = vaddr - viz_range_bytes.min; - SLLQueuePush(visible_memory_annotations[visible_byte_idx].first, visible_memory_annotations[visible_byte_idx].last, annotation); - } } } } //- rjf: fill selected thread stack range annotation - if(call_stack.concrete_frames_count > 0) + if(selected_call_stack.concrete_frames_count > 0) { - U64 stack_base_vaddr = thread->stack_base; - U64 stack_top_vaddr = regs_rsp_from_arch_block(thread->arch, call_stack.concrete_frames[0]->regs); + U64 stack_base_vaddr = selected_thread->stack_base; + U64 stack_top_vaddr = regs_rsp_from_arch_block(selected_thread->arch, selected_call_stack.concrete_frames[0]->regs); Rng1U64 stack_vaddr_range = r1u64(stack_base_vaddr, stack_top_vaddr); Rng1U64 stack_vaddr_range_in_viz = intersect_1u64(stack_vaddr_range, viz_range_bytes); if(dim_1u64(stack_vaddr_range_in_viz) != 0) { Annotation *annotation = push_array(scratch.arena, Annotation, 1); - annotation->name_string = thread->string.size ? thread->string : push_str8f(scratch.arena, "TID: %I64u", thread->id); + annotation->name_string = selected_thread->string.size ? selected_thread->string : push_str8f(scratch.arena, "TID: %I64u", selected_thread->id); annotation->kind_string = str8_lit("Stack"); - annotation->color = rd_color_from_ctrl_entity(thread); + annotation->color = rd_color_from_ctrl_entity(selected_thread); annotation->vaddr_range = stack_vaddr_range; for(U64 vaddr = stack_vaddr_range_in_viz.min; vaddr < stack_vaddr_range_in_viz.max; vaddr += 1) { U64 visible_byte_idx = vaddr - viz_range_bytes.min; - SLLQueuePush(visible_memory_annotations[visible_byte_idx].first, visible_memory_annotations[visible_byte_idx].last, annotation); + AnnotationNode *n = push_array(scratch.arena, AnnotationNode, 1); + n->v = annotation; + SLLQueuePush(visible_memory_annotations[visible_byte_idx].first, visible_memory_annotations[visible_byte_idx].last, n); } } } //- rjf: fill local variable annotations + if(e_space_match(rd_eval_space_from_ctrl_entity(selected_process, RD_EvalSpaceKind_CtrlEntity), eval.space)) { DI_Scope *scope = di_scope_open(); + Vec4F32 local_color = ui_color_from_name(str8_lit("code_local")); Vec4F32 color_gen_table[] = { - ui_color_from_name(str8_lit("code_local")), + mix_4f32(local_color, v4f32(0, 0, 0, 1), 0.2f), + mix_4f32(local_color, v4f32(0, 0, 0, 1), 0.4f), + mix_4f32(local_color, v4f32(0, 0, 0, 1), 0.6f), + mix_4f32(local_color, v4f32(0, 0, 0, 1), 0.8f), }; - U64 thread_rip_vaddr = d_query_cached_rip_from_thread_unwind(thread, rd_regs()->unwind_count); + U64 thread_rip_vaddr = d_query_cached_rip_from_thread_unwind(selected_thread, rd_regs()->unwind_count); for(E_String2NumMapNode *n = e_ir_ctx->locals_map->first; n != 0; n = n->order_next) { String8 local_name = n->string; @@ -2945,18 +3034,173 @@ RD_VIEW_UI_FUNCTION_DEF(memory) annotation->name_string = push_str8_copy(scratch.arena, local_name); annotation->kind_string = str8_lit("Local"); annotation->type_string = e_type_string_from_key(scratch.arena, local_eval.irtree.type_key); - annotation->color = color_gen_table[(vaddr_rng.min/8)%ArrayCount(color_gen_table)]; + annotation->color = color_gen_table[(vaddr_rng.min/7)%ArrayCount(color_gen_table)]; annotation->vaddr_range = vaddr_rng; } for(U64 vaddr = vaddr_rng_in_visible.min; vaddr < vaddr_rng_in_visible.max; vaddr += 1) { - SLLQueuePushFront(visible_memory_annotations[vaddr-viz_range_bytes.min].first, visible_memory_annotations[vaddr-viz_range_bytes.min].last, annotation); + AnnotationNode *n = push_array(scratch.arena, AnnotationNode, 1); + n->v = annotation; + SLLQueuePushFront(visible_memory_annotations[vaddr-viz_range_bytes.min].first, visible_memory_annotations[vaddr-viz_range_bytes.min].last, n); } } } } di_scope_close(scope); } + + //- rjf: fill procedures annotations + if(eval_process != &ctrl_entity_nil) + { + Vec4F32 symbol_color = ui_color_from_name(str8_lit("code_symbol")); + Vec4F32 color_gen_table[] = + { + mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.2f), + mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.4f), + mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.6f), + mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.8f), + }; + for(U64 vaddr = viz_range_bytes.min, next_vaddr = 0; + viz_range_bytes.min <= vaddr && vaddr <= viz_range_bytes.max; + vaddr = next_vaddr) + { + next_vaddr = vaddr+1; + DI_Scope *scope = di_scope_open(); + CTRL_Entity *module = ctrl_module_from_process_vaddr(eval_process, vaddr); + if(module != &ctrl_entity_nil) + { + U64 voff = ctrl_voff_from_vaddr(module, vaddr); + DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); + RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); + RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, voff); + RDI_Scope *root_scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx); + if(procedure->root_scope_idx != 0) + { + Rng1U64 voff_range = r1u64(rdi_first_voff_from_scope(rdi, root_scope), + rdi_opl_voff_from_scope(rdi, root_scope)); + Rng1U64 vaddr_range = ctrl_vaddr_range_from_voff_range(module, voff_range); + next_vaddr = vaddr_range.max; + next_vaddr = Max(next_vaddr, vaddr+1); + Rng1U64 vaddr_range_in_visible = intersect_1u64(vaddr_range, viz_range_bytes); + if(vaddr_range_in_visible.min < vaddr_range_in_visible.max) + { + String8 procedure_name = {0}; + procedure_name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &procedure_name.size); + Annotation *annotation = push_array(scratch.arena, Annotation, 1); + { + annotation->name_string = push_str8_copy(scratch.arena, procedure_name); + annotation->kind_string = str8_lit("Procedure"); + annotation->color = color_gen_table[(vaddr_range.min/7)%ArrayCount(color_gen_table)]; + annotation->vaddr_range = vaddr_range; + } + for(U64 vaddr = vaddr_range_in_visible.min; vaddr < vaddr_range_in_visible.max; vaddr += 1) + { + AnnotationNode *n = push_array(scratch.arena, AnnotationNode, 1); + n->v = annotation; + SLLQueuePushFront(visible_memory_annotations[vaddr-viz_range_bytes.min].first, visible_memory_annotations[vaddr-viz_range_bytes.min].last, n); + } + } + } + } + di_scope_close(scope); + } + } + + //- rjf: fill globals annotations + if(eval_process != &ctrl_entity_nil) + { + Vec4F32 symbol_color = ui_color_from_name(str8_lit("code_symbol")); + Vec4F32 color_gen_table[] = + { + mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.2f), + mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.4f), + mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.6f), + mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.8f), + }; + for(U64 vaddr = viz_range_bytes.min, next_vaddr = 0; + viz_range_bytes.min <= vaddr && vaddr <= viz_range_bytes.max; + vaddr = next_vaddr) + { + next_vaddr = vaddr+1; + DI_Scope *scope = di_scope_open(); + CTRL_Entity *module = ctrl_module_from_process_vaddr(eval_process, vaddr); + if(module != &ctrl_entity_nil) + { + U64 voff = ctrl_voff_from_vaddr(module, vaddr); + DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); + RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); + RDI_GlobalVariable *gvar = rdi_global_variable_from_voff(rdi, voff); + if(gvar->voff != 0) + { + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, gvar->type_idx); + Rng1U64 voff_range = r1u64(gvar->voff, gvar->voff + type_node->byte_size); + Rng1U64 vaddr_range = ctrl_vaddr_range_from_voff_range(module, voff_range); + next_vaddr = vaddr_range.max; + next_vaddr = Max(next_vaddr, vaddr+1); + Rng1U64 vaddr_range_in_visible = intersect_1u64(vaddr_range, viz_range_bytes); + if(vaddr_range_in_visible.min < vaddr_range_in_visible.max) + { + String8 gvar_name = {0}; + gvar_name.str = rdi_string_from_idx(rdi, gvar->name_string_idx, &gvar_name.size); + Annotation *annotation = push_array(scratch.arena, Annotation, 1); + { + annotation->name_string = push_str8_copy(scratch.arena, gvar_name); + annotation->kind_string = str8_lit("Global"); + annotation->color = color_gen_table[(vaddr_range.min/7)%ArrayCount(color_gen_table)]; + annotation->vaddr_range = vaddr_range; + } + for(U64 vaddr = vaddr_range_in_visible.min; vaddr < vaddr_range_in_visible.max; vaddr += 1) + { + AnnotationNode *n = push_array(scratch.arena, AnnotationNode, 1); + n->v = annotation; + SLLQueuePushFront(visible_memory_annotations[vaddr-viz_range_bytes.min].first, visible_memory_annotations[vaddr-viz_range_bytes.min].last, n); + } + } + } + } + di_scope_close(scope); + } + } + + //- rjf: fill debuggee-specified annotations + if(eval_process != &ctrl_entity_nil) UI_TagF(".") UI_TagF("pop") + { + Vec4F32 symbol_color = ui_color_from_name(str8_lit("background")); + Vec4F32 color_gen_table[] = + { + mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.00f), + mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.05f), + mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.10f), + mix_4f32(symbol_color, v4f32(0, 0, 0, 1), 0.15f), + }; + for(CTRL_Entity *child = eval_process->first; child != &ctrl_entity_nil; child = child->next) + { + if(child->kind != CTRL_EntityKind_AddressRangeAnnotation) + { + continue; + } + String8 name = child->string; + Rng1U64 vaddr_range = child->vaddr_range; + Rng1U64 vaddr_range_in_visible = intersect_1u64(vaddr_range, viz_range_bytes); + if(vaddr_range_in_visible.max > vaddr_range_in_visible.min) + { + Annotation *annotation = push_array(scratch.arena, Annotation, 1); + { + annotation->name_string = push_str8_copy(scratch.arena, name); + annotation->kind_string = str8_lit("Annotation"); + annotation->color = color_gen_table[(vaddr_range.min/7)%ArrayCount(color_gen_table)]; + annotation->vaddr_range = vaddr_range; + } + for(U64 vaddr = vaddr_range_in_visible.min; vaddr < vaddr_range_in_visible.max; vaddr += 1) + { + AnnotationNode *n = push_array(scratch.arena, AnnotationNode, 1); + n->v = annotation; + SLLQueuePushFront(visible_memory_annotations[vaddr-viz_range_bytes.min].first, visible_memory_annotations[vaddr-viz_range_bytes.min].last, n); + } + } + } + } + ctrl_scope_close(ctrl_scope); } @@ -3172,6 +3416,18 @@ RD_VIEW_UI_FUNCTION_DEF(memory) } } } + + // rjf: rich hover + if(mouse_hover_byte_num != 0) + { + Rng1U64 hovered_range = r1u64(mouse_hover_byte_num-1, mouse_hover_byte_num-1 + 1); + if(ui_dragging(sig) && !ui_pressed(sig) && dim_1u64(selection) != 0) + { + hovered_range = selection; + } + RD_RegsScope(.vaddr_range = hovered_range, .eval_space = eval.space, .src_ui_key = memory_rich_hover_key) + rd_set_hover_regs(RD_RegSlot_VaddrRange); + } } ////////////////////////////// @@ -3189,14 +3445,6 @@ RD_VIEW_UI_FUNCTION_DEF(memory) break; } UI_BoxFlags row_flags = 0; - if(row_range_bytes.min <= selection.min && selection.min < row_range_bytes.max) - { - row_flags |= UI_BoxFlag_DrawSideTop; - } - if(row_range_bytes.min <= selection.max && selection.max < row_range_bytes.max) - { - row_flags |= UI_BoxFlag_DrawSideBottom; - } UI_Box *row = ui_build_box_from_stringf(row_flags, "row_%I64x", row_range_bytes.min); UI_Parent(row) { @@ -3206,7 +3454,7 @@ RD_VIEW_UI_FUNCTION_DEF(memory) { ui_set_next_tag(str8_lit("weak")); } - ui_labelf("0x%016I64X", row_range_bytes.min); + ui_labelf("0x%016I64x", row_range_bytes.min); } UI_PrefWidth(ui_px(cell_width_px, 1.f)) UI_TextAlignment(UI_TextAlign_Center) @@ -3229,84 +3477,128 @@ RD_VIEW_UI_FUNCTION_DEF(memory) else { // rjf: unpack byte info + B32 byte_is_selected = (selection.min <= global_byte_idx && global_byte_idx <= selection.max); U8 byte_value = visible_memory[visible_byte_idx]; - Annotation *annotation = visible_memory_annotations[visible_byte_idx].first; + B32 byte_is_bad = !!(visible_memory_bad_flags[visible_byte_idx/64] & (1ull<<(visible_byte_idx%64))); + B32 byte_is_changed = !!(visible_memory_change_flags[visible_byte_idx/64] & (1ull<<(visible_byte_idx%64))); + AnnotationNode *annotation_node = visible_memory_annotations[visible_byte_idx].first; // rjf: unpack visual cell info UI_BoxFlags cell_flags = 0; Vec4F32 cell_bg_rgba = {0}; + Vec4F32 cell_bd_rgba = ui_color_from_name(str8_lit("text")); if(global_byte_num == mouse_hover_byte_num) { - cell_flags |= UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawSideTop|UI_BoxFlag_DrawSideBottom|UI_BoxFlag_DrawSideLeft|UI_BoxFlag_DrawSideRight; + cell_flags |= UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawDropShadow; } - if(annotation != 0) + if(annotation_node != 0) { cell_flags |= UI_BoxFlag_DrawBackground; - cell_bg_rgba = annotation->color; - if(contains_1u64(annotation->vaddr_range, mouse_hover_byte_num-1)) - { - cell_bg_rgba.w *= 0.15f; - } - else - { - cell_bg_rgba.w *= 0.08f; - } + Vec4F32 cell_bg_color_rgba = annotation_node->v->color; + Vec4F32 cell_bg_color_hsva = hsva_from_rgba(cell_bg_color_rgba); + cell_bg_rgba = mix_4f32(cell_bg_color_rgba, main_bg_color_rgba, clamp_1f32(r1f32(0, 1), 1.f - abs_f32(cell_bg_color_hsva.z - main_tx_color_hsva.z)*0.5f)); } - if(selection.min <= global_byte_idx && global_byte_idx <= selection.max) - { - cell_flags |= UI_BoxFlag_DrawBackground; - cell_bg_rgba = selection_color; - } - if(selection.min%num_columns == col_idx) + if(selection.min == global_byte_idx) { cell_flags |= UI_BoxFlag_DrawSideLeft; } - if(selection.max%num_columns == col_idx) + if(selection.max == global_byte_idx) { cell_flags |= UI_BoxFlag_DrawSideRight; } + if(row_idx == (selection.min - view_range.min)/num_columns && selection.min <= global_byte_idx && global_byte_idx <= selection.max) + { + cell_flags |= UI_BoxFlag_DrawSideTop; + } + if(row_idx == (selection.max - view_range.min)/num_columns && selection.min <= global_byte_idx && global_byte_idx <= selection.max) + { + cell_flags |= UI_BoxFlag_DrawSideBottom; + } + if(contains_1u64(rich_hover_range, global_byte_idx)) UI_TagF("pop") + { + cell_flags |= UI_BoxFlag_DrawBackground; + cell_bg_rgba = ui_color_from_name(str8_lit("background")); + } + if(byte_is_changed) UI_TagF("fresh") + { + cell_flags |= UI_BoxFlag_DrawBackground; + cell_bg_rgba = ui_color_from_name(str8_lit("background")); + } + if(byte_is_bad) UI_TagF("bad_pop") + { + cell_flags |= UI_BoxFlag_DrawBackground; + cell_bg_rgba = ui_color_from_name(str8_lit("background")); + } // rjf: build - ui_set_next_background_color(cell_bg_rgba); + if(cell_bd_rgba.w != 0) { ui_set_next_border_color(cell_bd_rgba); } + if(cell_bg_rgba.w != 0) { ui_set_next_background_color(cell_bg_rgba); } UI_Box *cell_box = ui_build_box_from_key(UI_BoxFlag_DrawText|cell_flags, ui_key_zero()); - ui_box_equip_display_fstrs(cell_box, &byte_fstrs[byte_value]); + if(byte_is_selected || byte_is_changed) { - F32 off = 0; - for(Annotation *a = annotation; a != 0; a = a->next) + ui_box_equip_display_fstrs(cell_box, &byte_fstrs_selected[byte_value]); + } + else + { + ui_box_equip_display_fstrs(cell_box, &byte_fstrs[byte_value]); + } + { + for(AnnotationNode *a_n = annotation_node; a_n != 0; a_n = a_n->next) { + Annotation *a = a_n->v; if(global_byte_idx == a->vaddr_range.min) UI_Parent(row_overlay_box) { - ui_set_next_background_color(annotation->color); - ui_set_next_fixed_x(big_glyph_advance*20.f + col_idx*cell_width_px + -cell_width_px/8.f + off); - ui_set_next_fixed_y((row_idx-viz_range_rows.min)*row_height_px + -cell_width_px/8.f); - ui_set_next_fixed_width(cell_width_px/4.f); - ui_set_next_fixed_height(cell_width_px/4.f); + F32 size = cell_width_px/4.f + cell_width_px/8.f*ui_anim(ui_key_from_stringf(ui_active_seed_key(), "###annotation_hovered_%I64x_%I64x", a->vaddr_range.min, a->vaddr_range.max), + (F32)!!(a->vaddr_range.min+1 <= mouse_hover_byte_num && mouse_hover_byte_num <= a->vaddr_range.max)); + ui_set_next_border_color(a->color); + ui_set_next_fixed_x(big_glyph_advance*20.f + col_idx*cell_width_px + -size*0.5f); + ui_set_next_fixed_y((row_idx-viz_range_rows.min)*row_height_px + -size*0.5f); + ui_set_next_fixed_width(size); + ui_set_next_fixed_height(size); ui_set_next_corner_radius_00(cell_width_px/8.f); ui_set_next_corner_radius_01(cell_width_px/8.f); ui_set_next_corner_radius_10(cell_width_px/8.f); ui_set_next_corner_radius_11(cell_width_px/8.f); - ui_build_box_from_key(UI_BoxFlag_Floating|UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawDropShadow, ui_key_zero()); - off += cell_width_px/8.f + cell_width_px/16.f; + ui_build_box_from_key(UI_BoxFlag_Floating|UI_BoxFlag_DrawSideLeft|UI_BoxFlag_DrawSideTop|UI_BoxFlag_DrawDropShadow, ui_key_zero()); + } + if(global_byte_idx+1 == a->vaddr_range.max) UI_Parent(row_overlay_box) + { + F32 size = cell_width_px/4.f + cell_width_px/8.f*ui_anim(ui_key_from_stringf(ui_active_seed_key(), "###annotation_hovered_%I64x_%I64x", a->vaddr_range.min, a->vaddr_range.max), + (F32)!!(a->vaddr_range.min+1 <= mouse_hover_byte_num && mouse_hover_byte_num <= a->vaddr_range.max)); + ui_set_next_border_color(a->color); + ui_set_next_fixed_x(big_glyph_advance*20.f + (col_idx+1)*cell_width_px + -size*0.5f); + ui_set_next_fixed_y((row_idx-viz_range_rows.min)*row_height_px + row_height_px + -size*0.5f); + ui_set_next_fixed_width(size); + ui_set_next_fixed_height(size); + ui_set_next_corner_radius_00(cell_width_px/8.f); + ui_set_next_corner_radius_01(cell_width_px/8.f); + ui_set_next_corner_radius_10(cell_width_px/8.f); + ui_set_next_corner_radius_11(cell_width_px/8.f); + ui_build_box_from_key(UI_BoxFlag_Floating|UI_BoxFlag_DrawSideRight|UI_BoxFlag_DrawSideBottom|UI_BoxFlag_DrawDropShadow, ui_key_zero()); } } } - if(annotation != 0 && mouse_hover_byte_num == global_byte_num) UI_Tooltip UI_FontSize(ui_top_font_size()) UI_PrefHeight(ui_px(ui_top_font_size()*1.75f, 1.f)) + if(annotation_node != 0 && mouse_hover_byte_num == global_byte_num) { - for(Annotation *a = annotation; a != 0; a = a->next) + UI_Tooltip UI_FontSize(ui_top_font_size()) UI_PrefHeight(ui_px(ui_top_font_size()*1.75f, 1.f)) { - UI_PrefWidth(ui_children_sum(1)) UI_Row UI_PrefWidth(ui_text_dim(10, 1)) + for(AnnotationNode *a_n = annotation_node; a_n != 0; a_n = a_n->next) { - RD_Font(RD_FontSlot_Code) ui_label(a->name_string); - RD_Font(RD_FontSlot_Main) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) ui_label(a->kind_string); - } - if(a->type_string.size != 0) - { - rd_code_label(1.f, 1, ui_color_from_name(str8_lit("code_type")), a->type_string); - } - UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) ui_label(str8_from_memory_size(scratch.arena, dim_1u64(a->vaddr_range))); - if(a->next != 0) - { - ui_spacer(ui_em(1.5f, 1.f)); + Annotation *a = a_n->v; + UI_PrefWidth(ui_children_sum(1)) UI_Row UI_PrefWidth(ui_text_dim(10, 1)) + { + RD_Font(RD_FontSlot_Code) rd_code_label(1.f, 0, ui_color_from_name(str8_lit("code_default")), a->name_string); + UI_TagF("weak") RD_Font(RD_FontSlot_Main) ui_label(a->kind_string); + } + if(a->type_string.size != 0) + { + rd_code_label(1.f, 1, ui_color_from_name(str8_lit("code_type")), a->type_string); + } + UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) ui_label(str8_from_memory_size(scratch.arena, dim_1u64(a->vaddr_range))); + if(a_n->next != 0) + { + ui_spacer(ui_em(1.5f, 1.f)); + } } } } @@ -3342,7 +3634,6 @@ RD_VIEW_UI_FUNCTION_DEF(memory) { Vec2F32 text_pos = ui_box_text_position(ascii_box); Vec4F32 color = selection_color; - color.w *= 0.2f; dr_rect(r2f32p(text_pos.x + fnt_dim_from_tag_size_string(font, font_size, 0, 0, str8_prefix(ascii_text, selection_in_row.min+0-row_range_bytes.min)).x - font_size/8.f, ascii_box->rect.y0, text_pos.x + fnt_dim_from_tag_size_string(font, font_size, 0, 0, str8_prefix(ascii_text, selection_in_row.max+1-row_range_bytes.min)).x + font_size/4.f, @@ -3401,6 +3692,8 @@ RD_VIEW_UI_FUNCTION_DEF(memory) ////////////////////////////// //- rjf: save parameters // + mv->last_cursor_range = r1u64(cursor_base_vaddr, cursor_base_vaddr + cursor_size); + mv->last_cursor_range_inited = 1; if(cursor_base_vaddr != initial_cursor_base_vaddr) { rd_store_view_param_u64(str8_lit("cursor"), cursor_base_vaddr); diff --git a/src/raddbg/raddbg_views.h b/src/raddbg/raddbg_views.h index 5f8d0869..3b6d5c2a 100644 --- a/src/raddbg/raddbg_views.h +++ b/src/raddbg/raddbg_views.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDBG_VIEWS_H diff --git a/src/raddbg/raddbg_widgets.c b/src/raddbg/raddbg_widgets.c index 40eaa452..571a7af0 100644 --- a/src/raddbg/raddbg_widgets.c +++ b/src/raddbg/raddbg_widgets.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -548,7 +548,7 @@ rd_title_fstrs_from_ctrl_entity(Arena *arena, CTRL_Entity *entity, B32 include_e Arch arch = entity->arch; B32 call_stack_high_priority = ctrl_handle_match(entity->handle, rd_base_regs()->thread); CTRL_CallStack call_stack = ctrl_call_stack_from_thread(ctrl_scope, &d_state->ctrl_entity_store->ctx, entity, call_stack_high_priority, call_stack_high_priority ? rd_state->frame_eval_memread_endt_us : 0); - for(U64 idx = 0, limit = 6; idx < call_stack.frames_count && idx < limit; idx += 1) + for(U64 idx = 0, limit = 10; idx < call_stack.frames_count && idx < limit; idx += 1) { CTRL_CallStackFrame *f = &call_stack.frames[call_stack.frames_count - 1 - idx]; U64 rip_vaddr = regs_rip_from_arch_block(arch, f->regs); @@ -1279,7 +1279,7 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe }; U64 line_idx = 0; for(S64 line_num = params->line_num_range.min; - line_num < params->line_num_range.max; + line_num <= params->line_num_range.max; line_num += 1, line_idx += 1) { String8 line_string = params->line_text[line_idx]; @@ -1971,7 +1971,7 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe { U64 line_idx = 0; for(S64 line_num = params->line_num_range.min; - line_num < params->line_num_range.max; + line_num <= params->line_num_range.max; line_num += 1, line_idx += 1) { DR_FStrList line_fstrs = lines_fstrs[line_idx]; @@ -2119,7 +2119,7 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe params->line_pins[line_idx], immediate_pins, }; - for EachElement(list_idx, pin_lists) + E_ParentKey(e_key_zero()) for EachElement(list_idx, pin_lists) { RD_CfgList pins = pin_lists[list_idx]; if(pins.count != 0) UI_Parent(line_extras_boxes[line_idx]) diff --git a/src/raddbg/raddbg_widgets.h b/src/raddbg/raddbg_widgets.h index 36014bad..5556ae64 100644 --- a/src/raddbg/raddbg_widgets.h +++ b/src/raddbg/raddbg_widgets.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDBG_WIDGETS_H diff --git a/src/raddump/raddump.c b/src/raddump/raddump.c index b3ecb678..2e626226 100644 --- a/src/raddump/raddump.c +++ b/src/raddump/raddump.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) // TODO: @@ -46,23 +46,23 @@ internal RDI_Parsed * rd_rdi_from_pe(Arena *arena, String8 pe_path) { Temp scratch = scratch_begin(&arena, 1); - + // make command line for converter String8List cmdl_string = {0}; str8_list_pushf(scratch.arena, &cmdl_string, "-pe:%S", pe_path); CmdLine cmdl = cmd_line_from_string_list(scratch.arena, cmdl_string); - + // run converter String8 raw_rdi = rc_rdi_from_cmd_line(scratch.arena, &cmdl); - + // load RDI RDI_Parsed *rdi = 0; if (raw_rdi.size) { rdi = push_array(arena, RDI_Parsed, 1); - + // TODO: check guid RDI_ParseStatus parse_status = rdi_parse(raw_rdi.str, raw_rdi.size, rdi); - + String8 parse_status_string = str8_zero(); if (parse_status == RDI_ParseStatus_Good) { } else if (parse_status == RDI_ParseStatus_HeaderDoesNotMatch) { @@ -76,13 +76,13 @@ rd_rdi_from_pe(Arena *arena, String8 pe_path) } else { parse_status_string = push_str8f(scratch.arena, "unknown parse status code: %u", parse_status); } - + if (parse_status_string.size) { rdi = 0; rd_errorf("RDI parse status(%u): %S", parse_status, parse_status_string); } } - + scratch_end(scratch); return rdi; } @@ -139,11 +139,11 @@ rd_line_from_voff(Arena *arena, RDI_Parsed *rdi, U64 voff, PathStyle path_style) RDI_Line line = rdi_line_from_voff(rdi, voff); RDI_SourceFile *src_file = rdi_source_file_from_line(rdi, &line); String8 file_path = rd_path_from_file_path_node_idx(arena, rdi, src_file->file_path_node_idx, path_style); - + RD_Line result = {0}; result.file_path = file_path; result.line_num = line.line_num; - + return result; } @@ -249,24 +249,11 @@ rd_string_from_array_hex_u64(Arena *arena, U64 *v, U64 count) return result; } -internal String8 -rd_string_from_range_array_u64_hex(Arena *arena, U64 *v, U64 count) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List list = {0}; - for (U64 i = 0; i+2 <= count; i += 2) { - str8_list_pushf(scratch.arena, &list, "[%#llx, %#llx)", v[i+0], v[i+1]); - } - String8 result = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(", ")}); - scratch_end(scratch); - return result; -} - internal void rd_format_preamble(Arena *arena, String8List *out, String8 indent, String8 input_path, String8 raw_data) { Temp scratch = scratch_begin(&arena, 1); - + String8 input_type_string = str8_lit("???"); if (coff_is_regular_archive(raw_data)) { input_type_string = str8_lit("Archive"); @@ -285,13 +272,13 @@ rd_format_preamble(Arena *arena, String8List *out, String8 indent, String8 input str8_deserial_read(raw_data, 0, &sig[0], sizeof(sig), 1); input_type_string = push_str8f(scratch.arena, "ELF (Class: %S)", elf_string_from_class(scratch.arena, sig[ELF_Identifier_Class])); } - + DateTime universal_dt = os_now_universal_time(); DateTime local_dt = os_local_time_from_universal(&universal_dt); String8 time = push_date_time_string(scratch.arena, &local_dt); String8 full_path = os_full_path_from_path(scratch.arena, input_path); rd_printf("# %S, [%S] %S", time, input_type_string, full_path); - + scratch_end(scratch); } @@ -338,44 +325,44 @@ internal RD_MarkerArray * rd_section_markers_from_rdi(Arena *arena, RDI_Parsed *rdi) { Temp scratch = scratch_begin(&arena, 1); - + U64 sect_count = 0; RDI_BinarySection *sect_lo = rdi_table_from_name(rdi, BinarySections, §_count); - + Rng1U64 *sect_vranges = push_array(scratch.arena, Rng1U64, sect_count); for (U64 i = 0; i < sect_count; ++i) { sect_vranges[i].min = sect_lo[i].voff_first; sect_vranges[i].max = i; } radsort(sect_vranges, sect_count, rd_range_min_is_before); - + U64 proc_count = 0; RDI_Procedure *proc_lo = rdi_table_from_name(rdi, Procedures, &proc_count); - + RD_MarkerList *markers = push_array(scratch.arena, RD_MarkerList, sect_count); for (U64 i = 0; i < proc_count; ++i) { RDI_Procedure *proc = proc_lo + i; U64 proc_voff_lo = rdi_first_voff_from_procedure(rdi, proc); U64 proc_voff_hi = rdi_opl_voff_from_procedure(rdi, proc); - + U64 sect_range_idx = rd_range_bsearch(sect_vranges, sect_count, proc_voff_lo); if (sect_range_idx < sect_count) { Rng1U64 sect_range = sect_vranges[sect_range_idx]; U64 sect_idx = sect_range.max; - + String8 name = str8_zero(); name.str = rdi_name_from_procedure(rdi, proc, &name.size); - + RD_MarkerNode *n = push_array(scratch.arena, RD_MarkerNode, 1); n->v.off = proc_voff_lo - sect_range.min; n->v.string = name; - + RD_MarkerList *list = &markers[sect_idx]; SLLQueuePush(list->first, list->last, n); ++list->count; } } - + // lists -> arrays RD_MarkerArray *result = push_array(arena, RD_MarkerArray, sect_count); for (U64 i = 0; i < sect_count; ++i) { @@ -385,12 +372,12 @@ rd_section_markers_from_rdi(Arena *arena, RDI_Parsed *rdi) result[i].v[result[i].count++] = n->v; } } - + // sort arrays for (U64 i = 0; i < sect_count; ++i) { radsort(result[i].v, result[i].count, rd_marker_is_before); } - + scratch_end(scratch); return result; } @@ -399,32 +386,32 @@ internal RD_MarkerArray * rd_section_markers_from_coff_symbol_table(Arena *arena, String8 string_table, U64 section_count, COFF_Symbol32Array symbols) { Temp scratch = scratch_begin(&arena, 1); - + // extract markers from symbol table RD_MarkerList *markers = push_array(scratch.arena, RD_MarkerList, section_count+1); for (U64 symbol_idx = 0; symbol_idx < symbols.count; ++symbol_idx) { COFF_Symbol32 *symbol = &symbols.v[symbol_idx]; - + COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol->section_number, symbol->value, symbol->storage_class); B32 is_marker = interp == COFF_SymbolValueInterp_Regular && - symbol->aux_symbol_count == 0 && - (symbol->storage_class == COFF_SymStorageClass_External || symbol->storage_class == COFF_SymStorageClass_Static); - + symbol->aux_symbol_count == 0 && + (symbol->storage_class == COFF_SymStorageClass_External || symbol->storage_class == COFF_SymStorageClass_Static); + if (is_marker) { String8 name = coff_read_symbol_name(string_table, &symbol->name); - + RD_MarkerNode *n = push_array(scratch.arena, RD_MarkerNode, 1); n->v.off = symbol->value; n->v.string = name; - + RD_MarkerList *list = &markers[symbol->section_number]; SLLQueuePush(list->first, list->last, n); ++list->count; } - + symbol_idx += symbol->aux_symbol_count; } - + // lists -> arrays RD_MarkerArray *result = push_array(arena, RD_MarkerArray, section_count); for (U64 i = 0; i < section_count; ++i) { @@ -434,12 +421,12 @@ rd_section_markers_from_coff_symbol_table(Arena *arena, String8 string_table, U6 result[i].v[result[i].count++] = n->v; } } - + // sort arrays for (U64 i = 0; i < section_count; ++i) { radsort(result[i].v, result[i].count, rd_marker_is_before); } - + scratch_end(scratch); return result; } @@ -448,54 +435,54 @@ internal RD_DisasmResult rd_disasm_next_instruction(Arena *arena, Arch arch, U64 addr, String8 raw_code) { RD_DisasmResult result = {0}; - + switch (arch) { case Arch_Null: break; - + case Arch_x64: case Arch_x86: { ZydisMachineMode machine_mode = bit_size_from_arch(arch) == 32 ? ZYDIS_MACHINE_MODE_LEGACY_32 : ZYDIS_MACHINE_MODE_LONG_64; ZydisDisassembledInstruction inst = {0}; ZyanStatus status = ZydisDisassemble(machine_mode, addr, raw_code.str, raw_code.size, &inst, ZYDIS_FORMATTER_STYLE_INTEL); - + String8 text = str8_cstring_capped(inst.text, inst.text+sizeof(inst.text)); result.text = push_str8_copy(arena, text); result.size = inst.info.length; } break; - + default: NotImplemented; } - + return result; } internal void rd_print_disasm(Arena *arena, - String8List *out, - String8 indent, - Arch arch, - U64 image_base, - U64 sect_off, - U64 marker_count, - RD_Marker *markers, - String8 raw_code) + String8List *out, + String8 indent, + Arch arch, + U64 image_base, + U64 sect_off, + U64 marker_count, + RD_Marker *markers, + String8 raw_code) { Temp scratch = scratch_begin(&arena, 1); - + U64 bytes_buffer_max = 256; char *bytes_buffer = push_array(scratch.arena, char, bytes_buffer_max); - + U64 decode_off = 0; U64 marker_cursor = 0; String8 to_decode = raw_code; - + for (; to_decode.size > 0; ) { Temp temp = temp_begin(scratch.arena); - + // decode instruction U64 addr = image_base + sect_off + decode_off; RD_DisasmResult disasm_result = rd_disasm_next_instruction(temp.arena, arch, addr, to_decode); - + // format instruction bytes String8 bytes; { @@ -505,7 +492,7 @@ rd_print_disasm(Arena *arena, } bytes = str8((U8*)bytes_buffer, bytes_size); } - + // print address marker if (marker_cursor < marker_count) { RD_Marker *m = &markers[marker_cursor]; @@ -520,17 +507,17 @@ rd_print_disasm(Arena *arena, marker_cursor += 1; } } - + // print final line rd_printf("%#08x: %-32S %S", addr, bytes, disasm_result.text); - + // advance to_decode = str8_skip(to_decode, disasm_result.size); decode_off += disasm_result.size; - + temp_end(temp); } - + scratch_end(scratch); } @@ -540,42 +527,42 @@ rd_format_hex_array(Arena *arena, U8 *ptr, U64 size) U64 buf_max = 32 + size * 8; char *buf = push_array(arena, char, buf_max); U64 buf_size = 0; - + buf_size += raddbg_snprintf(buf+buf_size, buf_max-buf_size, "{ "); for (U64 i = 0; i < size; ++i) { buf_size += raddbg_snprintf(buf+buf_size, buf_max-buf_size, "%s0x%02x", i>0 ? ", " : "", ptr[i]); } buf_size += raddbg_snprintf(buf+buf_size, buf_max-buf_size, " }"); - + buf[buf_size] = '\0'; - + String8 result = str8((U8*)buf, buf_size); return result; } internal void rd_print_raw_data(Arena *arena, - String8List *out, - String8 indent, - U64 bytes_per_row, - U64 marker_count, - RD_Marker *markers, - String8 raw_data) + String8List *out, + String8 indent, + U64 bytes_per_row, + U64 marker_count, + RD_Marker *markers, + String8 raw_data) { AssertAlways(bytes_per_row > 0); - + char temp_buffer[1024]; - + String8 to_format = raw_data; for (; to_format.size > 0; ) { String8 raw_row = str8_prefix(to_format, bytes_per_row); - + U64 temp_cursor = 0; - + // offset U64 offset = (U64)(raw_row.str-raw_data.str); temp_cursor += raddbg_snprintf(temp_buffer+temp_cursor, sizeof(temp_buffer)-temp_cursor, "%#08llx: ", offset); - + // hex for (U64 i = 0; i < raw_row.size; ++i) { U8 b = raw_row.str[i]; @@ -584,9 +571,9 @@ rd_print_raw_data(Arena *arena, U64 hex_indent_size = (bytes_per_row - raw_row.size) * 3; MemorySet(temp_buffer+temp_cursor, ' ', hex_indent_size); temp_cursor += hex_indent_size; - + temp_cursor += raddbg_snprintf(temp_buffer+temp_cursor, sizeof(temp_buffer) - temp_cursor, " "); - + // ascii for (U64 i = 0; i < raw_row.size; ++i) { U8 b = raw_row.str[i]; @@ -596,1197 +583,14 @@ rd_print_raw_data(Arena *arena, } temp_cursor += raddbg_snprintf(temp_buffer+temp_cursor, sizeof(temp_buffer)-temp_cursor, "%c", c); } - + rd_printf("%.*s", temp_cursor, temp_buffer); - + // advance to_format = str8_skip(to_format, bytes_per_row); } } -internal String8 -str8_from_rdi_string_idx(RDI_Parsed *rdi, U32 idx) -{ - String8 result = str8_zero(); - result.str = rdi_string_from_idx(rdi, idx, &result.size); - return result; -} - -internal String8 -rdi_string_from_data_section_kind(Arena *arena, RDI_SectionKind v) -{ - String8 result; - switch (v) { - default: result = push_str8f(arena, "", v); break; -#define X(name, lower, type) case RDI_SectionKind_##name:{result = str8_lit(#name);} break; - RDI_SectionKind_XList -#undef X - } - return result; -} - -internal String8 -rdi_string_from_arch(Arena *arena, RDI_Arch v) -{ - String8 result; - switch (v) { - default:{ result = push_str8f(arena, "", v); } break; -#define X(name) case RDI_LocalKind_##name:{ result = str8_lit(#name); } break; - RDI_LocalKind_XList -#undef X - } - return result; -} - -internal String8 -rdi_string_from_member_kind(Arena *arena, RDI_MemberKind v) -{ - String8 result; - switch (v) { - default: { result = push_str8f(arena, "", v); } break; -#define X(name) case RDI_MemberKind_##name: { result = str8_lit(#name); } break; - RDI_MemberKind_XList -#undef X - } - return result; -} - -internal String8 -rdi_string_from_reg_code_x86(U64 reg_code) -{ -#define X(name, value) case RDI_RegCodeX86_##name: return str8_lit(#name); - switch (reg_code) { - RDI_RegCodeX86_XList - } -#undef X - return str8_lit(""); -} - -internal String8 -rdi_string_from_reg_code_x64(U64 reg_code) -{ -#define X(name, value) case RDI_RegCodeX64_##name: return str8_lit(#name); - switch (reg_code) { - RDI_RegCodeX64_XList - } -#undef X - return str8_lit(""); -} - -internal String8 -rdi_string_from_reg_code(Arena *arena, RDI_Arch arch, U64 reg_code) -{ - switch (arch) { - case RDI_Arch_NULL: break; - case RDI_Arch_X86: return rdi_string_from_reg_code_x86(reg_code); - case RDI_Arch_X64: return rdi_string_from_reg_code_x64(reg_code); - default: InvalidPath; - } - return push_str8f(arena, "??? (%llu)", reg_code); -} - -internal String8 -rdi_string_from_eval_op(Arena *arena, RDI_EvalOp op) -{ - switch (op) { - case RDI_EvalOp_Stop: return str8_lit("Stop"); - case RDI_EvalOp_Noop: return str8_lit("Noop"); - case RDI_EvalOp_Cond: return str8_lit("Cond"); - case RDI_EvalOp_Skip: return str8_lit("Skip"); - case RDI_EvalOp_MemRead: return str8_lit("MemRead"); - case RDI_EvalOp_RegRead: return str8_lit("RegRead"); - case RDI_EvalOp_RegReadDyn: return str8_lit("RegReadDyn"); - case RDI_EvalOp_FrameOff: return str8_lit("FrameOff"); - case RDI_EvalOp_ModuleOff: return str8_lit("ModuleOff"); - case RDI_EvalOp_TLSOff: return str8_lit("TLSOff"); - case RDI_EvalOp_ObjectOff: return str8_lit("ObjectOff"); - case RDI_EvalOp_CFA: return str8_lit("CFA"); - case RDI_EvalOp_ConstU8: return str8_lit("ConstU8"); - case RDI_EvalOp_ConstU16: return str8_lit("ConstU16"); - case RDI_EvalOp_ConstU32: return str8_lit("ConstU32"); - case RDI_EvalOp_ConstU64: return str8_lit("ConstU64"); - case RDI_EvalOp_ConstU128: return str8_lit("ConstU128"); - case RDI_EvalOp_ConstString: return str8_lit("ConstString"); - case RDI_EvalOp_Abs: return str8_lit("Abs"); - case RDI_EvalOp_Neg: return str8_lit("Neg"); - case RDI_EvalOp_Add: return str8_lit("Add"); - case RDI_EvalOp_Sub: return str8_lit("Sub"); - case RDI_EvalOp_Mul: return str8_lit("Mul"); - case RDI_EvalOp_Div: return str8_lit("Div"); - case RDI_EvalOp_Mod: return str8_lit("Mod"); - case RDI_EvalOp_LShift: return str8_lit("LShift"); - case RDI_EvalOp_RShift: return str8_lit("RShift"); - case RDI_EvalOp_BitAnd: return str8_lit("BitAnd"); - case RDI_EvalOp_BitOr: return str8_lit("BitOr"); - case RDI_EvalOp_BitXor: return str8_lit("BitXor"); - case RDI_EvalOp_BitNot: return str8_lit("BitNot"); - case RDI_EvalOp_LogAnd: return str8_lit("LogAnd"); - case RDI_EvalOp_LogOr: return str8_lit("LogOr"); - case RDI_EvalOp_LogNot: return str8_lit("LogNot"); - case RDI_EvalOp_EqEq: return str8_lit("EqEq"); - case RDI_EvalOp_NtEq: return str8_lit("NtEq"); - case RDI_EvalOp_LsEq: return str8_lit("LsEq"); - case RDI_EvalOp_GrEq: return str8_lit("GrEq"); - case RDI_EvalOp_Less: return str8_lit("Less"); - case RDI_EvalOp_Grtr: return str8_lit("Grtr"); - case RDI_EvalOp_Trunc: return str8_lit("Trunc"); - case RDI_EvalOp_TruncSigned: return str8_lit("TruncSigned"); - case RDI_EvalOp_Convert: return str8_lit("Convert"); - case RDI_EvalOp_Pick: return str8_lit("Pick"); - case RDI_EvalOp_Pop: return str8_lit("Pop"); - case RDI_EvalOp_Insert: return str8_lit("Insert"); - case RDI_EvalOp_ValueRead: return str8_lit("ValueRead"); - case RDI_EvalOp_ByteSwap: return str8_lit("ByteSwap"); - case RDI_EvalOp_CallSiteValue: return str8_lit("CallSiteValue"); - case RDI_EvalOp_PartialValue: return str8_lit("PartialValue"); - case RDI_EvalOp_PartialValueBit: return str8_lit("PartialValueBit"); - } - return push_str8f(arena, "%#x", op); -} - -internal String8 -rdi_string_from_eval_type_group(Arena *arena, RDI_EvalTypeGroup x) -{ - switch (x) { - case RDI_EvalTypeGroup_Other: return str8_lit("Other"); - case RDI_EvalTypeGroup_U: return str8_lit("U"); - case RDI_EvalTypeGroup_S: return str8_lit("S"); - case RDI_EvalTypeGroup_F32: return str8_lit("F32"); - case RDI_EvalTypeGroup_F64: return str8_lit("F64"); - } - return push_str8f(arena, "%#x", x); -} - -internal String8 -rdi_string_from_binary_section_flags(Arena *arena, RDI_BinarySectionFlags flags) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List list = {0}; -#define X(name) if (flags & RDI_BinarySectionFlag_##name) { flags &= ~RDI_BinarySectionFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } - RDI_BinarySectionFlags_XList; -#undef X - String8 result = rd_string_from_flags(arena, list, flags); - scratch_end(scratch); - return result; -} - -internal String8 -rdi_string_from_type_modifier_flags(Arena *arena, RDI_TypeModifierFlags flags) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List list = {0}; -#define X(name) if(flags & RDI_TypeModifierFlag_##name) { flags &= ~RDI_TypeModifierFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } - RDI_TypeModifierFlags_XList; -#undef X - String8 result = rd_string_from_flags(arena, list, flags); - scratch_end(scratch); - return result; -} - -internal String8 -rdi_string_from_udt_flags(Arena *arena, RDI_UDTFlags flags) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List list = {0}; -#define X(name) if (flags & RDI_UDTFlag_##name) { flags &= ~RDI_UDTFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } - RDI_UDTFlags_XList; -#undef X - String8 result = rd_string_from_flags(arena, list, flags); - scratch_end(scratch); - return result; -} - -internal String8 -rdi_string_from_link_flags(Arena *arena, RDI_LinkFlags flags) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List list = {0}; -#define X(name) if (flags & RDI_LinkFlag_##name) { flags &= ~RDI_LinkFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } - RDI_LinkFlags_XList; -#undef X - String8 result = rd_string_from_flags(arena, list, flags); - scratch_end(scratch); - return result; -} - -internal void -rdi_print_data_sections(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi) -{ - Temp scratch = scratch_begin(&arena, 1); - for(U64 idx = 0; idx < rdi->sections_count; idx += 1) { - RDI_SectionKind kind = (RDI_SectionKind)idx; - RDI_Section *section = &rdi->sections[idx]; - String8 kind_str = rdi_string_from_data_section_kind(scratch.arena, kind); - rd_printf("data_section[%5llu] = {%#08llx, %7u, %7u}, %S", idx, section->off, section->encoded_size, section->unpacked_size, kind_str); - } - scratch_end(scratch); -} - -internal void -rdi_print_top_level_info(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_TopLevelInfo *tli) -{ - Temp scratch = scratch_begin(&arena, 1); - rd_printf("arch =%S", rdi_string_from_arch(scratch.arena, tli->arch)); - rd_printf("exe_name ='%S'", str8_from_rdi_string_idx(rdi, tli->exe_name_string_idx)); - rd_printf("voff_max =%#08llx", tli->voff_max); - rd_printf("producer_name='%S'", str8_from_rdi_string_idx(rdi, tli->producer_name_string_idx)); - scratch_end(scratch); -} - -internal void -rdi_print_binary_section(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_BinarySection *bin_section) -{ - Temp scratch = scratch_begin(&arena, 1); - rd_printf("name ='%S'", str8_from_rdi_string_idx(rdi, bin_section->name_string_idx)); - rd_printf("flags =%S", rdi_string_from_binary_section_flags(scratch.arena, bin_section->flags)); - rd_printf("voff_first=%#08x", bin_section->voff_first); - rd_printf("voff_opl =%#08x", bin_section->voff_opl); - rd_printf("foff_first=%#08x", bin_section->foff_first); - rd_printf("foff_opl =%#08x", bin_section->foff_opl); - scratch_end(scratch); -} - -internal void -rdi_print_file_path(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_FilePathNode *file_path) -{ - U64 file_path_count = 0; - RDI_FilePathNode *file_path_array = rdi_table_from_name(rdi, FilePathNodes, &file_path_count); - - String8 name = str8_from_rdi_string_idx(rdi, file_path->name_string_idx); - U64 this_idx = (U64)(file_path - file_path_array); - - if (file_path->source_file_idx == 0) { - rd_printf("[%llu] '%S'", this_idx, name); - } else { - rd_printf("[%llu] '%S'; source_file=%u", this_idx, name, file_path->source_file_idx); - } - - for (U32 child = file_path->first_child; child != 0; ) { - // get node for child - RDI_FilePathNode *child_node = 0; - if (child < file_path_count) { - child_node = file_path_array + child; - } - if (child_node == 0) { - break; - } - - // stringize child - rd_indent(); - rdi_print_file_path(arena, out, indent, rdi, child_node); - rd_unindent(); - - // increment iterator - child = child_node->next_sibling; - } -} - -internal void -rdi_print_source_file(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_SourceFile *source_file) -{ - rd_printf("{ file_path_node_idx= "); - rd_printf("file_path_node_idx= %u", source_file->file_path_node_idx); - rd_printf("path= '%S'", str8_from_rdi_string_idx(rdi, source_file->normal_full_path_string_idx)); - rd_printf("source_line_map= %u", source_file->source_line_map_idx); -} - -internal void -rdi_print_line_table(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_LineTable *line_table) -{ - RDI_ParsedLineTable parsed_line_table = {0}; - rdi_parsed_from_line_table(rdi, line_table, &parsed_line_table); - - rd_printf("lines:"); - for (U32 i = 0; i < parsed_line_table.count; i += 1) { - U64 first = parsed_line_table.voffs[i]; - U64 opl = parsed_line_table.voffs[i + 1]; - RDI_Line *line = parsed_line_table.lines + i; - RDI_Column *col = 0; - if (i < parsed_line_table.col_count) { - col = parsed_line_table.cols + i; - } - if (col == 0) { - rd_printf("[0x%08llx,0x%08llx) file=%u; line=%u", first, opl, line->file_idx, line->line_num); - } else { - rd_printf("[0x%08llx,0x%08llx) file=%u; line=%u; columns=[%u,%u)", first, opl, line->file_idx, line->line_num, col->col_first, col->col_opl); - } - } -} - -internal void -rdi_print_source_line_map(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_SourceLineMap *map) -{ - Temp scratch = scratch_begin(&arena, 1); - - RDI_ParsedSourceLineMap line_map = {0}; - rdi_parsed_from_source_line_map(rdi, map, &line_map); - - rd_printf("source lines:"); - for (U32 line_num_idx = 0; line_num_idx < line_map.count; ++line_num_idx) { - Temp temp = temp_begin(scratch.arena); - - String8List list = {0}; - U32 voff_lo = line_map.ranges[line_num_idx]; - U32 voff_hi = ClampTop(line_map.ranges[line_num_idx + 1], line_map.voff_count); - for (U64 voff_idx = voff_lo; voff_idx < voff_hi; ++voff_idx) { - str8_list_pushf(temp.arena, &list, "%#llx", line_map.voffs[voff_idx]); - } - - String8 voffs = str8_list_join(temp.arena, &list, &(StringJoin){.sep=str8_lit(", ")}); - rd_printf("%u: %S", line_map.nums[line_num_idx], voffs); - - temp_end(temp); - } - - scratch_end(scratch); -} - -internal void -rdi_print_unit(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Unit *unit) -{ - Temp scratch = scratch_begin(&arena, 1); - rd_printf("unit_name ='%S'", str8_from_rdi_string_idx(rdi, unit->unit_name_string_idx)); - rd_printf("compiler_name ='%S'", str8_from_rdi_string_idx(rdi, unit->compiler_name_string_idx)); - rd_printf("source_file_path =%u", unit->source_file_path_node); - rd_printf("object_file_path =%u", unit->object_file_path_node); - rd_printf("archive_file_path=%u", unit->archive_file_path_node); - rd_printf("build_path =%u", unit->build_path_node); - rd_printf("language =%S", rdi_string_from_language(scratch.arena, unit->language)); - rd_printf("line_table_idx =%u", unit->line_table_idx); - scratch_end(scratch); -} - -internal void -rdi_print_type_node(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_TypeNode *type) -{ - Temp scratch = scratch_begin(&arena, 1); - - String8 type_kind_str = {0}; - type_kind_str.str = rdi_string_from_type_kind(type->kind, &type_kind_str.size); - - rd_printf("kind =%S", type_kind_str); - if (type->kind == RDI_TypeKind_Modifier) { - rd_printf("flags =%S", rdi_string_from_type_modifier_flags(scratch.arena, type->flags)); - } else { - if (type->flags != 0) { - rd_printf("flags=%#x (missing stringizer path)", type->flags); - } - } - rd_printf("byte_size =%u", type->byte_size); - if (RDI_TypeKind_FirstBuiltIn <= type->kind && type->kind <= RDI_TypeKind_LastBuiltIn) { - rd_printf("built_in.name ='%S'", str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx)); - } else if (type->kind == RDI_TypeKind_Array) { - rd_printf("constructed.direct_type =%u", type->constructed.direct_type_idx); - rd_printf("constructed.array_count =%u", type->constructed.count); - } else if (type->kind == RDI_TypeKind_Function) { - U32 param_idx_count = 0; - U32 *param_idx_array = rdi_idx_run_from_first_count(rdi, type->constructed.param_idx_run_first, type->constructed.count, ¶m_idx_count); - String8 param_idx_str = rd_string_from_array_u32(scratch.arena, param_idx_array, param_idx_count); - rd_printf("constructed.params =%S", param_idx_str); - rd_printf("return type =%u", type->constructed.direct_type_idx); - } else if (type->kind == RDI_TypeKind_Method) { - U32 param_idx_count = 0; - U32 *param_idx_array = rdi_idx_run_from_first_count(rdi, type->constructed.param_idx_run_first, type->constructed.count, ¶m_idx_count); - String8 this_type_str = str8_lit("\?\?\?"); - if (param_idx_count > 0) { - this_type_str = push_str8f(scratch.arena, "%u", param_idx_array[0]); - param_idx_count -= 1; - param_idx_array += 1; - } - String8 param_idx_str = rd_string_from_array_u32(scratch.arena, param_idx_array, param_idx_count); - rd_printf("constructed.this_type =%S", this_type_str); - rd_printf("constructed.params =%S", param_idx_str); - rd_printf("return type =%u", type->constructed.direct_type_idx); - } else if (RDI_TypeKind_FirstConstructed <= type->kind && type->kind <= RDI_TypeKind_LastConstructed) { - - rd_printf("constructed.direct_type =%u", type->constructed.direct_type_idx); - } else if (RDI_TypeKind_FirstUserDefined <= type->kind && type->kind <= RDI_TypeKind_LastUserDefined){ - rd_printf("user_defined.name ='%S'", str8_from_rdi_string_idx(rdi, type->user_defined.name_string_idx)); - rd_printf("user_defined.direct_type=%u", type->user_defined.direct_type_idx); - rd_printf("user_defined.udt =%u", type->user_defined.udt_idx); - } else if (type->kind == RDI_TypeKind_Bitfield) { - rd_printf("bitfield.off =%u", type->bitfield.off); - rd_printf("bitfield.size =%u", type->bitfield.size); - } - - scratch_end(scratch); -} - -internal void -rdi_print_udt(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_UDT *udt) -{ - Temp scratch = scratch_begin(&arena, 1); - - U64 member_count = 0; - U64 enum_member_count = 0; - RDI_Member *member_array = rdi_table_from_name(rdi, Members, &member_count); - RDI_EnumMember *enum_member_array = rdi_table_from_name(rdi, EnumMembers, &enum_member_count); - - String8 flags_str = rdi_string_from_udt_flags(scratch.arena, udt->flags); - - rd_printf("self_type=%u", udt->self_type_idx); - rd_printf("flags =%S", flags_str); - if (udt->file_idx != 0) { - rd_printf("loc ={file=%u; line=%u; col=%u}", udt->file_idx, udt->line, udt->col); - } - - // enum members - if (udt->flags & RDI_UDTFlag_EnumMembers) { - U32 member_hi = ClampTop(udt->member_first + udt->member_count, enum_member_count); - U32 member_lo = ClampTop(udt->member_first, member_hi); - if (member_lo < member_hi) { - rd_printf("members={"); - rd_indent(); - RDI_EnumMember *enum_member = enum_member_array + member_lo; - for (U32 i = member_lo; i < member_hi; ++i, ++enum_member) { - rd_printf("{ %llu, '%S' }", enum_member->val, str8_from_rdi_string_idx(rdi, enum_member->name_string_idx)); - } - rd_unindent(); - rd_printf("}"); - } - } - // field members - else { - U32 member_hi = ClampTop(udt->member_first + udt->member_count, member_count); - U32 member_lo = ClampTop(udt->member_first, member_hi); - if (member_lo < member_hi) { - rd_printf("members={"); - rd_indent(); - RDI_Member *member = member_array + member_lo; - for (U32 i = member_lo; i < member_hi; ++i, ++member) { - String8 kind_str = rdi_string_from_member_kind(scratch.arena, member->kind); - String8 name_str = str8_from_rdi_string_idx(rdi, member->name_string_idx); - rd_printf("{ kind=%S, type=%u, off=%u, name='%S' }", kind_str, member->type_idx, member->off, name_str); - } - rd_unindent(); - rd_printf("}"); - } - } - scratch_end(scratch); -} - -internal String8 -rdi_string_from_bytecode(Arena *arena, RDI_Arch arch, String8 bc) -{ - Temp scratch = scratch_begin(&arena, 1); - - String8List fmt = {0}; - for (U64 cursor = 0; cursor < bc.size; ) { - RDI_EvalOp op = RDI_EvalOp_Stop; - cursor += str8_deserial_read_struct(bc, cursor, &op); - - U16 ctrlbits = rdi_eval_op_ctrlbits_table[op]; - U32 imm_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); - - String8 imm = {0}; - cursor += str8_deserial_read_block(bc, cursor, imm_size, &imm); - if (imm.size != imm_size) { - str8_list_pushf(scratch.arena, &fmt, "(ERROR: not enough bytes to read immediate)"); - break; - } - - String8 imm_fmt = {0}; - switch (op) { - case RDI_EvalOp_Stop: goto exit; - case RDI_EvalOp_Noop: break; - case RDI_EvalOp_Cond: break; - case RDI_EvalOp_Skip: { - imm_fmt = push_str8f(scratch.arena, "%u", *(U16 *)imm.str); - } break; - case RDI_EvalOp_MemRead: { - imm_fmt = push_str8f(scratch.arena, "%u", *(U8 *)imm.str); - } break; - case RDI_EvalOp_RegRead: { - U32 regread = *(U32 *)imm.str; - RDI_RegCode reg_code = Extract8(regread, 0); - U8 byte_size = Extract8(regread, 1); - U8 byte_off = Extract8(regread, 2); - String8 reg_str = rdi_string_from_reg_code(scratch.arena, arch, reg_code); - imm_fmt = push_str8f(scratch.arena, "%S, Size: %u", rd_string_from_reg_off(scratch.arena, reg_str, byte_off), byte_size); - } break; - case RDI_EvalOp_RegReadDyn: break; - case RDI_EvalOp_FrameOff: { - imm_fmt = push_str8f(scratch.arena, "%+lld", *(S64 *)imm.str); - } break; - case RDI_EvalOp_ModuleOff: { - imm_fmt = push_str8f(scratch.arena, "%u", *(U32 *)imm.str); - } break; - case RDI_EvalOp_TLSOff: { - imm_fmt = push_str8f(scratch.arena, "%u", *(U32 *)imm.str); - } break; - case RDI_EvalOp_ConstU8: { - imm_fmt = push_str8f(scratch.arena, "%u", *(U8 *)imm.str); - } break; - case RDI_EvalOp_ConstU16: { - imm_fmt = push_str8f(scratch.arena, "%u", *(U16 *)imm.str); - } break; - case RDI_EvalOp_ConstU32: { - imm_fmt = push_str8f(scratch.arena, "%u", *(U32 *)imm.str); - } break; - case RDI_EvalOp_ConstU64: { - imm_fmt = push_str8f(scratch.arena, "%llu", *(U64 *)imm.str); - } break; - case RDI_EvalOp_ConstU128: { - imm_fmt = push_str8f(scratch.arena, "Lo: %llu, Hi: %llu", *(U64 *)imm.str, *((U64 *)imm.str + 1)); - } break; - case RDI_EvalOp_ConstString: { - U8 size = *(U8 *)imm.str; - String8 string = {0}; - cursor += str8_deserial_read_block(bc, cursor, size, &string); - - imm_fmt = push_str8f(scratch.arena, "(%u) \"%S\"", size, string); - } break; - case RDI_EvalOp_Abs: - case RDI_EvalOp_Neg: - case RDI_EvalOp_Add: - case RDI_EvalOp_Sub: - case RDI_EvalOp_Mul: - case RDI_EvalOp_Div: - case RDI_EvalOp_Mod: - case RDI_EvalOp_LShift: - case RDI_EvalOp_RShift: - case RDI_EvalOp_BitAnd: - case RDI_EvalOp_BitOr: - case RDI_EvalOp_BitXor: - case RDI_EvalOp_BitNot: - case RDI_EvalOp_LogAnd: - case RDI_EvalOp_LogOr: - case RDI_EvalOp_LogNot: - case RDI_EvalOp_EqEq: - case RDI_EvalOp_NtEq: - case RDI_EvalOp_LsEq: - case RDI_EvalOp_GrEq: - case RDI_EvalOp_Less: - case RDI_EvalOp_Grtr: { - U8 eval_type_group = *(U8 *)imm.str; - imm_fmt = rdi_string_from_eval_type_group(scratch.arena, eval_type_group); - } break; - case RDI_EvalOp_Trunc: - case RDI_EvalOp_TruncSigned: { - U8 trunc = *(U8 *)imm.str; - imm_fmt = push_str8f(scratch.arena, "%u", trunc); - } break; - case RDI_EvalOp_Convert: { - U16 convert = *(U16 *)imm.str; - U8 in = Extract8(convert, 0); - U8 out = Extract8(convert, 1); - String8 in_str = rdi_string_from_eval_type_group(scratch.arena, in); - String8 out_str = rdi_string_from_eval_type_group(scratch.arena, out); - imm_fmt = push_str8f(scratch.arena, "in: %S out: %S", in_str, out_str); - } break; - case RDI_EvalOp_Pick: { - U8 pick = *(U8 *)imm.str; - imm_fmt = push_str8f(scratch.arena, "%u", pick); - } break; - case RDI_EvalOp_Pop: break; - case RDI_EvalOp_Insert: { - U8 insert = *(U8 *)imm.str; - imm_fmt = push_str8f(scratch.arena, "%u", insert); - } break; - case RDI_EvalOp_ValueRead: { - U8 bytes_to_read = *(U8 *)imm.str; - imm_fmt = push_str8f(scratch.arena, "%u", bytes_to_read); - } break; - case RDI_EvalOp_ByteSwap: { - U8 byte_size = *(U8 *)imm.str; - imm_fmt = push_str8f(scratch.arena, "%u", byte_size); - } break; - case RDI_EvalOp_CallSiteValue: { - U32 call_site_bc_size = *(U32 *)imm.str; - String8 call_site_bc = {0}; - cursor += str8_deserial_read_block(bc, cursor, call_site_bc_size, &call_site_bc); - - String8 call_site_str = rdi_string_from_bytecode(scratch.arena, arch, call_site_bc); - imm_fmt = push_str8f(scratch.arena, "%S", call_site_str); - } break; - case RDI_EvalOp_PartialValue: { - U32 partial_value_size = *(U32 *)imm.str; - imm_fmt = push_str8f(scratch.arena, "%u", partial_value_size); - } break; - case RDI_EvalOp_PartialValueBit: { - U64 partial_value = *(U64 *)imm.str; - U32 bit_size = Extract32(partial_value, 0); - U32 bit_off = Extract32(partial_value, 1); - imm_fmt = push_str8f(scratch.arena, "Off: %u, Size: %u", bit_size, bit_off); - } break; - } - - String8 op_str = rdi_string_from_eval_op(scratch.arena, op); - if (imm_fmt.size) { - str8_list_pushf(scratch.arena, &fmt, "RDI_EvalOp_%S(%S)", op_str, imm_fmt); - } else { - str8_list_pushf(scratch.arena, &fmt, "RDI_EvalOp_%S", op_str); - } - } - exit:; - - String8 result = str8_list_join(arena, &fmt, &(StringJoin){.sep = str8_lit(", ")}); - - scratch_end(scratch); - return result; -} - -internal void -rdi_print_locations(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Arch arch, U64 block_lo, U64 block_hi) -{ - Temp scratch = scratch_begin(&arena, 1); - - U64 location_block_count = 0; - U64 location_data_size = 0; - RDI_LocationBlock *location_block_array = rdi_table_from_name(rdi, LocationBlocks, &location_block_count); - RDI_U8 *location_data = rdi_table_from_name(rdi, LocationData, &location_data_size); - - block_lo = ClampTop(block_lo, location_block_count); - block_hi = ClampTop(block_hi, location_block_count); - - for (U32 block_idx = block_lo; block_idx < block_hi; ++block_idx) { - RDI_LocationBlock *block_ptr = &location_block_array[block_idx]; - - String8List fmt = {0}; - - if (block_ptr->scope_off_first == 0 && block_ptr->scope_off_opl == max_U32) { - str8_list_pushf(scratch.arena, &fmt, "*always*:"); - } else { - str8_list_pushf(scratch.arena, &fmt, "[%#08x, %#08x):", block_ptr->scope_off_first, block_ptr->scope_off_opl); - } - - if (block_ptr->location_data_off >= location_data_size) { - str8_list_pushf(scratch.arena, &fmt, "", block_ptr->location_data_off); - } else { - U8 *loc_data_opl = location_data + location_data_size; - U8 *loc_base_ptr = location_data + block_ptr->location_data_off; - RDI_LocationKind kind = *(RDI_LocationKind*)loc_base_ptr; - switch (kind) { - default: { - str8_list_pushf(scratch.arena, &fmt, "\?\?\?: %u", kind); - } break; - - case RDI_LocationKind_AddrBytecodeStream: { - String8 bc = str8_range(loc_base_ptr + 1, loc_data_opl); - String8 bc_str = rdi_string_from_bytecode(scratch.arena, arch, bc); - str8_list_pushf(scratch.arena, &fmt, "AddrBytecodeStream(%S)", bc_str); - } break; - - case RDI_LocationKind_ValBytecodeStream: { - String8 bc = str8_range(loc_base_ptr + 1, loc_data_opl); - String8 bc_str = rdi_string_from_bytecode(scratch.arena, arch, bc); - str8_list_pushf(scratch.arena, &fmt, "ValBytecodeStream(%S)", bc_str); - } break; - - case RDI_LocationKind_AddrRegPlusU16: { - if (loc_base_ptr + sizeof(RDI_LocationRegPlusU16) > loc_data_opl) { - str8_list_pushf(scratch.arena, &fmt, "AddrRegPlusU16(\?\?\?)"); - } else { - RDI_LocationRegPlusU16 *loc = (RDI_LocationRegPlusU16*)loc_base_ptr; - str8_list_pushf(scratch.arena, &fmt, "AddrRegPlusU16(reg: %S, off: %u)", rdi_string_from_reg_code(scratch.arena, arch, loc->reg_code), loc->offset); - } - } break; - - case RDI_LocationKind_AddrAddrRegPlusU16: { - if (loc_base_ptr + sizeof(RDI_LocationRegPlusU16) > loc_data_opl){ - str8_list_pushf(scratch.arena, &fmt, "AddrAddrRegPlusU16(\?\?\?)"); - } else { - RDI_LocationRegPlusU16 *loc = (RDI_LocationRegPlusU16 *)loc_base_ptr; - str8_list_pushf(scratch.arena, &fmt, "AddrAddrRegisterPlusU16(reg: %S, off: %u)", rdi_string_from_reg_code(scratch.arena, arch, loc->reg_code), loc->offset); - } - } break; - - case RDI_LocationKind_ValReg: { - if (loc_base_ptr + sizeof(RDI_LocationReg) > loc_data_opl) { - str8_list_pushf(scratch.arena, &fmt, "ValReg(\?\?\?)"); - } else { - RDI_LocationReg *loc = (RDI_LocationReg*)loc_base_ptr; - str8_list_pushf(scratch.arena, &fmt, "ValReg(reg: %S)", rdi_string_from_reg_code(scratch.arena, arch, loc->reg_code)); - } - } break; - } - } - - String8 print_string = str8_list_join(scratch.arena, &fmt, &(StringJoin){.sep=str8_lit(" ")}); - rd_printf("%S", print_string); - } - - scratch_end(scratch); -} - -internal void -rdi_print_global_variable(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_GlobalVariable *gvar) -{ - Temp scratch = scratch_begin(&arena, 1); - rd_printf("name ='%S'", str8_from_rdi_string_idx(rdi, gvar->name_string_idx)); - rd_printf("link_flags =%S", rdi_string_from_link_flags(scratch.arena, gvar->link_flags)); - rd_printf("voff =%#08x", gvar->voff); - rd_printf("type_idx =%u", gvar->type_idx); - rd_printf("container_idx=%u", gvar->container_idx); - scratch_end(scratch); -} - -internal void -rdi_print_thread_variable(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_ThreadVariable *tvar) -{ - Temp scratch = scratch_begin(&arena, 1); - rd_printf("name ='%S'", str8_from_rdi_string_idx(rdi, tvar->name_string_idx)); - rd_printf("link_flags =%S", rdi_string_from_link_flags(scratch.arena, tvar->link_flags)); - rd_printf("tls_off =%#08x", tvar->tls_off); - rd_printf("type_idx =%u", tvar->type_idx); - rd_printf("container_idx=%u", tvar->container_idx); - scratch_end(scratch); -} - -internal void -rdi_print_procedure(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Procedure *proc, RDI_Arch arch) -{ - Temp scratch = scratch_begin(&arena, 1); - rd_printf("name ='%S'", str8_from_rdi_string_idx(rdi, proc->name_string_idx)); - rd_printf("link_name ='%S'", str8_from_rdi_string_idx(rdi, proc->link_name_string_idx)); - rd_printf("link_flags =%S", rdi_string_from_link_flags(scratch.arena, proc->link_flags)); - rd_printf("type_idx =%u", proc->type_idx); - rd_printf("root_scope_idx =%u", proc->root_scope_idx); - rd_printf("container_idx =%u", proc->container_idx); - rd_printf("frame_base (first=%u, opl=%u)", proc->frame_base_location_first, proc->frame_base_location_opl); - rd_indent(); - rdi_print_locations(arena, out, indent, rdi, arch, proc->frame_base_location_first, proc->frame_base_location_opl); - rd_unindent(); - - scratch_end(scratch); -} - -internal void -rdi_print_scope(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Scope *scope, RDI_Arch arch) -{ - Temp scratch = scratch_begin(&arena, 1); - - U64 scope_count = 0; - U64 scope_voff_count = 0; - U64 local_count = 0; - U64 proc_count = 0; - U64 inline_site_count = 0; - RDI_Scope *scope_array = rdi_table_from_name(rdi, Scopes, &scope_count); - U64 *scope_voff_array = rdi_table_from_name(rdi, ScopeVOffData, &scope_voff_count); - RDI_Local *local_array = rdi_table_from_name(rdi, Locals, &local_count); - RDI_Procedure *proc_array = rdi_table_from_name(rdi, Procedures, &proc_count); - RDI_InlineSite *inline_site_array = rdi_table_from_name(rdi, InlineSites, &inline_site_count); - - U32 voff_range_lo = ClampTop(scope->voff_range_first, scope_voff_count); - U32 voff_range_hi = ClampTop(scope->voff_range_opl, scope_voff_count); - U32 voff_range_count = (voff_range_hi - voff_range_lo); - U64 *voff_ptr = scope_voff_array + voff_range_lo; - String8 voff_str = rd_string_from_range_array_u64_hex(scratch.arena, voff_ptr, voff_range_count); - - U64 scope_idx = (U64)(scope - scope_array); - rd_printf("scope[%llu]", scope_idx); - rd_indent(); - - String8 proc_name = str8_lit("???"); - if (scope->proc_idx < proc_count) { - RDI_Procedure *proc = &proc_array[scope->proc_idx]; - proc_name = str8_from_rdi_string_idx(rdi, proc->name_string_idx); - } - - String8 inline_site_name = str8_lit(""); - if (scope->inline_site_idx != 0) { - if (scope->inline_site_idx < inline_site_count) { - RDI_InlineSite *inline_site = &inline_site_array[scope->inline_site_idx]; - inline_site_name = str8_from_rdi_string_idx(rdi, inline_site->name_string_idx); - } else { - inline_site_name = str8_lit("???"); - } - inline_site_name = push_str8f(scratch.arena, " '%S'", inline_site_name); - } - - rd_printf("proc_idx =%u '%S'", scope->proc_idx, proc_name); - rd_printf("first_child_scope_idx =%u", scope->first_child_scope_idx); - rd_printf("next_sibling_scope_idx=%u", scope->next_sibling_scope_idx); - rd_printf("inline_site_idx =%u%S", scope->inline_site_idx, inline_site_name); - rd_printf("voff_ranges =%S", voff_str); - - // local_array - { - U32 local_lo = ClampTop(scope->local_first, local_count); - U32 local_hi = ClampTop(local_lo + scope->local_count, local_count); - if (local_lo < local_hi) { - for (U32 local_idx = local_lo; local_idx < local_hi; ++local_idx) { - RDI_Local *local_ptr = &local_array[local_idx]; - - rd_printf("local[%u]", local_idx); - rd_indent(); - rd_printf("kind =%S", rdi_string_from_local_kind(scratch.arena, local_ptr->kind)); - rd_printf("name ='%S'", str8_from_rdi_string_idx(rdi, local_ptr->name_string_idx)); - rd_printf("type_idx=%u", local_ptr->type_idx); - - if (local_ptr->location_first < local_ptr->location_opl) { - rd_printf("locations:"); - rd_indent(); - rdi_print_locations(arena, out, indent, rdi, arch, local_ptr->location_first, local_ptr->location_opl); - rd_unindent(); - } - rd_unindent(); - } - } - } - - for (U32 child_scope_idx = scope->first_child_scope_idx; child_scope_idx != 0; ) { - if (child_scope_idx >= scope_count) { - rd_errorf("child scope index (%u) is out of bounds", child_scope_idx); - break; - } - - rd_indent(); - RDI_Scope *child_scope = scope_array + child_scope_idx; - rdi_print_scope(arena, out, indent, rdi, child_scope, arch); - rd_unindent(); - - // advance to next child - child_scope_idx = child_scope->next_sibling_scope_idx; - } - - rd_unindent(); - rd_printf("[/%llu]", scope_idx); - - scratch_end(scratch); -} - -internal void -rdi_print_inline_site(Arena *arena, - String8List *out, - String8 indent, - RDI_Parsed *rdi, - U64 idx, - RDI_InlineSite *inline_site) -{ - Temp scratch = scratch_begin(&arena, 1); - String8 inline_site_idx = push_str8f(scratch.arena, "inline_site[%u]", idx); - String8 type_idx = push_str8f(scratch.arena, "type_idx = %u,", inline_site->type_idx); - String8 owner_type_idx = push_str8f(scratch.arena, "owner_type_idx = %u,", inline_site->owner_type_idx); - String8 line_table_idx = push_str8f(scratch.arena, "line_table_idx = %u,", inline_site->line_table_idx); - rd_printf("%-20S = { %-25S %-25S %-25S name = '%-20S' }", - inline_site_idx, - type_idx, - owner_type_idx, - line_table_idx, - str8_from_rdi_string_idx(rdi, inline_site->name_string_idx)); - scratch_end(scratch); -} - -internal void -rdi_print_vmap_entry(Arena *arena, String8List *out, String8 indent, RDI_VMapEntry *v) -{ - rd_printf("%#llx: %llu", v->voff, v->idx); -} - -internal void -rdi_print(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RD_Option opts) -{ - RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); - - if (opts & RD_Option_RdiDataSections) { - rd_printf("# DATA SECTIONS"); - rd_indent(); - rdi_print_data_sections(arena, out, indent, rdi); - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiTopLevelInfo) { - rd_printf("# TOP LEVEL INFO"); - rd_indent(); - rdi_print_top_level_info(arena, out, indent, rdi, tli); - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiBinarySections) { - U64 count; - RDI_BinarySection *v = rdi_table_from_name(rdi, BinarySections, &count); - rd_printf("# BINARY SECTIONS"); - rd_indent(); - for (U64 idx = 0; idx < count; ++idx) { - rd_printf("section[%llu]:", idx); - rd_indent(); - rdi_print_binary_section(arena, out, indent, rdi, &v[idx]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiFilePaths) { - U64 file_path_count = 0; - RDI_FilePathNode *file_path_array = rdi_table_from_name(rdi, FilePathNodes, &file_path_count); - rd_printf("# FILE PATHS"); - rd_indent(); - for (U64 i = 0; i < file_path_count; ++i) { - if (file_path_array[i].parent_path_node == 0) { - rdi_print_file_path(arena, out, indent, rdi, &file_path_array[i]); - } - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiSourceFiles) { - U64 source_file_count = 0; - RDI_SourceFile *source_file_array = rdi_table_from_name(rdi, SourceFiles, &source_file_count); - rd_printf("# SOURCE FILES"); - rd_indent(); - for (U64 i = 0; i < source_file_count; ++i) { - RDI_SourceFile *source_file = &source_file_array[i]; - rd_printf("source_file[%4llu] = { file_path_node_idx = %4u, source_line_map = %4u, path = '%S' }", - i, - source_file->file_path_node_idx, - source_file->source_line_map_idx, - str8_from_rdi_string_idx(rdi, source_file->normal_full_path_string_idx)); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiUnits) { - U64 unit_count = 0; - RDI_Unit *unit_array = rdi_table_from_name(rdi, Units, &unit_count); - rd_printf("# UNITS"); - rd_indent(); - for (U64 i = 0; i < unit_count; ++i) { - rd_printf("unit[%llu]:", i); - rd_indent(); - rdi_print_unit(arena, out, indent, rdi, &unit_array[i]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiUnitVMap) { - U64 vmap_count = 0; - RDI_VMapEntry *vmap_array = rdi_table_from_name(rdi, UnitVMap, &vmap_count); - rd_printf("# UNIT VMAP"); - rd_indent(); - for (U64 i = 0; i < vmap_count; ++i) { - rdi_print_vmap_entry(arena, out, indent, &vmap_array[i]); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiLineTables) { - U64 line_table_count = 0; - RDI_LineTable *line_table_array = rdi_table_from_name(rdi, LineTables, &line_table_count); - rd_printf("# LINE TABLES"); - rd_indent(); - for (U64 i = 0; i < line_table_count; ++i) { - rd_printf("line_table[%llu]", i); - rd_indent(); - rdi_print_line_table(arena, out, indent, rdi, &line_table_array[i]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiSourceLineMaps) { - U64 source_line_map_count = 0; - RDI_SourceLineMap *source_line_map_array = rdi_table_from_name(rdi, SourceLineMaps, &source_line_map_count); - rd_printf("# SOURCE LINE MAPS"); - rd_indent(); - for (U64 i = 0; i < source_line_map_count; ++i) { - rd_printf("source_line_map[%llu]:", i); - rd_indent(); - rdi_print_source_line_map(arena, out, indent, rdi, &source_line_map_array[i]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiTypeNodes) { - U64 type_node_count = 0; - RDI_TypeNode *type_node_array = rdi_table_from_name(rdi, TypeNodes, &type_node_count); - rd_printf("# TYPE NODES"); - rd_indent(); - for (U64 i = 0; i < type_node_count; ++i) { - rd_printf("type[%llu]", i); - rd_indent(); - rdi_print_type_node(arena, out, indent, rdi, &type_node_array[i]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiUserDefinedTypes) { - U64 udt_count = 0; - RDI_UDT *udt_array = rdi_table_from_name(rdi, UDTs, &udt_count); - rd_printf("# UDTS"); - rd_indent(); - for (U64 i = 0; i < udt_count; ++i) { - rd_printf("udt[%u]:", i); - rd_indent(); - rdi_print_udt(arena, out, indent, rdi, &udt_array[i]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiGlobalVars) { - U64 gvar_count = 0; - RDI_GlobalVariable *gvar_array = rdi_table_from_name(rdi, GlobalVariables, &gvar_count); - rd_printf("# GLOBAL VARIABLES"); - rd_indent(); - for (U64 i = 0; i < gvar_count; ++i) { - rd_printf("global_variable[%llu]:", i); - rd_indent(); - rdi_print_global_variable(arena, out, indent, rdi, &gvar_array[i]); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiGlobalVarsVMap) { - U64 vmap_count = 0; - RDI_VMapEntry *vmap_array = rdi_table_from_name(rdi, GlobalVMap, &vmap_count); - rd_printf("# GLOBAL VMAP"); - rd_indent(); - for (U64 i = 0; i < vmap_count; ++i) { - rdi_print_vmap_entry(arena, out, indent, &vmap_array[i]); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiThreadVars) { - U64 tvar_count = 0; - RDI_ThreadVariable *tvar_array = rdi_table_from_name(rdi, ThreadVariables, &tvar_count); - rd_printf("# THREAD VARIABLES"); - rd_indent(); - for (U64 i = 0; i < tvar_count; ++i) { - rd_printf("thread_variable[%llu]:", i); - rdi_print_thread_variable(arena, out, indent, rdi, &tvar_array[i]); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiProcedures) { - U64 proc_count = 0; - RDI_Procedure *proc_array = rdi_table_from_name(rdi, Procedures, &proc_count); - rd_printf("# PROCEDURES"); - rd_indent(); - for (U64 i = 0; i < proc_count; ++i) { - rd_printf("procedure[%llu]:", i); - rd_indent(); - rdi_print_procedure(arena, out, indent, rdi, &proc_array[i], tli->arch); - rd_unindent(); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiScopes) { - U64 scope_count = 0; - RDI_Scope *scope_array = rdi_table_from_name(rdi, Scopes, &scope_count); - rd_printf("# SCOPES"); - rd_indent(); - for (U64 i = 0; i < scope_count; ++i) { - if (scope_array[i].parent_scope_idx == 0) { - rdi_print_scope(arena, out, indent, rdi, &scope_array[i], tli->arch); - } - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiScopeVMap) { - U64 vmap_count = 0; - RDI_VMapEntry *vmap_array = rdi_table_from_name(rdi, ScopeVMap, &vmap_count); - rd_printf("# SCOPE VMAP"); - rd_indent(); - for (U64 i = 0; i < vmap_count; ++i) { - rdi_print_vmap_entry(arena, out, indent, &vmap_array[i]); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiInlineSites) { - U64 inline_site_count = 0; - RDI_InlineSite *inline_site_array = rdi_table_from_name(rdi, InlineSites, &inline_site_count); - rd_printf("# INLINE SITES"); - rd_indent(); - for (U64 i = 0; i < inline_site_count; ++i) { - rdi_print_inline_site(arena, out, indent, rdi, i, &inline_site_array[i]); - } - rd_unindent(); - rd_newline(); - } - if (opts & RD_Option_RdiNameMaps) { - Temp scratch = scratch_begin(&arena, 1); - U64 name_map_count = 0; - RDI_NameMap *name_map_array = rdi_table_from_name(rdi, NameMaps, &name_map_count); - rd_printf("# NAME MAPS"); - rd_indent(); - for (U64 i = 0; i < name_map_count; ++i) { - if (i > 0) { - rd_newline(); - } - RDI_ParsedNameMap name_map = {0}; - rdi_parsed_from_name_map(rdi, &name_map_array[i], &name_map); - rd_printf("name_map[%S]",rdi_string_from_name_map_kind(i)); - rd_indent(); - for (U64 bucket_idx = 0; bucket_idx < name_map.bucket_count; ++bucket_idx) { - if (name_map.buckets[bucket_idx].node_count == 0) { - continue; - } - rd_printf("bucket[%llu]:", bucket_idx); - rd_indent(); - RDI_NameMapNode *node_ptr = name_map.nodes + name_map.buckets[bucket_idx].first_node; - RDI_NameMapNode *node_opl = node_ptr + name_map.buckets[bucket_idx].node_count; - for (; node_ptr < node_opl; ++node_ptr) { - Temp temp = temp_begin(scratch.arena); - String8 str = str8_from_rdi_string_idx(rdi, node_ptr->string_idx); - String8 indices; - if (node_ptr->match_count == 1) { - indices = push_str8f(temp.arena, "%u", node_ptr->match_idx_or_idx_run_first); - } else { - U32 idx_count = 0; - U32 *idx_array = rdi_idx_run_from_first_count(rdi, node_ptr->match_idx_or_idx_run_first, node_ptr->match_count, &idx_count); - indices = rd_string_from_array_u32(temp.arena, idx_array, idx_count); - } - rd_printf("match \"%S\": %S", str, indices); - temp_end(temp); - } - rd_unindent(); - } - rd_unindent(); - } - rd_unindent(); - rd_newline(); - scratch_end(scratch); - } - if (opts & RD_Option_RdiStrings) { - U64 stridx_count = 0; - U32 *stridx_array = rdi_table_from_name(rdi, StringTable, &stridx_count); - rd_printf("# STRINGS"); - rd_indent(); - for (U64 i = 0; i < stridx_count; ++i) { - rd_printf("string[%llu]: \"%S\"", i, str8_from_rdi_string_idx(rdi, i)); - } - rd_unindent(); - rd_newline(); - } -} - internal String8 dw_string_from_reg_off(Arena *arena, Arch arch, U64 reg_idx, S64 reg_off) { @@ -1894,7 +698,7 @@ dw_string_list_from_expression(Arena *arena, String8 raw_data, U64 cu_base, U64 Rng1U64 value_range = rng_1u64(cursor, cursor + value_size); String8 value_data = str8_substr(raw_data, value_range); cursor += value_size; - + String8 value_str = rd_string_from_hex_u8(scratch.arena, value_data.str, value_data.size); op_value = push_str8f(scratch.arena, "{ %S }", value_str); } break; @@ -1995,7 +799,7 @@ dw_string_list_from_expression(Arena *arena, String8 raw_data, U64 cu_base, U64 cursor += str8_deserial_read_dwarf_uint(raw_data, cursor, format, &info_off); S64 ptr = 0; cursor += str8_deserial_read_sleb128(raw_data, cursor, &ptr); - + op_value = push_str8f(scratch.arena, ".debug_info+%#llx, ptr %llx", info_off, ptr); } break; case DW_ExprOp_Convert: @@ -2088,7 +892,7 @@ dw_string_list_from_expression(Arena *arena, String8 raw_data, U64 cu_base, U64 // no operands } break; } - + String8 opcode_str = dw_string_from_expr_op(scratch.arena, ver, ext, op); if (op_value.size == 0) { str8_list_pushf(arena, &result, "DW_OP_%S", opcode_str); @@ -2114,7 +918,7 @@ internal void dw_print_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) { Temp scratch = scratch_begin(&arena, 1); - + U64 address_bit_size = bit_size_from_arch(arch); U64 address_size = address_bit_size / 8; @@ -2136,7 +940,7 @@ dw_print_cfi_program(Arena *arena, String8List *out, String8 indent, String8 raw U64 address = 0; switch (arch) { case Arch_x64: cursor += dw_unwind_parse_pointer_x64(raw_data.str, rng_1u64(0,raw_data.size), ptr_ctx, cie->addr_encoding, cursor, &address); break; - + default: NotImplemented; break; } rd_printf("DW_CFA_set_loc: %#llx", address); @@ -2144,26 +948,26 @@ dw_print_cfi_program(Arena *arena, String8List *out, String8 indent, String8 raw case DW_CFA_AdvanceLoc1: { U8 delta = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &delta); - + rd_printf("DW_CFA_advance_loc1: %+u", delta * cie->code_align_factor); } break; case DW_CFA_AdvanceLoc2: { U16 delta = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &delta); - + rd_printf("DW_CFA_advance_loc2: %+u", delta * cie->code_align_factor); } break; case DW_CFA_AdvanceLoc4: { U32 delta = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &delta); - + rd_printf("DW_CFA_advance_loc4: %+u", delta * cie->code_align_factor); } break; case DW_CFA_OffsetExt: { U64 reg_idx = 0, reg_off = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, ®_idx); cursor += str8_deserial_read_uleb128(raw_data, cursor, ®_off); - + rd_printf("DW_CFA_offset_extended: %S register %llu (%S), offset %+llu", dw_string_from_reg_off(scratch.arena, arch, reg_idx, (S64)reg_off * cie->data_align_factor)); } break; @@ -2173,20 +977,20 @@ dw_print_cfi_program(Arena *arena, String8List *out, String8 indent, String8 raw case DW_CFA_Undefined: { U64 reg = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, ®); - + rd_printf("DW_CFA_undefined: %llu", reg); } break; case DW_CFA_SameValue: { U64 reg = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, ®); - + rd_printf("DW_CFA_same_value: %S", dw_string_from_register(scratch.arena, arch, reg)); } break; case DW_CFA_Register: { U64 reg_idx = 0, reg_off = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, ®_idx); cursor += str8_deserial_read_uleb128(raw_data, cursor, ®_off); - + rd_printf("DW_CFA_register: %S", dw_string_from_reg_off(scratch.arena, arch, reg_idx, reg_off)); } break; case DW_CFA_RememberState: { @@ -2199,13 +1003,13 @@ dw_print_cfi_program(Arena *arena, String8List *out, String8 indent, String8 raw U64 reg_idx = 0, reg_off = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, ®_idx); cursor += str8_deserial_read_uleb128(raw_data, cursor, ®_off); - + rd_printf("DW_CFA_def_cfa: %S", dw_string_from_reg_off(scratch.arena, arch, reg_idx, reg_off)); } break; case DW_CFA_DefCfaRegister: { U64 reg = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, ®); - + rd_printf("DW_CFA_register: %llu (%S)", reg, dw_string_from_register(arena, arch, reg)); @@ -2213,7 +1017,7 @@ dw_print_cfi_program(Arena *arena, String8List *out, String8 indent, String8 raw case DW_CFA_DefCfaOffset: { U64 offset = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, &offset); - + rd_printf("DW_CFA_def_cfa_offset: %llu", offset); } break; case DW_CFA_DefCfaExpr: { @@ -2241,7 +1045,7 @@ dw_print_cfi_program(Arena *arena, String8List *out, String8 indent, String8 raw S64 reg_off = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, ®_idx); cursor += str8_deserial_read_sleb128(raw_data, cursor, ®_off); - + rd_printf("DW_CFA_offset_ext_sf: %S", dw_string_from_reg_off(scratch.arena, arch, reg_idx, reg_off * cie->data_align_factor)); } break; case DW_CFA_DefCfaSf: { @@ -2249,14 +1053,14 @@ dw_print_cfi_program(Arena *arena, String8List *out, String8 indent, String8 raw S64 reg_off = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, ®_idx); cursor += str8_deserial_read_sleb128(raw_data, cursor, ®_off); - + rd_printf("DW_CFA_def_cfa_sf: %S", dw_string_from_reg_off(scratch.arena, arch, reg_idx, reg_off * cie->data_align_factor)); } break; case DW_CFA_ValOffset: { U64 val = 0, offset = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, &val); cursor += str8_deserial_read_uleb128(raw_data, cursor, &offset); - + rd_printf("DW_CFA_val_offset: value %llu, offset %+llu", val, offset); } break; case DW_CFA_ValOffsetSf: { @@ -2264,7 +1068,7 @@ dw_print_cfi_program(Arena *arena, String8List *out, String8 indent, String8 raw S64 offset = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, &val); cursor += str8_deserial_read_sleb128(raw_data, cursor, &offset); - + rd_printf("DW_CFA_val_offset_sf: value %llu, offset %+lld", val, offset); } break; case DW_CFA_ValExpr: { @@ -2274,7 +1078,7 @@ dw_print_cfi_program(Arena *arena, String8List *out, String8 indent, String8 raw cursor += str8_deserial_read_uleb128(raw_data, cursor, &block_size); String8 raw_expr = str8_substr(raw_data, rng_1u64(cursor, cursor + block_size)); cursor += block_size; - + rd_printf("DW_CFA_val_expr: value %+llu, expression %S", val, dw_format_expression_single_line(scratch.arena, raw_expr, 0, address_size, arch, ver, ext, format)); @@ -2286,7 +1090,7 @@ dw_print_cfi_program(Arena *arena, String8List *out, String8 indent, String8 raw U64 offset = 0; cursor += str8_deserial_read_uleb128(raw_data, cursor, &offset); S64 v = (S64)offset * cie->data_align_factor; - + rd_printf("DW_CFA_offset: %S", dw_string_from_reg_off(scratch.arena, arch, operand, v)); } break; case DW_CFA_Restore: { @@ -2344,17 +1148,17 @@ dw_print_eh_frame(Arena *arena, String8List *out, String8 indent, String8 raw_eh U64 length = 0; // doesn't include bytes for size cursor += dw_based_range_read_length(raw_eh_frame.str, rng_1u64(0,raw_eh_frame.size), cursor, &length); - + if (length == 0) { break; // encountered exit marker } - + U64 entry_start = cursor; U64 entry_end = cursor + length; - + U32 entry_id = 0; // always 4-bytes, even when length is encoded as 64-bit integer cursor += str8_deserial_read_struct(raw_eh_frame, cursor, &entry_id); - + // TODO: fix the freaking DW_EhPtrEnc_PCREL encoding. // it assumes "frame_base" points to the first byte of .eh_frame // but here base is start of ELF and we use range to select .eh_frame @@ -2383,11 +1187,11 @@ dw_print_eh_frame(Arena *arena, String8List *out, String8 indent, String8 raw_eh DW_FDEUnpacked fde = {0}; dw_unwind_parse_fde_x64(raw_eh_frame.str, rng_1u64(0,raw_eh_frame.size), ptr_ctx, &cie, 0, &fde); cfi_range = fde.cfi_range; - + // calc parent CIE offset AssertAlways(entry_start >= entry_id); U64 cie_offset = entry_start - entry_id; NotImplemented; // TODO: syms_safe_sub_u64(range.min + entry_start, entry_id); - + rd_printf("FDE @ %#llx, Length %u, Parent CIE @ %#llx", header_offset, length, cie_offset); rd_indent(); rd_printf("IP Range: %#llx-%#llx", fde.ip_voff_range.min, fde.ip_voff_range.max); @@ -2398,18 +1202,18 @@ dw_print_eh_frame(Arena *arena, String8List *out, String8 indent, String8 raw_eh // print CFI program rd_printf("CFI Program:"); rd_indent(); - + DW_Format format = DW_FormatFromSize(length); String8 raw_cfi = str8_substr(raw_eh_frame, cfi_range); dw_print_cfi_program(scratch.arena, out, indent, raw_cfi, &cie, ptr_ctx, arch, ver, ext, format); - + rd_unindent(); rd_newline(); - + // advance to next entry cursor = entry_end; } - + scratch_end(scratch); } @@ -2417,29 +1221,29 @@ internal void dw_print_debug_info(Arena *arena, String8List *out, String8 indent, DW_Input *input, DW_ListUnitInput lu_input, Arch arch, B32 relaxed) { Temp scratch = scratch_begin(&arena, 1); - + Rng1U64List cu_ranges = dw_unit_ranges_from_data(scratch.arena, input->sec[DW_Section_Info].data); - + if (cu_ranges.count > 0) { rd_printf("# %S", input->sec[DW_Section_Info].name); rd_indent(); } - + U64 comp_idx = 0; for (Rng1U64Node *cu_range_n = cu_ranges.first; cu_range_n != 0; cu_range_n = cu_range_n->next, ++comp_idx) { Temp comp_temp = temp_begin(scratch.arena); - + U64 cu_base = cu_range_n->v.min; Rng1U64 cu_range = cu_range_n->v; DW_CompUnit cu = dw_cu_from_info_off(comp_temp.arena, input, lu_input, cu_range.min, relaxed); - + String8 cu_dir = dw_string_from_attrib (input, &cu, cu.tag, DW_Attrib_CompDir ); String8 cu_name = dw_string_from_attrib (input, &cu, cu.tag, DW_Attrib_Name ); String8 stmt_list = dw_line_ptr_from_attrib(input, &cu, cu.tag, DW_Attrib_StmtList); - + DW_LineVMHeader line_vm = {0}; dw_read_line_vm_header(comp_temp.arena, stmt_list, 0, input, cu_dir, cu_name, cu.address_size, cu.str_offsets_lu, &line_vm); - + // print comp info rd_printf("Compilation Unit #%u", comp_idx); rd_indent(); @@ -2448,31 +1252,31 @@ dw_print_debug_info(Arena *arena, String8List *out, String8 indent, DW_Input *in rd_printf("Abbrev Offset: %#llx", cu.abbrev_off); rd_printf("Info Range: %#llx-%#llx (%M)", cu.info_range.min, cu.info_range.max, dim_1u64(cu.info_range)); rd_newline(); - + // prase tags U32 tag_depth = 0; for (U64 info_off = cu.first_tag_info_off; info_off < cu.info_range.max; ) { Temp tag_temp = temp_begin(scratch.arena); - + U64 tag_info_off = info_off; DW_Tag tag = {0}; info_off += dw_read_tag_cu(tag_temp.arena, input, &cu, tag_info_off, &tag); - + String8 tag_str = dw_string_from_tag_kind(tag_temp.arena, tag.kind); rd_printf("<%x><%llx> DW_Tag_%S (Abbrev Number: %llu)", tag_depth, tag_info_off, tag_str, tag.abbrev_id); rd_indent(); - + // parse attributes for (DW_AttribNode *attrib_n = tag.attribs.first; attrib_n != 0; attrib_n = attrib_n->next) { Temp attrib_temp = temp_begin(tag_temp.arena); - + DW_Attrib *attrib = &attrib_n->v; - + String8List attrib_list = {0}; - + // attribute .debug_info offset str8_list_pushf(attrib_temp.arena, &attrib_list, "<%llx> ", attrib->info_off); - + // attribute kind String8 attrib_kind_str = dw_string_from_attrib_kind(attrib_temp.arena, cu.version, cu.ext, attrib->attrib_kind); if (attrib_kind_str.size == 0) { @@ -2485,159 +1289,159 @@ dw_print_debug_info(Arena *arena, String8List *out, String8 indent, DW_Input *in } else { str8_list_pushf(attrib_temp.arena, &attrib_list, "DW_Attrib_%-20S ", attrib_kind_str); } - + // form kind String8 form_kind_str = dw_string_from_form_kind(scratch.arena, cu.version, attrib->form_kind); str8_list_pushf(attrib_temp.arena, &attrib_list, "DW_Form_%-15S", form_kind_str); - + DW_AttribClass value_class = dw_value_class_from_attrib(&cu, attrib); switch (value_class) { - default: { - str8_list_pushf(attrib_temp.arena, &attrib_list, "ERROR: unknown value class"); - } break; - case DW_AttribClass_Undefined: { - str8_list_pushf(attrib_temp.arena, &attrib_list, "ERROR: undefined value class"); - } break; - case DW_AttribClass_Address: { - U64 address = dw_address_from_attrib_ptr(input, &cu, attrib); - str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", address); - } break; - case DW_AttribClass_Block: { - String8 block = dw_block_from_attrib_ptr(input, &cu, attrib); - String8 block_str = rd_string_from_hex_u8(attrib_temp.arena, block.str, block.size); - str8_list_pushf(attrib_temp.arena, &attrib_list, "%S", block_str); - } break; - case DW_AttribClass_Const: { - U64 constant = dw_const_u64_from_attrib_ptr(input, &cu, attrib); - str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", constant); - } break; - case DW_AttribClass_ExprLoc: { - String8 exprloc = dw_exprloc_from_attrib_ptr(input, &cu, attrib); - String8 exprloc_str = dw_format_expression_single_line(attrib_temp.arena, exprloc, cu_base, cu.address_size, arch, cu.version, cu.ext, cu.format); - str8_list_push(attrib_temp.arena, &attrib_list, exprloc_str); - } break; - case DW_AttribClass_Flag: { - B32 flag = dw_flag_from_attrib_ptr(input, &cu, attrib); - str8_list_pushf(attrib_temp.arena, &attrib_list, "%llu (%s)", flag, flag == 0 ? "false" : "true"); - } break; - case DW_AttribClass_LinePtr: { - if (attrib->form_kind == DW_Form_SecOffset) { - str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); - } else { - str8_list_pushf(attrib_temp.arena, &attrib_list, "ERROR: unexpected form %S", dw_string_from_form_kind(attrib_temp.arena, cu.version, attrib->form_kind)); - } - } break; - case DW_AttribClass_LocListPtr: { - if (attrib->form_kind == DW_Form_SecOffset) { - str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); - } else { - str8_list_pushf(attrib_temp.arena, &attrib_list, "ERROR: unexpected form %S", dw_string_from_form_kind(attrib_temp.arena, cu.version, attrib->form_kind)); - } - } break; - case DW_AttribClass_MacPtr: { - if (attrib->form_kind == DW_Form_SecOffset) { - str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); - } else { - str8_list_pushf(attrib_temp.arena, &attrib_list, "\?\?\?"); - } - } break; - case DW_AttribClass_RngListPtr: { - if (attrib->form_kind == DW_Form_SecOffset) { - str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); - } else { - str8_list_pushf(attrib_temp.arena, &attrib_list, "\?\?\?"); - } - } break; - case DW_AttribClass_RngList: { - if (attrib->form_kind == DW_Form_SecOffset) { - str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); - } else { - str8_list_pushf(attrib_temp.arena, &attrib_list, "\?\?\?"); - } - } break; - case DW_AttribClass_Reference: { - if (attrib->form_kind == DW_Form_Ref1 || - attrib->form_kind == DW_Form_Ref2 || - attrib->form_kind == DW_Form_Ref4 || - attrib->form_kind == DW_Form_Ref8 || - attrib->form_kind == DW_Form_RefUData) { - U64 info_off = cu.info_range.min + attrib->form.ref; - str8_list_pushf(attrib_temp.arena, &attrib_list, "<%llx>", info_off); - if (!contains_1u64(cu.info_range, attrib->form.ref)) { - str8_list_pushf(attrib_temp.arena, &attrib_list, "(ERROR: out of bounds reference)"); + default: { + str8_list_pushf(attrib_temp.arena, &attrib_list, "ERROR: unknown value class"); + } break; + case DW_AttribClass_Undefined: { + str8_list_pushf(attrib_temp.arena, &attrib_list, "ERROR: undefined value class"); + } break; + case DW_AttribClass_Address: { + U64 address = dw_address_from_attrib_ptr(input, &cu, attrib); + str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", address); + } break; + case DW_AttribClass_Block: { + String8 block = dw_block_from_attrib_ptr(input, &cu, attrib); + String8 block_str = rd_string_from_hex_u8(attrib_temp.arena, block.str, block.size); + str8_list_pushf(attrib_temp.arena, &attrib_list, "%S", block_str); + } break; + case DW_AttribClass_Const: { + U64 constant = dw_const_u64_from_attrib_ptr(input, &cu, attrib); + str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", constant); + } break; + case DW_AttribClass_ExprLoc: { + String8 exprloc = dw_exprloc_from_attrib_ptr(input, &cu, attrib); + String8 exprloc_str = dw_format_expression_single_line(attrib_temp.arena, exprloc, cu_base, cu.address_size, arch, cu.version, cu.ext, cu.format); + str8_list_push(attrib_temp.arena, &attrib_list, exprloc_str); + } break; + case DW_AttribClass_Flag: { + B32 flag = dw_flag_from_attrib_ptr(input, &cu, attrib); + str8_list_pushf(attrib_temp.arena, &attrib_list, "%llu (%s)", flag, flag == 0 ? "false" : "true"); + } break; + case DW_AttribClass_LinePtr: { + if (attrib->form_kind == DW_Form_SecOffset) { + str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); + } else { + str8_list_pushf(attrib_temp.arena, &attrib_list, "ERROR: unexpected form %S", dw_string_from_form_kind(attrib_temp.arena, cu.version, attrib->form_kind)); } - } else { - str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.ref); - } - } break; - case DW_AttribClass_String: { - if (attrib->form_kind == DW_Form_Strp) { - str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); - } - String8 string = dw_string_from_attrib_ptr(input, &cu, attrib); - str8_list_pushf(attrib_temp.arena, &attrib_list, "(%S)", string); - } break; - case DW_AttribClass_StrOffsetsPtr: { - if (attrib->form_kind == DW_Form_SecOffset) { - str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); - } else { - str8_list_pushf(attrib_temp.arena, &attrib_list, "ERROR: unexpected form %S", dw_string_from_form_kind(attrib_temp.arena, cu.version, attrib->form_kind)); - } - } break; - case DW_AttribClass_AddrPtr: { - if (attrib->form_kind == DW_Form_SecOffset) { - str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); - } else { - str8_list_pushf(attrib_temp.arena, &attrib_list, "ERROR: unexpected form %S", dw_string_from_form_kind(attrib_temp.arena, cu.version, attrib->form_kind)); - } - } break; + } break; + case DW_AttribClass_LocListPtr: { + if (attrib->form_kind == DW_Form_SecOffset) { + str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); + } else { + str8_list_pushf(attrib_temp.arena, &attrib_list, "ERROR: unexpected form %S", dw_string_from_form_kind(attrib_temp.arena, cu.version, attrib->form_kind)); + } + } break; + case DW_AttribClass_MacPtr: { + if (attrib->form_kind == DW_Form_SecOffset) { + str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); + } else { + str8_list_pushf(attrib_temp.arena, &attrib_list, "\?\?\?"); + } + } break; + case DW_AttribClass_RngListPtr: { + if (attrib->form_kind == DW_Form_SecOffset) { + str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); + } else { + str8_list_pushf(attrib_temp.arena, &attrib_list, "\?\?\?"); + } + } break; + case DW_AttribClass_RngList: { + if (attrib->form_kind == DW_Form_SecOffset) { + str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); + } else { + str8_list_pushf(attrib_temp.arena, &attrib_list, "\?\?\?"); + } + } break; + case DW_AttribClass_Reference: { + if (attrib->form_kind == DW_Form_Ref1 || + attrib->form_kind == DW_Form_Ref2 || + attrib->form_kind == DW_Form_Ref4 || + attrib->form_kind == DW_Form_Ref8 || + attrib->form_kind == DW_Form_RefUData) { + U64 info_off = cu.info_range.min + attrib->form.ref; + str8_list_pushf(attrib_temp.arena, &attrib_list, "<%llx>", info_off); + if (!contains_1u64(cu.info_range, attrib->form.ref)) { + str8_list_pushf(attrib_temp.arena, &attrib_list, "(ERROR: out of bounds reference)"); + } + } else { + str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.ref); + } + } break; + case DW_AttribClass_String: { + if (attrib->form_kind == DW_Form_Strp) { + str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); + } + String8 string = dw_string_from_attrib_ptr(input, &cu, attrib); + str8_list_pushf(attrib_temp.arena, &attrib_list, "(%S)", string); + } break; + case DW_AttribClass_StrOffsetsPtr: { + if (attrib->form_kind == DW_Form_SecOffset) { + str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); + } else { + str8_list_pushf(attrib_temp.arena, &attrib_list, "ERROR: unexpected form %S", dw_string_from_form_kind(attrib_temp.arena, cu.version, attrib->form_kind)); + } + } break; + case DW_AttribClass_AddrPtr: { + if (attrib->form_kind == DW_Form_SecOffset) { + str8_list_pushf(attrib_temp.arena, &attrib_list, "%#llx", attrib->form.sec_offset); + } else { + str8_list_pushf(attrib_temp.arena, &attrib_list, "ERROR: unexpected form %S", dw_string_from_form_kind(attrib_temp.arena, cu.version, attrib->form_kind)); + } + } break; } - + String8 attrib_str = {0}; switch (attrib->attrib_kind) { - case DW_Attrib_Language: { - DW_Language lang = dw_const_u64_from_attrib_ptr(input, &cu, attrib); - attrib_str = dw_string_from_language(attrib_temp.arena, lang); - } break; - case DW_Attrib_DeclFile: { - U64 file_idx = dw_const_u64_from_attrib_ptr(input, &cu, attrib); - DW_LineFile *file = dw_file_from_attrib_ptr(&cu, &line_vm, attrib); - attrib_str = str8_lit("\?\?\?"); - if (file) { - attrib_str = dw_path_from_file(attrib_temp.arena, &line_vm, file); - } - } break; - case DW_Attrib_DeclLine: { - U64 line = dw_const_u64_from_attrib_ptr(input, &cu, attrib); - attrib_str = push_str8f(attrib_temp.arena, "%llu", line); - } break; - case DW_Attrib_Inline: { - DW_InlKind inl = dw_const_u64_from_attrib_ptr(input, &cu, attrib); - attrib_str = dw_string_from_inl(attrib_temp.arena, inl); - } break; - case DW_Attrib_Accessibility: { - DW_AccessKind access = dw_const_u64_from_attrib_ptr(input, &cu, attrib); - attrib_str = dw_string_from_access_kind(attrib_temp.arena, access); - } break; - case DW_Attrib_CallingConvention: { - DW_CallingConventionKind calling_convetion = dw_const_u64_from_attrib_ptr(input, &cu, attrib); - attrib_str = dw_string_from_calling_convetion(attrib_temp.arena, calling_convetion); - } break; - case DW_Attrib_Encoding: { - DW_ATE encoding = dw_const_u64_from_attrib_ptr(input, &cu, attrib); - attrib_str = dw_string_from_attrib_type_encoding(attrib_temp.arena, encoding); - } break; + case DW_Attrib_Language: { + DW_Language lang = dw_const_u64_from_attrib_ptr(input, &cu, attrib); + attrib_str = dw_string_from_language(attrib_temp.arena, lang); + } break; + case DW_Attrib_DeclFile: { + U64 file_idx = dw_const_u64_from_attrib_ptr(input, &cu, attrib); + DW_LineFile *file = dw_file_from_attrib_ptr(&cu, &line_vm, attrib); + attrib_str = str8_lit("\?\?\?"); + if (file) { + attrib_str = dw_path_from_file(attrib_temp.arena, &line_vm, file); + } + } break; + case DW_Attrib_DeclLine: { + U64 line = dw_const_u64_from_attrib_ptr(input, &cu, attrib); + attrib_str = push_str8f(attrib_temp.arena, "%llu", line); + } break; + case DW_Attrib_Inline: { + DW_InlKind inl = dw_const_u64_from_attrib_ptr(input, &cu, attrib); + attrib_str = dw_string_from_inl(attrib_temp.arena, inl); + } break; + case DW_Attrib_Accessibility: { + DW_AccessKind access = dw_const_u64_from_attrib_ptr(input, &cu, attrib); + attrib_str = dw_string_from_access_kind(attrib_temp.arena, access); + } break; + case DW_Attrib_CallingConvention: { + DW_CallingConventionKind calling_convetion = dw_const_u64_from_attrib_ptr(input, &cu, attrib); + attrib_str = dw_string_from_calling_convetion(attrib_temp.arena, calling_convetion); + } break; + case DW_Attrib_Encoding: { + DW_ATE encoding = dw_const_u64_from_attrib_ptr(input, &cu, attrib); + attrib_str = dw_string_from_attrib_type_encoding(attrib_temp.arena, encoding); + } break; } - + if (attrib_str.size) { str8_list_pushf(attrib_temp.arena, &attrib_list, "(%S)", attrib_str); } String8 print = str8_list_join(attrib_temp.arena, &attrib_list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", print); - + temp_end(attrib_temp); } - + B32 is_ender_tag = tag.abbrev_id == 0; if (tag.has_children) { if (is_ender_tag) { @@ -2654,20 +1458,20 @@ dw_print_debug_info(Arena *arena, String8List *out, String8 indent, DW_Input *in tag_depth -= 1; } } - + rd_unindent(); temp_end(tag_temp); } temp_end(comp_temp); - + rd_unindent(); rd_newline(); } - + if (cu_ranges.count > 0) { rd_unindent(); } - + scratch_end(scratch); } @@ -2675,37 +1479,37 @@ internal void dw_print_debug_abbrev(Arena *arena, String8List *out, String8 indent, DW_Input *input) { Temp scratch = scratch_begin(&arena, 1); - + DW_Section abbrev = input->sec[DW_Section_Abbrev]; String8 raw_abbrev = abbrev.data; - + if (raw_abbrev.size) { rd_printf("# %S", input->sec[DW_Section_Abbrev].name); rd_indent(); } - + for (U64 cursor = 0; cursor < raw_abbrev.size; ) { U64 id_off = cursor; - + U64 id = 0; cursor += str8_deserial_read_uleb128(raw_abbrev, cursor, &id); - + if (id == 0) { continue; // end of abbrev data for CU } - + Temp temp = temp_begin(scratch.arena); - + U64 tag = 0; U8 has_children = 0; cursor += str8_deserial_read_uleb128(raw_abbrev, cursor, &tag); cursor += str8_deserial_read_struct(raw_abbrev, cursor, &has_children); - + rd_printf("<%llx> %llu DW_Tag_%S %s", id_off, id, dw_string_from_tag_kind(temp.arena, tag), has_children ? "[has children]" : "[no children]"); rd_indent(); for (;;) { U64 attrib_off = cursor; - + U64 attrib_id = 0, form_id = 0; cursor += str8_deserial_read_uleb128(raw_abbrev, cursor, &attrib_id); cursor += str8_deserial_read_uleb128(raw_abbrev, cursor, &form_id); @@ -2717,14 +1521,14 @@ dw_print_debug_abbrev(Arena *arena, String8List *out, String8 indent, DW_Input * rd_printf("<%llx> DW_Attrib_%-20S DW_Form_%S", attrib_off, attrib_str, form_str); } rd_unindent(); - + temp_end(temp); } - + if (raw_abbrev.size) { rd_unindent(); } - + scratch_end(scratch); } @@ -2732,24 +1536,24 @@ internal void dw_print_debug_line(Arena *arena, String8List *out, String8 indent, DW_Input *input, DW_ListUnitInput lu_input, B32 relaxed) { Temp scratch = scratch_begin(&arena, 1); - + rd_printf("# .debug_line"); - + Rng1U64List unit_ranges = dw_unit_ranges_from_data(scratch.arena, input->sec[DW_Section_Line].data); for (Rng1U64Node *unit_range_n = unit_ranges.first; unit_range_n != 0; unit_range_n = unit_range_n->next) { Temp unit_temp = temp_begin(scratch.arena); - + String8 unit_data = str8_substr(input->sec[DW_Section_Line].data, unit_range_n->v); String8 cu_dir = {0}; String8 cu_name = {0}; DW_ListUnit cu_str_offsets = {0}; DW_LineVMHeader line_vm = {0}; U64 line_vm_size = dw_read_line_vm_header(unit_temp.arena, unit_data, 0, input, cu_dir, cu_name, line_vm.address_size, &cu_str_offsets, &line_vm); - + if (line_vm_size == 0) { continue; } - + { rd_printf("Header:", line_vm_size); rd_indent(); @@ -2771,7 +1575,7 @@ dw_print_debug_line(Arena *arena, String8List *out, String8 indent, DW_Input *in rd_unindent(); rd_newline(); } - + { rd_printf("Directory Table:"); rd_indent(); @@ -2782,7 +1586,7 @@ dw_print_debug_line(Arena *arena, String8List *out, String8 indent, DW_Input *in rd_unindent(); rd_newline(); } - + { rd_printf("File Table:"); rd_indent(); @@ -2801,207 +1605,207 @@ dw_print_debug_line(Arena *arena, String8List *out, String8 indent, DW_Input *in rd_unindent(); rd_newline(); } - + { rd_printf("Opcodes:"); rd_indent(); - + String8 opcodes = str8_skip(unit_data, line_vm_size); B32 end_of_seq = 0; DW_LineVMState vm_state = {0}; dw_line_vm_reset(&vm_state, line_vm.default_is_stmt); - + for (U64 cursor = 0; cursor < opcodes.size; ) { Temp opcode_temp = temp_begin(unit_temp.arena); - + String8List opcode_fmt = {0}; - + // opcode offset str8_list_pushf(opcode_temp.arena, &opcode_fmt, "[%08llx]", cursor); - + // parse opcode U8 opcode = 0; cursor += str8_deserial_read_struct(opcodes, cursor, &opcode); - + // push opcode id String8 opcode_str = dw_string_from_std_opcode(opcode_temp.arena, opcode); str8_list_push(arena, &opcode_fmt, opcode_str); // format operands switch (opcode) { - default: { - if (opcode >= line_vm.opcode_base) { - U32 adjusted_opcode = 0; - U32 op_advance = 0; - S32 line_advance = 0; - U64 addr_advance = 0; - if (line_vm.line_range > 0 && line_vm.max_ops_for_inst > 0) { - adjusted_opcode = (U32)(opcode - line_vm.opcode_base); - op_advance = adjusted_opcode / line_vm.line_range; - line_advance = (S32)line_vm.line_base + ((S32)adjusted_opcode) % (S32)line_vm.line_range; - addr_advance = line_vm.min_inst_len * ((vm_state.op_index+op_advance) / line_vm.max_ops_for_inst); + default: { + if (opcode >= line_vm.opcode_base) { + U32 adjusted_opcode = 0; + U32 op_advance = 0; + S32 line_advance = 0; + U64 addr_advance = 0; + if (line_vm.line_range > 0 && line_vm.max_ops_for_inst > 0) { + adjusted_opcode = (U32)(opcode - line_vm.opcode_base); + op_advance = adjusted_opcode / line_vm.line_range; + line_advance = (S32)line_vm.line_base + ((S32)adjusted_opcode) % (S32)line_vm.line_range; + addr_advance = line_vm.min_inst_len * ((vm_state.op_index+op_advance) / line_vm.max_ops_for_inst); + } + + vm_state.address += addr_advance; + vm_state.op_index = (vm_state.op_index + op_advance) % line_vm.max_ops_for_inst; + vm_state.line = (U32)((S32)vm_state.line + line_advance); + vm_state.basic_block = 0; + vm_state.prologue_end = 0; + vm_state.epilogue_begin = 0; + vm_state.discriminator = 0; + + end_of_seq = 0; + + str8_list_pushf(opcode_temp.arena, &opcode_fmt, "advance line by %d, advance address by %lld", line_advance, addr_advance); + } else { + if (opcode > 0 && opcode <= line_vm.num_opcode_lens) { + str8_list_pushf(opcode_temp.arena, &opcode_fmt, "skip operands:"); + U64 num_operands = line_vm.opcode_lens[opcode - 1]; + for (U8 i = 0; i < num_operands; i += 1){ + U64 operand = 0; + cursor += str8_deserial_read_uleb128(opcodes, cursor, &operand); + str8_list_pushf(opcode_temp.arena, &opcode_fmt, " %llx", operand); + } + } } - - vm_state.address += addr_advance; - vm_state.op_index = (vm_state.op_index + op_advance) % line_vm.max_ops_for_inst; - vm_state.line = (U32)((S32)vm_state.line + line_advance); + }break; + + case DW_StdOpcode_Copy: { + str8_list_pushf(opcode_temp.arena, &opcode_fmt, "Line = %u, Column = %u, Address = %#llx", vm_state.line, vm_state.column, vm_state.address); + end_of_seq = 0; + vm_state.discriminator = 0; vm_state.basic_block = 0; vm_state.prologue_end = 0; vm_state.epilogue_begin = 0; - vm_state.discriminator = 0; - - end_of_seq = 0; - - str8_list_pushf(opcode_temp.arena, &opcode_fmt, "advance line by %d, advance address by %lld", line_advance, addr_advance); - } else { - if (opcode > 0 && opcode <= line_vm.num_opcode_lens) { - str8_list_pushf(opcode_temp.arena, &opcode_fmt, "skip operands:"); - U64 num_operands = line_vm.opcode_lens[opcode - 1]; - for (U8 i = 0; i < num_operands; i += 1){ - U64 operand = 0; - cursor += str8_deserial_read_uleb128(opcodes, cursor, &operand); - str8_list_pushf(opcode_temp.arena, &opcode_fmt, " %llx", operand); - } - } - } - }break; - - case DW_StdOpcode_Copy: { - str8_list_pushf(opcode_temp.arena, &opcode_fmt, "Line = %u, Column = %u, Address = %#llx", vm_state.line, vm_state.column, vm_state.address); - end_of_seq = 0; - vm_state.discriminator = 0; - vm_state.basic_block = 0; - vm_state.prologue_end = 0; - vm_state.epilogue_begin = 0; - } break; - case DW_StdOpcode_AdvancePc: { - U64 advance = 0; - cursor += str8_deserial_read_uleb128(opcodes, cursor, &advance); - dw_line_vm_advance(&vm_state, advance, line_vm.min_inst_len, line_vm.max_ops_for_inst); - str8_list_pushf(opcode_temp.arena, &opcode_fmt, "advance %#llx ; current address %#llx", advance, vm_state.address); - } break; - - case DW_StdOpcode_AdvanceLine: { - S64 advance = 0; - cursor += str8_deserial_read_sleb128(opcodes, cursor, &advance); - vm_state.line += advance; - str8_list_pushf(opcode_temp.arena, &opcode_fmt, "advance %lld ; current line %u", advance, vm_state.line); - } break; - - case DW_StdOpcode_SetFile: { - U64 file_idx = 0; - cursor += str8_deserial_read_uleb128(opcodes, cursor, &file_idx); - vm_state.file_index = file_idx; - - String8 path = dw_path_from_file_idx(opcode_temp.arena, &line_vm, file_idx); - str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%llu \"%S\"", file_idx, path); - } break; - - case DW_StdOpcode_SetColumn: { - U64 column = 0; - cursor += str8_deserial_read_uleb128(opcodes, cursor, &column); - vm_state.column = column; - str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%llu", column); - } break; - - case DW_StdOpcode_NegateStmt: { - vm_state.is_stmt = !vm_state.is_stmt; - str8_list_pushf(opcode_temp.arena, &opcode_fmt, "is_stmt = %u", vm_state.is_stmt); - } break; - - case DW_StdOpcode_SetBasicBlock: { - vm_state.basic_block = 1; - } break; - - case DW_StdOpcode_ConstAddPc: { - U64 advance = (0xffu - line_vm.opcode_base)/line_vm.line_range; - dw_line_vm_advance(&vm_state, advance, line_vm.min_inst_len, line_vm.max_ops_for_inst); - str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%lld ; address %#llx", advance, vm_state.address); - }break; - - case DW_StdOpcode_FixedAdvancePc: { - U64 operand = 0; - cursor += str8_deserial_read_struct(opcodes, cursor, &operand); - vm_state.address += operand; - vm_state.op_index = 0; - str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%llu", operand); - } break; - - case DW_StdOpcode_SetPrologueEnd: { - vm_state.prologue_end = 1; - } break; - - case DW_StdOpcode_SetEpilogueBegin: { - vm_state.epilogue_begin = 1; - } break; - - case DW_StdOpcode_SetIsa: { - U64 v = 0; - cursor += str8_deserial_read_uleb128(opcodes, cursor, &v); - vm_state.isa = v; - str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%llu", v); - } break; - - case DW_StdOpcode_ExtendedOpcode: { - U64 length = 0; - U8 ext_opcode = 0; - - cursor += str8_deserial_read_uleb128(opcodes, cursor, &length); - U64 opcode_end = cursor + length; - - cursor += str8_deserial_read_struct(opcodes, cursor, &ext_opcode); - - String8 ext_opcode_str = dw_string_from_ext_opcode(opcode_temp.arena, ext_opcode); - //str8_list_pushf(opcode_temp.arena, &opcode_fmt, "length: %u", length); - str8_list_push(opcode_temp.arena, &opcode_fmt, ext_opcode_str); - switch (ext_opcode) { - case DW_ExtOpcode_EndSequence: { - vm_state.end_sequence = 1; - dw_line_vm_reset(&vm_state, line_vm.default_is_stmt); - end_of_seq = 1; } break; - case DW_ExtOpcode_SetAddress: { - U64 address = 0; - cursor += str8_deserial_read(opcodes, cursor, &address, line_vm.address_size, line_vm.address_size); - vm_state.address = address; - vm_state.op_index = 0; - str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%#llx", address); + case DW_StdOpcode_AdvancePc: { + U64 advance = 0; + cursor += str8_deserial_read_uleb128(opcodes, cursor, &advance); + dw_line_vm_advance(&vm_state, advance, line_vm.min_inst_len, line_vm.max_ops_for_inst); + str8_list_pushf(opcode_temp.arena, &opcode_fmt, "advance %#llx ; current address %#llx", advance, vm_state.address); } break; - case DW_ExtOpcode_DefineFile: { - String8 file_name = {0}; - cursor += str8_deserial_read_cstr(opcodes, cursor, &file_name); - - U64 dir_idx = 0, modify_time = 0, file_size = 0; - cursor += str8_deserial_read_uleb128(opcodes, cursor, &dir_idx); - cursor += str8_deserial_read_uleb128(opcodes, cursor, &modify_time); - cursor += str8_deserial_read_uleb128(opcodes, cursor, &file_size); - str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%S Dir: %llu, Time: %llu, Size: %llu", file_name, dir_idx, modify_time, file_size); + + case DW_StdOpcode_AdvanceLine: { + S64 advance = 0; + cursor += str8_deserial_read_sleb128(opcodes, cursor, &advance); + vm_state.line += advance; + str8_list_pushf(opcode_temp.arena, &opcode_fmt, "advance %lld ; current line %u", advance, vm_state.line); } break; - case DW_ExtOpcode_SetDiscriminator: { + + case DW_StdOpcode_SetFile: { + U64 file_idx = 0; + cursor += str8_deserial_read_uleb128(opcodes, cursor, &file_idx); + vm_state.file_index = file_idx; + + String8 path = dw_path_from_file_idx(opcode_temp.arena, &line_vm, file_idx); + str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%llu \"%S\"", file_idx, path); + } break; + + case DW_StdOpcode_SetColumn: { + U64 column = 0; + cursor += str8_deserial_read_uleb128(opcodes, cursor, &column); + vm_state.column = column; + str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%llu", column); + } break; + + case DW_StdOpcode_NegateStmt: { + vm_state.is_stmt = !vm_state.is_stmt; + str8_list_pushf(opcode_temp.arena, &opcode_fmt, "is_stmt = %u", vm_state.is_stmt); + } break; + + case DW_StdOpcode_SetBasicBlock: { + vm_state.basic_block = 1; + } break; + + case DW_StdOpcode_ConstAddPc: { + U64 advance = (0xffu - line_vm.opcode_base)/line_vm.line_range; + dw_line_vm_advance(&vm_state, advance, line_vm.min_inst_len, line_vm.max_ops_for_inst); + str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%lld ; address %#llx", advance, vm_state.address); + }break; + + case DW_StdOpcode_FixedAdvancePc: { + U64 operand = 0; + cursor += str8_deserial_read_struct(opcodes, cursor, &operand); + vm_state.address += operand; + vm_state.op_index = 0; + str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%llu", operand); + } break; + + case DW_StdOpcode_SetPrologueEnd: { + vm_state.prologue_end = 1; + } break; + + case DW_StdOpcode_SetEpilogueBegin: { + vm_state.epilogue_begin = 1; + } break; + + case DW_StdOpcode_SetIsa: { U64 v = 0; cursor += str8_deserial_read_uleb128(opcodes, cursor, &v); - vm_state.discriminator = v; - str8_list_pushf(arena, &opcode_fmt, "%llu", v); + vm_state.isa = v; + str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%llu", v); + } break; + + case DW_StdOpcode_ExtendedOpcode: { + U64 length = 0; + U8 ext_opcode = 0; + + cursor += str8_deserial_read_uleb128(opcodes, cursor, &length); + U64 opcode_end = cursor + length; + + cursor += str8_deserial_read_struct(opcodes, cursor, &ext_opcode); + + String8 ext_opcode_str = dw_string_from_ext_opcode(opcode_temp.arena, ext_opcode); + //str8_list_pushf(opcode_temp.arena, &opcode_fmt, "length: %u", length); + str8_list_push(opcode_temp.arena, &opcode_fmt, ext_opcode_str); + switch (ext_opcode) { + case DW_ExtOpcode_EndSequence: { + vm_state.end_sequence = 1; + dw_line_vm_reset(&vm_state, line_vm.default_is_stmt); + end_of_seq = 1; + } break; + case DW_ExtOpcode_SetAddress: { + U64 address = 0; + cursor += str8_deserial_read(opcodes, cursor, &address, line_vm.address_size, line_vm.address_size); + vm_state.address = address; + vm_state.op_index = 0; + str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%#llx", address); + } break; + case DW_ExtOpcode_DefineFile: { + String8 file_name = {0}; + cursor += str8_deserial_read_cstr(opcodes, cursor, &file_name); + + U64 dir_idx = 0, modify_time = 0, file_size = 0; + cursor += str8_deserial_read_uleb128(opcodes, cursor, &dir_idx); + cursor += str8_deserial_read_uleb128(opcodes, cursor, &modify_time); + cursor += str8_deserial_read_uleb128(opcodes, cursor, &file_size); + str8_list_pushf(opcode_temp.arena, &opcode_fmt, "%S Dir: %llu, Time: %llu, Size: %llu", file_name, dir_idx, modify_time, file_size); + } break; + case DW_ExtOpcode_SetDiscriminator: { + U64 v = 0; + cursor += str8_deserial_read_uleb128(opcodes, cursor, &v); + vm_state.discriminator = v; + str8_list_pushf(arena, &opcode_fmt, "%llu", v); + } break; + } + + cursor = opcode_end; } break; - } - - cursor = opcode_end; - } break; } - + String8 string = str8_list_join(opcode_temp.arena, &opcode_fmt, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", string); - + temp_end(opcode_temp); } - + rd_unindent(); rd_newline(); } - + temp_end(unit_temp); } - + scratch_end(scratch); } @@ -3020,25 +1824,25 @@ dw_print_debug_str(Arena *arena, String8List *out, String8 indent, DW_Input *inp } internal void -dw_print_debug_loc(Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ImageType image_type, B32 relaxed) +dw_print_debug_loc(Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ExecutableImageKind image_type, B32 relaxed) { #if 0 DW_Section info = input->sec[DW_Section_Info]; DW_Section loc = input->sec[DW_Section_Loc]; - + if (loc.data.size == 0) { return; } - + Temp scratch = scratch_begin(&arena, 1); - + rd_printf("# %S", input->sec[DW_Section_Loc].name); rd_indent(); - + // TODO: warn about overlaps in ranges - + Rng1U64List cu_range_list = dw_comp_unit_ranges_from_info(scratch.arena, info); - + // parse debug_info for attributes with LOCLIST and store .debug_loc offsets U64List *loc_lists = push_array(scratch.arena, U64List, cu_range_list.count); U64 *address_sizes = push_array(scratch.arena, U64, cu_range_list.count); @@ -3046,26 +1850,26 @@ dw_print_debug_loc(Arena *arena, String8List *out, String8 indent, DW_Input *inp U64 *cu_bases = push_array(scratch.arena, U64, cu_range_list.count); DW_Version *ver_arr = push_array(scratch.arena, DW_Version, cu_range_list.count); DW_Ext *ext_arr = push_array(scratch.arena, DW_Ext, cu_range_list.count); - + U64 comp_idx = 0; for (Rng1U64Node *cu_range_n = cu_range_list.first; cu_range_n != 0; cu_range_n = cu_range_n->next, ++comp_idx) { Temp comp_temp = temp_begin(arena); - + Rng1U64 cu_range = cu_range_n->v; DW_CompUnit cu = dw_comp_unit_from_info_off(comp_temp.arena, input, cu_range.min, relaxed); - + // store info about comp unit address_sizes[comp_idx] = cu.address_size; address_bases[comp_idx] = cu.base_addr; ver_arr[comp_idx] = cu.version; cu_bases[comp_idx] = cu_range_n->v.min; - + // parse tags for (U64 info_off = cu.tags_range.min; info_off < cu.tags_range.max; /* empty */) { Temp tag_temp = temp_begin(scratch.arena); - + DW_Tag tag = dw_tag_from_info_offset_cu(tag_temp.arena, input, &cu, ext_arr[comp_idx], info_off); - + // parse attribs for (DW_AttribNode *attrib_node = tag.attribs.first; attrib_node != 0; attrib_node = attrib_node->next) { DW_Attrib *attrib = &attrib_node->v; @@ -3077,50 +1881,50 @@ dw_print_debug_loc(Arena *arena, String8List *out, String8 indent, DW_Input *inp // TODO: support for section indexing } } - + // advance to next tag info_off = tag.next_info_off; - + temp_end(tag_temp); } - + temp_end(comp_temp); } - + void *base = dw_base_from_sec(input, DW_Section_Loc); Rng1U64 range = dw_range_from_sec(input, DW_Section_Loc); - + rd_printf(".debug_loc"); rd_indent(); rd_printf("%-8s %-8s %-8s %s", "Offset", "Min", "Max", "Expression"); for (U32 comp_idx = 0; comp_idx < cu_range_list.count; ++comp_idx) { Temp locs_temp = temp_begin(scratch.arena); - + DW_Version ver = ver_arr[comp_idx]; DW_Ext ext = ext_arr[comp_idx]; - + U64Array locs = u64_array_from_list(locs_temp.arena, &loc_lists[comp_idx]); u64_array_sort(locs.count, locs.v); - + U64Array locs_set = remove_duplicates_u64_array(locs_temp.arena, locs); U64 address_size = address_sizes[comp_idx]; U64 base_selector = (address_size == 8) ? max_U64 : max_U32; - + for (U64 loc_idx = 0; loc_idx < locs_set.count; ++loc_idx) { U64 base_address = address_bases[comp_idx]; for (U64 cursor = locs_set.v[loc_idx]; cursor < dim_1u64(range); /* empty */) { Temp range_temp = temp_begin(arena); - + String8List list = {0}; - + // offset str8_list_pushf(range_temp.arena, &list, "%08llx", cursor); - + // parse entry U64 v0 = 0, v1 = 0; cursor += dw_based_range_read(base, range, cursor, address_size, &v0); cursor += dw_based_range_read(base, range, cursor, address_size, &v1); - + B32 is_list_end = v0 == 0 && v1 == 0; if (is_list_end) { str8_list_pushf(range_temp.arena, &list, ""); @@ -3131,77 +1935,77 @@ dw_print_debug_loc(Arena *arena, String8List *out, String8 indent, DW_Input *inp cursor += dw_based_range_read_struct(base, range, cursor, &expr_size); Rng1U64 expr_range = rng_1u64(range.min+cursor, range.min+cursor+expr_size); cursor += expr_size; - + // format dwarf expression B32 is_dwarf64 = (address_size == 8); String8 raw_expr = str8((U8*)base+expr_range.min, dim_1u64(expr_range)); String8 expression = dw_format_expression_single_line(range_temp.arena, raw_expr, cu_bases[comp_idx], address_size, arch, ver, ext, input->sec[DW_Section_Loc].mode); - + // push entry U64 min = base_address + v0; U64 max = base_address + v1; str8_list_pushf(range_temp.arena, &list, "%08llx %08llx %S", min, max, expression); } - + // print entry String8 print = str8_list_join(range_temp.arena, &list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", print); - + // cleanup temp temp_end(range_temp); - + // exit check if (is_list_end) { break; } } } - + temp_end(locs_temp); } rd_unindent(); - + rd_unindent(); scratch_end(scratch); #endif } internal void -dw_print_debug_ranges(Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ImageType image_type, B32 relaxed) +dw_print_debug_ranges(Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ExecutableImageKind image_type, B32 relaxed) { NotImplemented; #if 0 DW_Section ranges = input->sec[DW_Section_Ranges]; void *base = dw_base_from_sec(input, DW_Section_Ranges); Rng1U64 range = dw_range_from_sec(input, DW_Section_Ranges); - + if (dim_1u64(range) == 0) { return; } - + Temp scratch = scratch_begin(&arena, 1); - + Rng1U64List cu_range_list = dw_comp_unit_ranges_from_info(scratch.arena, sections->v[DW_Section_Info]); - + // parse debug_info for attributes with LOCLIST and store .debug_loc offsets U64List *loc_lists = push_array(scratch.arena, U64List, cu_range_list.count); U64 *address_sizes = push_array(scratch.arena, U64, cu_range_list.count); U64 *address_bases = push_array(scratch.arena, U64, cu_range_list.count); - + { U64 comp_idx = 0; for (Rng1U64Node *cu_range_n = cu_range_list.first; cu_range_n != 0; cu_range_n = cu_range_n->next, ++comp_idx) { Rng1U64 cu_range = cu_range_n->v; DW_CompUnit cu = dw_comp_unit_from_info_offset(scratch.arena, sections, cu_range.min, relaxed); - + // store info about comp unit address_sizes[comp_idx] = cu.address_size; address_bases[comp_idx] = cu.base_addr; - + // parse tags for (U64 info_off = cu.tags_range.min; info_off < cu.tags_range.max; /* empty */) { DW_Tag tag = dw_tag_from_info_offset_cu(scratch.arena, sections, &cu, info_off); - + // parse attribs for (DW_AttribNode *attrib_node = tag.attribs.first; attrib_node != 0; attrib_node = attrib_node->next) { DW_Attrib *attrib = &attrib_node->v; @@ -3213,12 +2017,12 @@ dw_print_debug_ranges(Arena *arena, String8List *out, String8 indent, DW_Input * // TODO: support for section indexing } } - + info_off = tag.next_info_off; } } } - + rd_printf("# %S", sections->v[DW_Section_Ranges].name); rd_indent(); rd_printf("%-8s %-8s %-8s", "Offset", "Min", "Max"); @@ -3228,22 +2032,22 @@ dw_print_debug_ranges(Arena *arena, String8List *out, String8 indent, DW_Input * U64Array locs_set = remove_duplicates_u64_array(scratch.arena, locs); U64 address_size = address_sizes[comp_idx]; U64 base_selector = (address_size == 8) ? max_U64 : max_U32; - + for (U64 loc_idx = 0; loc_idx < locs_set.count; ++loc_idx) { U64 base_address = address_bases[comp_idx]; for (U64 cursor = locs_set.v[loc_idx]; cursor < dim_1u64(range); /* empty */) { Temp range_temp = temp_begin(scratch.arena); - + String8List list = {0}; - + // offset str8_list_pushf(range_temp.arena, &list, "%08llx", cursor); - + // parse entry U64 v0 = 0, v1 = 0; cursor += dw_based_range_read(base, range, cursor, address_size, &v0); cursor += dw_based_range_read(base, range, cursor, address_size, &v1); - + B32 is_list_end = v0 == 0 && v1 == 0; if (is_list_end) { str8_list_pushf(range_temp.arena, &list, ""); @@ -3255,13 +2059,13 @@ dw_print_debug_ranges(Arena *arena, String8List *out, String8 indent, DW_Input * U64 max = base_address + v1; str8_list_pushf(range_temp.arena, &list, "%08llx %08llx", min, max); } - + // print entry String8 print = str8_list_join(range_temp.arena, &list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", print); - + temp_end(range_temp); - + // exit check if (is_list_end) { break; @@ -3279,13 +2083,13 @@ dw_print_debug_aranges(Arena *arena, String8List *out, String8 indent, DW_Input #if 0 void *base = dw_base_from_sec(sections, DW_Section_ARanges); Rng1U64 range = dw_range_from_sec(sections, DW_Section_ARanges); - + if (dim_1u64(range) == 0) { return; } - + Temp scratch = scratch_begin(&arena, 1); - + rd_printf("# %S", sections->v[DW_Section_ARanges].name); rd_indent(); for (U64 cursor = 0; cursor < dim_1u64(range); ) { @@ -3294,50 +2098,50 @@ dw_print_debug_aranges(Arena *arena, String8List *out, String8 indent, DW_Input U64 debug_info_offset = 0; U8 address_size = 0; U8 segment_selector_size = 0; - + cursor += dw_based_range_read_length(base, range, cursor, &unit_length); U64 unit_opl = cursor + unit_length; cursor += dw_based_range_read_struct(base, range, cursor, &version); - + B32 is_dwarf64 = unit_length >= max_U32; U64 int_size = is_dwarf64 ? sizeof(U64) : sizeof(U32); cursor += dw_based_range_read(base, range, cursor, int_size, &debug_info_offset); - + cursor += dw_based_range_read_struct(base, range, cursor, &address_size); cursor += dw_based_range_read_struct(base, range, cursor, &segment_selector_size); - + U64 tuple_size = address_size * 2 + segment_selector_size; U64 bytes_too_far_past_boundary = cursor % tuple_size; if (bytes_too_far_past_boundary > 0) { cursor += tuple_size - bytes_too_far_past_boundary; } - + rd_printf("Unit length: %llu", unit_length); rd_printf("Version: %u", version); rd_printf("Debug info offset: %#llx", debug_info_offset); rd_printf("Address size: %u", address_size); rd_printf("Segment selector size: %u", segment_selector_size); - + if (version != DW_Version_2) { rd_warningf("Version value must be 2 (DWARF5 sepc, Feb 13, 2017)"); } - + rd_indent(); rd_printf("%-8s %-8s", "Offset", "Range"); for (; cursor < unit_opl; ) { Temp temp = temp_begin(arena); - + String8List list = {0}; - + str8_list_pushf(temp.arena, &list, "%08llx", cursor); - + U64 segment_selector = 0; U64 address = 0; U64 length = 0; cursor += dw_based_range_read(base, range, cursor, segment_selector_size, &segment_selector); cursor += dw_based_range_read(base, range, cursor, address_size, &address); cursor += dw_based_range_read(base, range, cursor, address_size, &length); - + if (segment_selector == 0 && address == 0 && length == 0) { str8_list_pushf(temp.arena, &list, ""); } else { @@ -3346,17 +2150,17 @@ dw_print_debug_aranges(Arena *arena, String8List *out, String8 indent, DW_Input } str8_list_pushf(temp.arena, &list, "%llx-%llx", address, address+length); } - + String8 print = str8_list_join(temp.arena, &list, &(StringJoin){.sep=str8_lit(" ") }); rd_printf("%S", print); - + temp_end(temp); } rd_unindent(); rd_newline(); } rd_unindent(); - + scratch_end(scratch); #endif } @@ -3368,13 +2172,13 @@ dw_print_debug_addr(Arena *arena, String8List *out, String8 indent, DW_Input *in #if 0 void *base = dw_base_from_sec(sections, DW_Section_Addr); Rng1U64 range = dw_range_from_sec(sections, DW_Section_Addr); - + if (dim_1u64(range) == 0) { return; } - + Temp scratch = scratch_begin(&arena, 1); - + rd_printf("# %S", sections->v[DW_Section_Addr].name); rd_indent(); for (U64 cursor = 0; cursor < dim_1u64(range); ) { @@ -3382,44 +2186,44 @@ dw_print_debug_addr(Arena *arena, String8List *out, String8 indent, DW_Input *in DW_Version version = 0; U8 address_size = 0; U8 segment_selector_size = 0; - + U64 unit_offset = cursor; cursor += dw_based_range_read_length(base, range, cursor, &unit_length); - + U64 unit_opl = cursor + unit_length; cursor += dw_based_range_read_struct(base, range, cursor, &version); cursor += dw_based_range_read_struct(base, range, cursor, &address_size); cursor += dw_based_range_read_struct(base, range, cursor, &segment_selector_size); - + U64 tuple_size = address_size * 2 + segment_selector_size; U64 bytes_too_far_past_boundary = cursor % tuple_size; if (bytes_too_far_past_boundary > 0) { cursor += tuple_size - bytes_too_far_past_boundary; } - + rd_printf("Unit @ %#llx, length %llu", unit_offset, unit_length); rd_printf("Version: %u", version); rd_printf("Address size: %u", address_size); rd_printf("Segment selector size: %u", segment_selector_size); - + if (version != DW_Version_2) { rd_warningf("Version value must be 5 (DWARF5 sepc, Feb 13, 2017)"); } - + rd_indent(); rd_printf("%-8s %-8s", "Offset", "Address"); for (; cursor < unit_opl; ) { Temp temp = temp_begin(arena); - + String8List list = {0}; - + str8_list_pushf(temp.arena, &list, "%08X", cursor); - + U64 segment_selector = 0; U64 address = 0; cursor += dw_based_range_read(base, range, cursor, segment_selector_size, &segment_selector); cursor += dw_based_range_read(base, range, cursor, address_size, &address); - + if (segment_selector == 0 && address == 0) { str8_list_pushf(temp.arena, &list, ""); } else { @@ -3428,17 +2232,17 @@ dw_print_debug_addr(Arena *arena, String8List *out, String8 indent, DW_Input *in } str8_list_pushf(temp.arena, &list, "%llx", address); } - + String8 print = str8_list_join(arena, &list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", print); - + temp_end(temp); } rd_unindent(); rd_newline(); } rd_unindent(); - + scratch_end(scratch); #endif } @@ -3447,15 +2251,15 @@ internal U64 dw_based_range_read_address(void *base, Rng1U64 range, U64 offset, Rng1U64Array segment_ranges, U8 segment_selector_size, U8 address_size, U64 *address_out) { U64 read_offset = offset; - + // read segment U64 segment_selector = 0; read_offset += dw_based_range_read(base, range, read_offset, segment_selector_size, &segment_selector); - + // read address U64 address = 0; read_offset += dw_based_range_read(base, range, read_offset, address_size, &address); - + // apply segment offset B32 is_address_segment_relative = segment_selector_size > 0; if (is_address_segment_relative) { @@ -3465,7 +2269,7 @@ dw_based_range_read_address(void *base, Rng1U64 range, U64 offset, Rng1U64Array Assert(!"invalid segment selector"); } } - + U64 read_size = (read_offset - offset); return read_size; } @@ -3477,20 +2281,20 @@ dw_print_debug_loclists(Arena *arena, String8List *out, String8 indent, DW_Input #if 0 void *base = dw_base_from_sec(sections, DW_Section_LocLists); Rng1U64 range = dw_range_from_sec(sections, DW_Section_LocLists); - + if (dim_1u64(range) == 0) { return; } - + Temp scratch = scratch_begin(&arena, 1); - + rd_printf("# %S", sections->v[DW_Section_LocLists].name); rd_indent(); for (U64 cursor = 0; cursor < dim_1u64(range); ) { U64 unit_offset = cursor; U64 unit_length = 0; cursor += dw_based_range_read_length(base, range, cursor, &unit_length); - + U64 unit_opl = cursor + unit_length; DW_Version version = 0; U8 address_size = 0; @@ -3500,11 +2304,11 @@ dw_print_debug_loclists(Arena *arena, String8List *out, String8 indent, DW_Input cursor += dw_based_range_read_struct(base, range, cursor, &address_size); cursor += dw_based_range_read_struct(base, range, cursor, &segment_selector_size); cursor += dw_based_range_read_struct(base, range, cursor, &offset_entry_count); - + U64 past_header_offset = cursor; B32 is_dwarf64 = unit_length > max_U32; U64 offset_size = is_dwarf64 ? sizeof(U64) : sizeof(U32); - + rd_printf("Unit @ %#llx, length %llu", unit_offset, unit_length); rd_printf("Version: %u", version); rd_printf("Address size: %u", address_size); @@ -3513,7 +2317,7 @@ dw_print_debug_loclists(Arena *arena, String8List *out, String8 indent, DW_Input if (version != DW_Version_5) { rd_warningf("Version value must be 5 (DWARF5 sepc, Feb 13, 2017)"); } - + if (offset_entry_count > 0) { rd_printf("Offsets:"); rd_indent(); @@ -3525,100 +2329,100 @@ dw_print_debug_loclists(Arena *arena, String8List *out, String8 indent, DW_Input } rd_unindent(); } - + rd_printf("Locations:"); rd_indent(); rd_printf("%-8s %-8s", "Offset", "Location"); for (; cursor < unit_opl; ) { Temp temp = temp_begin(arena); - + String8List list = {0}; - + str8_list_pushf(temp.arena, &list, "%08llx", cursor); - + U8 kind = 0; cursor += dw_based_range_read_struct(base, range, cursor, &kind); str8_list_pushf(temp.arena, &list, "DW_LLE_%S", dw_string_from_loc_list_entry_kind(temp.arena, kind)); - + B32 has_loc_desc = 0; switch (kind) { - case DW_LocListEntryKind_EndOfList: + case DW_LocListEntryKind_EndOfList: break; - case DW_LocListEntryKind_DefaultLocation: { - has_loc_desc = 1; - } break; - case DW_LocListEntryKind_BaseAddress: { - U64 base_address = 0; - cursor += dw_based_range_read_address(base, range, cursor, segment_virtual_ranges, segment_selector_size, address_size, &base_address); - str8_list_pushf(temp.arena, &list, "%llx", base_address); - } break; - case DW_LocListEntryKind_StartLength: { - U64 start = 0; - U64 length = 0; - cursor += dw_based_range_read_address(base, range, cursor, segment_virtual_ranges, segment_selector_size, address_size, &start); - cursor += dw_based_range_read_uleb128(base, range, cursor, &length); - str8_list_pushf(temp.arena, &list, "%llx, %llx", start, length); - } break; - case DW_LocListEntryKind_StartEnd: { - U64 start = 0; - U64 end = 0; - cursor += dw_based_range_read_address(base, range, cursor, segment_virtual_ranges, segment_selector_size, address_size, &start); - cursor += dw_based_range_read_address(base, range, cursor, segment_virtual_ranges, segment_selector_size, address_size, &end); - str8_list_pushf(temp.arena, &list, "%llx, %llx", start, end); - } break; - case DW_LocListEntryKind_BaseAddressX: { - U64 base_addressx = 0; - cursor += dw_based_range_read_uleb128(base, range, cursor, &base_addressx); - str8_list_pushf(temp.arena, &list, "%llx", base_addressx); - } break; - case DW_LocListEntryKind_StartXEndX: { - U64 startx = 0; - U64 endx = 0; - cursor += dw_based_range_read_uleb128(base, range, cursor, &startx); - cursor += dw_based_range_read_uleb128(base, range, cursor, &endx); - str8_list_pushf(temp.arena, &list, "%llx, %llx", startx, endx); - } break; - case DW_LocListEntryKind_OffsetPair: { - U64 a = 0; - U64 b = 0; - cursor += dw_based_range_read_uleb128(base, range, cursor, &a); - cursor += dw_based_range_read_uleb128(base, range, cursor, &b); - str8_list_pushf(temp.arena, &list, "%llx, %llx", a, b); - - U8 expr_length = 0; - cursor += dw_based_range_read_struct(base, range, cursor, &expr_length); - - String8 raw_expr = str8((U8*)base+cursor, expr_length); - cursor += expr_length; - - // TODO: we need actual cu base to format expression correctly - NotImplemented; - String8 expression = dw_format_expression_single_line(temp.arena, raw_expr, 0, address_size, arch, version, DW_Ext_Null, is_dwarf64); - str8_list_pushf(temp.arena, &list, "(%S)", expression); - } break; - case DW_LocListEntryKind_StartXLength: { - U64 startx = 0; - cursor += dw_based_range_read_uleb128(base, range, cursor, &startx); - U64 length = 0; - if (version < DW_Version_5) { - // pre-standard length - cursor += dw_based_range_read(base, range, cursor, sizeof(U32), &length); - } else { + case DW_LocListEntryKind_DefaultLocation: { + has_loc_desc = 1; + } break; + case DW_LocListEntryKind_BaseAddress: { + U64 base_address = 0; + cursor += dw_based_range_read_address(base, range, cursor, segment_virtual_ranges, segment_selector_size, address_size, &base_address); + str8_list_pushf(temp.arena, &list, "%llx", base_address); + } break; + case DW_LocListEntryKind_StartLength: { + U64 start = 0; + U64 length = 0; + cursor += dw_based_range_read_address(base, range, cursor, segment_virtual_ranges, segment_selector_size, address_size, &start); cursor += dw_based_range_read_uleb128(base, range, cursor, &length); - } - } break; + str8_list_pushf(temp.arena, &list, "%llx, %llx", start, length); + } break; + case DW_LocListEntryKind_StartEnd: { + U64 start = 0; + U64 end = 0; + cursor += dw_based_range_read_address(base, range, cursor, segment_virtual_ranges, segment_selector_size, address_size, &start); + cursor += dw_based_range_read_address(base, range, cursor, segment_virtual_ranges, segment_selector_size, address_size, &end); + str8_list_pushf(temp.arena, &list, "%llx, %llx", start, end); + } break; + case DW_LocListEntryKind_BaseAddressX: { + U64 base_addressx = 0; + cursor += dw_based_range_read_uleb128(base, range, cursor, &base_addressx); + str8_list_pushf(temp.arena, &list, "%llx", base_addressx); + } break; + case DW_LocListEntryKind_StartXEndX: { + U64 startx = 0; + U64 endx = 0; + cursor += dw_based_range_read_uleb128(base, range, cursor, &startx); + cursor += dw_based_range_read_uleb128(base, range, cursor, &endx); + str8_list_pushf(temp.arena, &list, "%llx, %llx", startx, endx); + } break; + case DW_LocListEntryKind_OffsetPair: { + U64 a = 0; + U64 b = 0; + cursor += dw_based_range_read_uleb128(base, range, cursor, &a); + cursor += dw_based_range_read_uleb128(base, range, cursor, &b); + str8_list_pushf(temp.arena, &list, "%llx, %llx", a, b); + + U8 expr_length = 0; + cursor += dw_based_range_read_struct(base, range, cursor, &expr_length); + + String8 raw_expr = str8((U8*)base+cursor, expr_length); + cursor += expr_length; + + // TODO: we need actual cu base to format expression correctly + NotImplemented; + String8 expression = dw_format_expression_single_line(temp.arena, raw_expr, 0, address_size, arch, version, DW_Ext_Null, is_dwarf64); + str8_list_pushf(temp.arena, &list, "(%S)", expression); + } break; + case DW_LocListEntryKind_StartXLength: { + U64 startx = 0; + cursor += dw_based_range_read_uleb128(base, range, cursor, &startx); + U64 length = 0; + if (version < DW_Version_5) { + // pre-standard length + cursor += dw_based_range_read(base, range, cursor, sizeof(U32), &length); + } else { + cursor += dw_based_range_read_uleb128(base, range, cursor, &length); + } + } break; } - + String8 print = str8_list_join(temp.arena, &list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", print); - + temp_end(temp); } rd_unindent(); rd_newline(); } rd_unindent(); - + scratch_end(scratch); #endif } @@ -3630,13 +2434,13 @@ dw_print_debug_rnglists(Arena *arena, String8List *out, String8 indent, DW_Input #if 0 void *base = dw_base_from_sec(sections, DW_Section_RngLists); Rng1U64 range = dw_range_from_sec(sections, DW_Section_RngLists); - + if (dim_1u64(range) == 0) { return; } - + Temp scratch = scratch_begin(&arena, 1); - + rd_printf("# %S", sections->v[DW_Section_RngLists].name); rd_indent(); for (U64 cursor = 0; cursor < dim_1u64(range); ) { @@ -3652,21 +2456,21 @@ dw_print_debug_rnglists(Arena *arena, String8List *out, String8 indent, DW_Input cursor += dw_based_range_read_struct(base, range, cursor, &address_size); cursor += dw_based_range_read_struct(base, range, cursor, &segment_selector_size); cursor += dw_based_range_read_struct(base, range, cursor, &offset_entry_count); - + U64 past_header_offset = cursor; B32 is_dwarf64 = unit_length > max_U32; U64 offset_size = is_dwarf64 ? sizeof(U64) : sizeof(U32); - + rd_printf("Unit @ %#llx, length %llu", unit_offset, unit_length); rd_printf("Version: %u", version); rd_printf("Address size: %u", address_size); rd_printf("Segment selector size: %u", segment_selector_size); rd_printf("Offset entry count: %u", offset_entry_count); - + if (version != DW_Version_5) { rd_warningf("Version value must be 5 (DWARF5 sepc, Feb 13, 2017)"); } - + if (offset_entry_count > 0) { rd_printf("Offsets:"); rd_indent(); @@ -3678,86 +2482,86 @@ dw_print_debug_rnglists(Arena *arena, String8List *out, String8 indent, DW_Input } rd_unindent(); } - + rd_printf("Ranges:"); rd_indent(); rd_printf("%-8s %-8s", "Offset", "Range"); for (; cursor < unit_opl; ) { Temp temp = temp_begin(scratch.arena); - + String8List list = {0}; - + // offset str8_list_pushf(temp.arena, &list, "%08llx", cursor); - + // opcode mnemonic U8 kind = 0; cursor += dw_based_range_read_struct(base, range, cursor, &kind); str8_list_pushf(temp.arena, &list, "DW_RLE_%S", dw_string_from_rng_list_entry_kind(temp.arena, kind)); - + // operand switch (kind) { - case DW_RngListEntryKind_EndOfList: { - // empty - } break; - case DW_RngListEntryKind_BaseAddressX: { - U64 base_addressx = 0; - cursor += dw_based_range_read_uleb128(base, range, cursor, &base_addressx); - str8_list_pushf(temp.arena, &list, "%llx", base_addressx); - } break; - case DW_RngListEntryKind_BaseAddress: { - U64 base_address = 0; - cursor += dw_based_range_read_address(base, range, cursor, segment_ranges, segment_selector_size, address_size, &base_address); - str8_list_pushf(temp.arena, &list, "%llx", base_address); - } break; - case DW_RngListEntryKind_OffsetPair: { - U64 min = 0; - U64 max = 0; - cursor += dw_based_range_read_uleb128(base, range, cursor, &min); - cursor += dw_based_range_read_uleb128(base, range, cursor, &max); - str8_list_pushf(temp.arena, &list, "%llx, %llx", min, max); - } break; - case DW_RngListEntryKind_StartxLength: { - U64 startx = 0; - U64 length = 0; - cursor += dw_based_range_read_uleb128(base, range, cursor, &startx); - cursor += dw_based_range_read_uleb128(base, range, cursor, &length); - str8_list_pushf(temp.arena, &list, "%llx, %llx", startx, length); - } break; - case DW_RngListEntryKind_StartxEndx: { - U64 startx = 0; - U64 endx = 0; - cursor += dw_based_range_read_uleb128(base, range, cursor, &startx); - cursor += dw_based_range_read_uleb128(base, range, cursor, &endx); - str8_list_pushf(temp.arena, &list, "%llx, %llx", startx, endx); - } break; - case DW_RngListEntryKind_StartEnd: { - U64 start = 0; - U64 end = 0; - cursor += dw_based_range_read_address(base, range, cursor, segment_ranges, segment_selector_size, address_size, &start); - cursor += dw_based_range_read_address(base, range, cursor, segment_ranges, segment_selector_size, address_size, &end); - str8_list_pushf(temp.arena, &list, "%llx, %llx", start, end); - } break; - case DW_RngListEntryKind_StartLength: { - U64 start = 0; - U64 length = 0; - cursor += dw_based_range_read_address(base, range, cursor, segment_ranges, segment_selector_size, address_size, &start); - cursor += dw_based_range_read_uleb128(base, range, cursor, &length); - str8_list_pushf(temp.arena, &list, "%llx, %llx", start, length); - } break; + case DW_RngListEntryKind_EndOfList: { + // empty + } break; + case DW_RngListEntryKind_BaseAddressX: { + U64 base_addressx = 0; + cursor += dw_based_range_read_uleb128(base, range, cursor, &base_addressx); + str8_list_pushf(temp.arena, &list, "%llx", base_addressx); + } break; + case DW_RngListEntryKind_BaseAddress: { + U64 base_address = 0; + cursor += dw_based_range_read_address(base, range, cursor, segment_ranges, segment_selector_size, address_size, &base_address); + str8_list_pushf(temp.arena, &list, "%llx", base_address); + } break; + case DW_RngListEntryKind_OffsetPair: { + U64 min = 0; + U64 max = 0; + cursor += dw_based_range_read_uleb128(base, range, cursor, &min); + cursor += dw_based_range_read_uleb128(base, range, cursor, &max); + str8_list_pushf(temp.arena, &list, "%llx, %llx", min, max); + } break; + case DW_RngListEntryKind_StartxLength: { + U64 startx = 0; + U64 length = 0; + cursor += dw_based_range_read_uleb128(base, range, cursor, &startx); + cursor += dw_based_range_read_uleb128(base, range, cursor, &length); + str8_list_pushf(temp.arena, &list, "%llx, %llx", startx, length); + } break; + case DW_RngListEntryKind_StartxEndx: { + U64 startx = 0; + U64 endx = 0; + cursor += dw_based_range_read_uleb128(base, range, cursor, &startx); + cursor += dw_based_range_read_uleb128(base, range, cursor, &endx); + str8_list_pushf(temp.arena, &list, "%llx, %llx", startx, endx); + } break; + case DW_RngListEntryKind_StartEnd: { + U64 start = 0; + U64 end = 0; + cursor += dw_based_range_read_address(base, range, cursor, segment_ranges, segment_selector_size, address_size, &start); + cursor += dw_based_range_read_address(base, range, cursor, segment_ranges, segment_selector_size, address_size, &end); + str8_list_pushf(temp.arena, &list, "%llx, %llx", start, end); + } break; + case DW_RngListEntryKind_StartLength: { + U64 start = 0; + U64 length = 0; + cursor += dw_based_range_read_address(base, range, cursor, segment_ranges, segment_selector_size, address_size, &start); + cursor += dw_based_range_read_uleb128(base, range, cursor, &length); + str8_list_pushf(temp.arena, &list, "%llx, %llx", start, length); + } break; } - + // output row String8 print = str8_list_join(temp.arena, &list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", print); - + temp_end(temp); } rd_unindent(); rd_newline(); } rd_unindent(); - + scratch_end(scratch); #endif } @@ -3765,45 +2569,45 @@ dw_print_debug_rnglists(Arena *arena, String8List *out, String8 indent, DW_Input internal void dw_format_string_table(Arena *arena, String8List *out, String8 indent, DW_Input *input, DW_SectionKind sec) { -NotImplemented; + NotImplemented; #if 0 void *base = dw_base_from_sec(sections, sec); Rng1U64 range = dw_range_from_sec(sections, sec); - + if (dim_1u64(range) == 0) { return; } - + Temp scratch = scratch_begin(&arena, 1); - + rd_printf("# %S", sections->v[sec].name); rd_indent(); for (U64 cursor = 0; cursor < dim_1u64(range); ) { U64 unit_offset = cursor; - + U64 unit_length = 0; cursor += dw_based_range_read_length(base, range, cursor, &unit_length); U64 unit_opl = cursor + unit_length; - + DW_Version version = 0; cursor += dw_based_range_read_struct(base, range, cursor, &version); - + if (version != DW_Version_2) { rd_warningf("Version value must be 2"); } - + B32 is_dwarf64 = unit_length > max_U32; U32 sec_offset_size = is_dwarf64 ? sizeof(U64) : sizeof(U32); - + U64 debug_info_offset = 0, debug_info_length = 0; cursor += dw_based_range_read(base, range, cursor, sec_offset_size, &debug_info_offset); cursor += dw_based_range_read(base, range, cursor, sec_offset_size, &debug_info_length); - + rd_printf("Unit @ %#llx, length %llu", unit_offset, unit_length); rd_printf("Version: %u", version); rd_printf("Debug info offset: %#llx", debug_info_offset); rd_printf("Debug info length: %#llx", debug_info_length); - + rd_printf("Entries:"); rd_indent(); rd_printf("%-8s %-8s", "Offset", "String"); @@ -3812,14 +2616,14 @@ NotImplemented; cursor += dw_based_range_read(base, range, cursor, sec_offset_size, &info_offset); String8 string = dw_based_range_read_string(base, range, cursor); cursor += (string.size + 1); - + rd_printf("%08llx %S", info_offset, string); } rd_unindent(); rd_newline(); } rd_unindent(); - + scratch_end(scratch); #endif } @@ -3839,20 +2643,20 @@ dw_print_debug_pubtypes(Arena *arena, String8List *out, String8 indent, DW_Input internal void dw_print_debug_line_str(Arena *arena, String8List *out, String8 indent, DW_Input *input) { -NotImplemented; + NotImplemented; #if 0 void *base = dw_base_from_sec(sections, DW_Section_LineStr); Rng1U64 range = dw_range_from_sec(sections, DW_Section_LineStr); - + if (dim_1u64(range) == 0) { return; } - + Temp scratch = scratch_begin(&arena, 1); - + rd_printf("# %S", sections->v[DW_Section_LineStr].name); rd_indent(); - + rd_printf("%-8s %-8s", "Offset", "String"); for (U64 cursor = 0; cursor < dim_1u64(range); ) { U64 offset = cursor; @@ -3861,7 +2665,7 @@ NotImplemented; rd_printf("%08llX %S", offset, string); } rd_unindent(); - + scratch_end(scratch); #endif } @@ -3869,44 +2673,44 @@ NotImplemented; internal void dw_print_debug_str_offsets(Arena *arena, String8List *out, String8 indent, DW_Input *input) { -NotImplemented; + NotImplemented; #if 0 void *base = dw_base_from_sec(sections, DW_Section_StrOffsets); Rng1U64 range = dw_range_from_sec(sections, DW_Section_StrOffsets); void *debug_str_base = dw_base_from_sec(sections, DW_Section_Str); Rng1U64 debug_str_range = dw_range_from_sec(sections, DW_Section_Str); - + if (dim_1u64(range) == 0) { return; } - + Temp scratch = scratch_begin(&arena, 1); - + rd_printf("# %S", sections->v[DW_Section_StrOffsets].name); rd_indent(); for (U64 cursor = 0; cursor < dim_1u64(range); ) { U64 unit_offset = cursor; - + U64 unit_length = 0; cursor += dw_based_range_read_length(base, range, cursor, &unit_length); U64 unit_opl = cursor + unit_length; - + DW_Version version = 0; cursor += dw_based_range_read_struct(base, range, cursor, &version); if (version != DW_Version_5) { rd_warningf("Version value must be 5 (DWARF5 sepc, Feb 13, 2017)"); } - + U16 padding = 0; cursor += dw_based_range_read_struct(base, range, cursor, &padding); if (padding != 0) { rd_warningf("unexpected padding byte"); } - + B32 is_dwarf64 = unit_length > max_U32; U32 offset_size = is_dwarf64 ? sizeof(U64) : sizeof(U32); - + rd_printf("Unit @ %#llX, length %lld", unit_offset, unit_length); rd_printf("Version: %d", version); rd_printf("Padding: %d", padding); @@ -3927,21 +2731,21 @@ NotImplemented; rd_newline(); } rd_unindent(); - + scratch_end(scratch); #endif } internal void -dw_format(Arena *arena, String8List *out, String8 indent, RD_Option opts, DW_Input *input, Arch arch, ImageType image_type) +dw_format(Arena *arena, String8List *out, String8 indent, RD_Option opts, DW_Input *input, Arch arch, ExecutableImageKind image_type) { Temp scratch = scratch_begin(&arena, 1); - + Rng1U64Array segment_vranges = {0}; - + DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, input); B32 relaxed = !!(opts & RD_Option_RelaxDwarfParser); - + if (opts & RD_Option_DebugInfo) { dw_print_debug_info(arena, out, indent, input, lu_input, arch, relaxed); } @@ -3984,7 +2788,7 @@ dw_format(Arena *arena, String8List *out, String8 indent, RD_Option opts, DW_Inp if (opts & RD_Option_DebugStrOffsets) { dw_print_debug_str_offsets(arena, out, indent, input); } - + scratch_end(scratch); } @@ -4005,37 +2809,37 @@ cv_print_binary_annots(Arena *arena, String8List *out, String8 indent, CV_Arch a { if (raw_data.size) { Temp scratch = scratch_begin(&arena, 1); - + rd_printf("Binary Annotations:"); rd_indent(); - + U64 cursor = 0; for (; cursor < raw_data.size; ) { String8List op_list = {0}; - + U8 op; cursor += str8_deserial_read_struct(raw_data, cursor, &op); if (op == CV_InlineBinaryAnnotation_Null) { break; } - + U8 params[2]; U32 param_count = (op == CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset) ? 2 : 1; cursor += str8_deserial_read_array(raw_data, cursor, ¶ms[0], param_count); - + String8 opcode_str = cv_string_from_binary_opcode(op); str8_list_pushf(scratch.arena, &op_list, "%S", opcode_str); for (U32 i = 0; i < param_count; ++i) { str8_list_pushf(scratch.arena, &op_list, " %x", params[i]); } - + String8 op_str = str8_list_join(scratch.arena, &op_list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", op_str); } rd_unindent(); - + rd_printf("Binary Annotations Length: %u bytes (%u bytes padding)", raw_data.size, raw_data.size - cursor); - + scratch_end(scratch); } } @@ -4084,7 +2888,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Parent : %#x", sym.parent); rd_printf("End : %#x", sym.end); @@ -4111,7 +2915,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV U32 invocation_count = (raw_symbol.size - cursor) / sizeof(U32); U32 *invocations = push_array(arena, U32, invocation_count); cursor += str8_deserial_read_array(raw_symbol, cursor, &invocations[0], invocation_count); - + rd_printf("Count: %u", sym.count); rd_indent(); for (U32 i = 0; i < sym.count; ++i) { @@ -4123,7 +2927,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV case CV_SymKind_INLINEES: { CV_SymInlinees sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + rd_printf("Count: %u", sym.count); rd_indent(); for (U32 i = 0; i < sym.count; ++i) { @@ -4138,7 +2942,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 raw_annots = str8_skip(raw_symbol, sizeof(CV_SymInlineSite)); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += raw_annots.size; - + rd_printf("Parent : %#x", sym.parent); rd_printf("End : %#x", sym.end); rd_printf("Inlinee: %S", cv_string_from_itemid(arena, sym.inlinee)); @@ -4149,7 +2953,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 raw_annots = str8_skip(raw_symbol, sizeof(CV_SymInlineSite2)); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += raw_annots.size; - + rd_printf("Parent : %#x", sym.parent_off); rd_printf("End : %#x", sym.end_off); rd_printf("Inlinee : %S", cv_string_from_itemid(arena, sym.inlinee)); @@ -4167,7 +2971,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("TSL Address: %S", cv_string_sec_off(scratch.arena, sym.tls_seg, sym.tls_off)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); @@ -4177,7 +2981,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Signature: %#x", sym.sig); } break; @@ -4187,7 +2991,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Parent : %#x", sym.parent); rd_printf("End : %#x", sym.end); rd_printf("Address: %S", cv_string_sec_off(scratch.arena, sym.sec, sym.off)); @@ -4202,7 +3006,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = str8_zero(); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Address: %S, Flags: %S, Name: %S", cv_string_sec_off(scratch.arena, sym.sec, sym.off), cv_string_from_proc_flags(scratch.arena, sym.flags), name); } break; case CV_SymKind_COMPILE: { @@ -4211,7 +3015,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 version_string = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &version_string); - + U32 language = CV_CompileFlags_Extract_Language(sym.flags); U32 float_prec = CV_CompileFlags_Extract_FloatPrec(sym.flags); U32 float_pkg = CV_CompileFlags_Extract_FloatPkg(sym.flags); @@ -4232,7 +3036,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 version_string = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &version_string); - + U32 language = CV_Compile2Flags_Extract_Language(sym.flags); rd_printf("Machine : %#x (%S)", sym.machine, cv_string_from_arch(sym.machine)); rd_printf("Flags : %#x", sym.flags); @@ -4248,7 +3052,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 version_string = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &version_string); - + U32 language = CV_Compile3Flags_Extract_Language(sym.flags); rd_printf("Machine : %#x (%S)", sym.machine, cv_string_from_arch(sym.machine)); rd_printf("Flags : %#x", sym.flags); @@ -4271,7 +3075,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); String8 name = str8_zero(); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Parent : %#x", sym.parent); rd_printf("End : %#x", sym.end); @@ -4291,7 +3095,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); rd_printf("Address: %S", cv_string_sec_off(scratch.arena, sym.sec, sym.off)); @@ -4304,7 +3108,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += cv_read_numeric(raw_symbol, cursor, &size); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name: %S", name); rd_printf("Type: %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); rd_printf("Size: %S", cv_string_from_numeric(scratch.arena, size)); @@ -4312,7 +3116,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV case CV_SymKind_FRAMEPROC: { CV_SymFrameproc sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + String8 flags = cv_string_from_frame_proc_flags(scratch.arena, sym.flags); U32 local_ptr = CV_FrameprocFlags_Extract_LocalBasePointer(sym.flags); U32 param_ptr = CV_FrameprocFlags_Extract_ParamBasePointer(sym.flags); @@ -4330,7 +3134,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); rd_printf("Flags: %S", cv_string_from_local_flags(scratch.arena, sym.flags)); @@ -4340,7 +3144,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 raw_gaps = str8_skip(raw_symbol, sizeof(CV_SymDefrange)); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += raw_gaps.size; - + rd_printf("Program: %#x", sym.program); cv_print_lvar_addr_range(arena, out, indent, sym.range); cv_print_lvar_addr_gap(arena, out, indent, raw_gaps); @@ -4350,7 +3154,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 raw_gaps = str8_skip(raw_symbol, sizeof(CV_SymDefrangeRegisterRel)); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += raw_gaps.size; - + rd_printf("Register : %S", cv_string_from_reg_id(scratch.arena, arch, sym.reg)); rd_printf("Attributes: %S", cv_string_from_range_attribs(scratch.arena, sym.attribs)); cv_print_lvar_addr_range(arena, out, indent, sym.range); @@ -4360,7 +3164,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV CV_SymDefrangeFramepointerRel sym = {0}; String8 raw_gaps = str8_skip(raw_symbol, sizeof(CV_SymDefrangeFramepointerRel)); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + rd_printf("Offset: %#x", sym.off); cv_print_lvar_addr_range(arena, out, indent, sym.range); cv_print_lvar_addr_gap(arena, out, indent, raw_gaps); @@ -4370,7 +3174,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 raw_gaps = str8_skip(raw_symbol, sizeof(CV_SymDefrangeSubfieldRegister)); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += raw_gaps.size; - + rd_printf("Register : %#x (%S)", sym.reg, cv_string_from_reg_id(scratch.arena, arch, sym.reg)); rd_printf("Attributes : %#x (%S)", sym.attribs, cv_string_from_range_attribs(scratch.arena, sym.attribs)); rd_printf("Parent Offset: %#x", sym.field_offset); @@ -4387,7 +3191,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 raw_gaps = str8_skip(raw_symbol, sizeof(CV_SymDefrangeRegisterRel)); cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += raw_gaps.size; - + rd_printf("Flags : %#x (%S)", sym.flags, cv_string_from_defrange_register_rel_flags(scratch.arena, sym.flags)); rd_printf("Address: %S", cv_string_from_reg_off(scratch.arena, arch, sym.reg, sym.reg_off)); cv_print_lvar_addr_gap(arena, out, indent, raw_gaps); @@ -4402,7 +3206,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name: %S", name); rd_printf("Type: %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); } break; @@ -4415,7 +3219,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV case CV_SymKind_UNAMESPACE: { String8 name = {0}; cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name: %S", name); } break; case CV_SymKind_REGREL32_ST: @@ -4424,7 +3228,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Address: %S, Type: %S, Name: %S", cv_string_from_reg_off(scratch.arena, arch, sym.reg, sym.reg_off), cv_string_from_itype(scratch.arena, min_itype, sym.itype), @@ -4433,7 +3237,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV case CV_SymKind_CALLSITEINFO: { CV_SymCallSiteInfo sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + rd_printf("Address: %S", cv_string_sec_off(scratch.arena, sym.sec, sym.off)); rd_printf("Pad : %u", sym.pad); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); @@ -4441,7 +3245,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV case CV_SymKind_FRAMECOOKIE: { CV_SymFrameCookie sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + rd_printf("Address: %S", cv_string_sec_off(arena, sym.reg, sym.off)); rd_printf("Kind : %#x (%S)", sym.kind, cv_string_from_frame_cookie_kind(sym.kind)); rd_printf("Flags : %#x", sym.flags); // TODO: llvm and cvinfo.h don't define these flags... @@ -4449,7 +3253,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV case CV_SymKind_HEAPALLOCSITE: { CV_SymHeapAllocSite sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + String8 addr = cv_string_sec_off(arena, sym.sec, sym.off); String8 itype = cv_string_from_itype(arena, min_itype, sym.itype); rd_printf("Address : %S", addr); @@ -4484,7 +3288,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV CV_SymStartSearch sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + rd_printf("Start Symbol: %#x", sym.start_symbol); rd_printf("Segment : %#x", sym.segment); } break; @@ -4493,13 +3297,13 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV CV_SymReturn sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + rd_printf("Flags : %#x (%S)", sym.flags, cv_string_from_generic_flags(scratch.arena, sym.flags)); rd_printf("Style : %#x (%S)", sym.style, cv_string_from_generic_style(sym.style)); if (sym.style == CV_GenericStyle_REG) { U8 count = 0; cursor += str8_deserial_read_struct(raw_symbol, cursor, &count); - + String8 data = rd_format_hex_array(scratch.arena, raw_symbol.str, raw_symbol.size); rd_printf("Byte Count: %u", count); rd_printf("Data : %S", data); @@ -4512,7 +3316,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV cursor += str8_deserial_read_struct(raw_symbol, cursor, &symbol_size); cursor += str8_deserial_read_struct(raw_symbol, cursor, &symbol_type); String8 raw_subsym = str8_skip(raw_symbol, cursor); - + cv_print_symbol(arena, out, indent, arch, min_itype, type, raw_subsym); } break; case CV_SymKind_SLINK32: { @@ -4520,7 +3324,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV CV_SymSLink32 sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + rd_printf("Frame Size: %x", sym.frame_size); rd_printf("Address : %S", cv_string_from_reg_off(scratch.arena, arch, sym.reg, sym.offset)); } break; @@ -4529,7 +3333,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV CV_SymOEM sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + // TODO: Not clear what to do about user data that follows, are we supposed to assume that // rest of the range is it? // @@ -4542,7 +3346,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV CV_SymVPath32 sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + rd_printf("Root : %S", cv_string_from_itype(scratch.arena, min_itype, sym.root)); rd_printf("Path : %S", cv_string_from_itype(scratch.arena, min_itype, sym.path)); rd_printf("Address: %S", cv_string_sec_off(scratch.arena, sym.seg, sym.off)); @@ -4553,7 +3357,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Flags : %S", cv_string_from_pub32_flags(scratch.arena, sym.flags)); rd_printf("Address: %S", cv_string_sec_off(scratch.arena, sym.sec, sym.off)); @@ -4566,7 +3370,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Offset: %#x", sym.off); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); @@ -4578,7 +3382,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Register: %S", cv_string_from_reg_id(scratch.arena, arch, sym.reg)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); @@ -4596,7 +3400,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("SUC : %#x", sym.suc_name); rd_printf("IMod : %#x", sym.imod); @@ -4607,7 +3411,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV CV_SymSepcode sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + rd_printf("Parent : %#x", sym.parent); rd_printf("End : %#x", sym.end); rd_printf("Length : %u", sym.len); @@ -4624,7 +3428,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name: %S", name); rd_printf("Slot: %u", sym.slot_index); rd_printf("Type: %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); @@ -4634,7 +3438,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV CV_SymTrampoline sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + rd_printf("Type : %S", cv_string_from_trampoline_kind(sym.kind)); rd_printf("Thunk Size: %u", sym.thunk_size); rd_printf("Thunk : %S", cv_string_sec_off(scratch.arena, sym.thunk_sec, sym.thunk_sec_off)); @@ -4645,7 +3449,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV CV_SymPogoInfo sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + rd_printf("Invocations : %u", sym.invocations); rd_printf("Dynamic instruction count : %u", sym.dynamic_inst_count); rd_printf("Static instruction count : %u", sym.static_inst_count); @@ -4656,7 +3460,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV CV_SymManyreg sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + rd_printf("Type : %S", cv_string_from_itype(arena, min_itype, sym.itype)); rd_printf("Reg Count: %u", sym.count); rd_printf("Regs :"); @@ -4674,7 +3478,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV CV_SymManyreg sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + rd_printf("Type : %S", cv_string_from_itype(arena, min_itype, sym.itype)); rd_printf("Reg Count: %u", sym.count); rd_printf("Regs :"); @@ -4693,7 +3497,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Index : %u", sym.sec_index); rd_printf("Align : %u", sym.align); @@ -4704,7 +3508,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV case CV_SymKind_ENVBLOCK: { CV_SymEnvBlock sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + for (; cursor < raw_symbol.size; ) { String8 id = str8_zero(); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &id); @@ -4723,7 +3527,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Size : %u", sym.size); rd_printf("Characteristics: %#x (%S)", sym.characteristics, coff_string_from_section_flags(scratch.arena, sym.characteristics)); @@ -4736,7 +3540,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Ordinal: %#x", sym.ordinal); rd_printf("Flags : %S", cv_string_from_export_flags(scratch.arena, sym.flags)); @@ -4746,7 +3550,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV CV_SymAnnotation sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + rd_printf("Address : %S", cv_string_sec_off(scratch.arena, sym.seg, sym.off)); rd_printf("Count : %u", sym.count); rd_printf("Annotations:"); @@ -4766,7 +3570,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Offset: %#x", sym.off); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); @@ -4780,7 +3584,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); rd_printf("Register: %S", cv_string_from_reg_id(scratch.arena, arch, sym.reg)); @@ -4793,7 +3597,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); rd_printf("Address: %S", cv_string_from_reg_off(scratch.arena, arch, sym.reg, sym.off)); @@ -4810,7 +3614,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV cursor += str8_deserial_read_array(raw_symbol, cursor, ®s[0], sym.count); String8 name = str8_zero(); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, sym.itype)); cv_print_lvar_attr(arena, out, indent, sym.attr); @@ -4823,12 +3627,12 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV rd_unindent(); } break; case CV_SymKind_MOD_TYPEREF: { - + Assert(!"TODO: test"); CV_SymModTypeRef sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + String8List flags_list = {0}; if (sym.flags & CV_ModTypeRefFlag_None) { str8_list_pushf(scratch.arena, &flags_list, "No TypeRef"); @@ -4850,7 +3654,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV } } String8 flags_str = str8_list_join(scratch.arena, &flags_list, &(StringJoin){.sep=str8_lit(", ")}); - + rd_printf("%S", flags_str); } break; case CV_SymKind_DISCARDED: { @@ -4861,7 +3665,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV U32 symbol_type = 0; cursor += str8_deserial_read_struct(raw_symbol, cursor, &symbol_type); String8 raw_subsym = str8_skip(raw_symbol, cursor); - + rd_printf("Kind : %x", sym.kind); rd_printf("File ID : %x", sym.file_id); rd_printf("File Line Number: %u", sym.file_ln); @@ -4875,7 +3679,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 to = {0}; cursor += str8_deserial_read_cstr(raw_symbol, cursor, &from); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &to); - + rd_printf("From: %S", from); rd_printf("To : %S", to); } break; @@ -4886,7 +3690,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Flags: %#x", sym.flags); rd_printf("Type : %S", cv_string_from_itype(arena, min_itype, sym.itype)); @@ -4896,7 +3700,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV CV_SymArmSwitchTable sym = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); - + rd_printf("Base Address : %S", cv_string_sec_off(scratch.arena, sym.sec_base, sym.off_base)); rd_printf("Branch Address: %S", cv_string_sec_off(scratch.arena, sym.sec_branch, sym.off_branch)); rd_printf("Table Address : %S", cv_string_sec_off(scratch.arena, sym.sec_table, sym.off_table)); @@ -4910,7 +3714,7 @@ cv_print_symbol(Arena *arena, String8List *out, String8 indent, CV_Arch arch, CV String8 name = {0}; cursor += str8_deserial_read_struct(raw_symbol, cursor, &sym); cursor += str8_deserial_read_cstr(raw_symbol, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Flags : %x", sym.flags); rd_printf("IMod : %04x", sym.imod); @@ -5031,7 +3835,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i case CV_LeafKind_BITFIELD: { CV_LeafBitField lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); - + rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); rd_printf("Length : %u", lf.len); rd_printf("Position: %u", lf.pos); @@ -5044,7 +3848,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &size); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Fields : %S", cv_string_from_itype(scratch.arena, min_itype, lf.field_itype)); rd_printf("Properties : %#x (%S)", lf.props, cv_string_from_type_props(scratch.arena, lf.props)); @@ -5063,7 +3867,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Start Index: %x", lf.start_index); rd_printf("Count : %u", lf.count); @@ -5074,7 +3878,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Sig70: %S", string_from_guid(arena, lf.sig70)); rd_printf("Age : %u", lf.age); @@ -5082,7 +3886,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i case CV_LeafKind_BUILDINFO: { CV_LeafBuildInfo lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); - + rd_printf("Entry Count: %u", lf.count); rd_indent(); for (U16 i = 0; i < lf.count; ++i) { @@ -5104,7 +3908,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i case CV_LeafKind_VFUNCTAB: { CV_LeafVFuncTab lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); - + rd_printf("Type: %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); } break; case CV_LeafKind_METHODLIST: { @@ -5149,7 +3953,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Count : %u", lf.count); rd_printf("Type List: %S", cv_string_from_itype(scratch.arena, min_itype, lf.list_itype)); @@ -5162,7 +3966,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &vbptr_off); cursor += cv_read_numeric(raw_leaf, cursor, &vbtable_off); - + rd_printf("Attribs : %#x (%S)", lf.attribs, cv_string_from_field_attribs(scratch.arena, lf.attribs)); rd_printf("Direct Base Type: %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); rd_printf("Virtual Base Ptr: %S", cv_string_from_itype(scratch.arena, min_itype, lf.vbptr_itype)); @@ -5174,7 +3978,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i CV_NumericParsed offset = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &offset); - + rd_printf("Attribs: %#x (%S)", lf.attribs, cv_string_from_field_attribs(scratch.arena, lf.attribs)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); rd_printf("Offset : %S", cv_string_from_numeric(scratch.arena, offset)); @@ -5182,7 +3986,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i case CV_LeafKind_VTSHAPE: { CV_LeafVTShape lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); - + rd_printf("Entry Count: %u", lf.count); rd_indent(); for (U16 i = 0; i < lf.count; ++i) { @@ -5200,7 +4004,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Attribs: %#x (%S)", lf.attribs, cv_string_from_field_attribs(scratch.arena, lf.attribs)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); @@ -5208,7 +4012,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i case CV_LeafKind_MFUNCTION: { CV_LeafMFunction lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); - + rd_printf("Return Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.ret_itype)); rd_printf("Class Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.class_itype)); rd_printf("This Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.this_itype)); @@ -5217,14 +4021,14 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i rd_printf("Argument Count : %u", lf.arg_count); rd_printf("Argument Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.arg_itype)); } break; - #if 0 +#if 0 case CV_LeafKind_SKIP_16t: { CV_LeafSkip_16t lf = {0}; cursor += str8_deserial_read_struct(base, range, cursor, &lf); - + rd_printf("Type: %S", cv_string_from_itype(scratch.arena, min_itype, lf.type)); } break; - #endif +#endif case CV_LeafKind_SKIP: { // ms-symbol-pdf: // This is used by incremental compilers to reserve space for indices. @@ -5238,7 +4042,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Field Count: %u", lf.count); rd_printf("Properties : %#x (%S)", lf.props, cv_string_from_type_props(scratch.arena, lf.props)); @@ -5257,7 +4061,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &value); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Attribs: %S", cv_string_from_field_attribs(scratch.arena, lf.attribs)); rd_printf("Value : %S", cv_string_from_numeric(scratch.arena, value)); @@ -5278,7 +4082,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i case CV_LeafKind_UDT_SRC_LINE: { CV_LeafUDTSrcLine lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); - + rd_printf("Type = %S, Source File = %x, Line = %u", cv_string_from_itype(scratch.arena, min_itype, lf.udt_itype), lf.src_string_id, lf.line); } break; case CV_LeafKind_STRING_ID: { @@ -5286,17 +4090,17 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i String8 string = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &string); - + rd_printf("string : %S", string); rd_printf("Substrings: %S", cv_string_from_itemid(arena, lf.substr_list_id)); // TODO: print actual strings instead } break; case CV_LeafKind_POINTER: { CV_LeafPointer lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); - + CV_PointerKind kind = CV_PointerAttribs_Extract_Kind(lf.attribs); CV_PointerMode mode = CV_PointerAttribs_Extract_Mode(lf.attribs); - + rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); rd_printf("Attribs: %S", cv_string_from_pointer_attribs(arena, lf.attribs)); rd_indent(); @@ -5305,21 +4109,21 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i CV_MemberPointerKind pm = 0; cursor += str8_deserial_read_struct(raw_leaf, cursor, &itype); cursor += str8_deserial_read_struct(raw_leaf, cursor, &pm); - + rd_printf("Class Type: %S", cv_string_from_itype(scratch.arena, min_itype, itype)); rd_printf("Format : %S", cv_string_from_member_pointer_kind(pm)); } else { if (kind == CV_PointerKind_BaseSeg) { U16 seg; cursor += str8_deserial_read_struct(raw_leaf, cursor, &seg); - + rd_printf("Base Segment: %#04x", seg); } else if (kind == CV_PointerKind_BaseType) { CV_TypeIndex base_itype = 0; String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &base_itype); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); - + rd_printf("Base Type: %S", cv_string_from_itype(scratch.arena, min_itype, base_itype)); rd_printf("Name : %S", name); } @@ -5334,7 +4138,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &num); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Field Count: %u", lf.count); rd_printf("Properties : %#x (%S)", lf.props, cv_string_from_type_props(scratch.arena, lf.props)); @@ -5356,7 +4160,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &num); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Field Count : %u", lf.count); rd_printf("Properties : %#x (%S)", lf.props, cv_string_from_type_props(scratch.arena, lf.props)); @@ -5374,7 +4178,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i case CV_LeafKind_ARGLIST: { CV_LeafArgList lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); - + rd_printf("Types %u", lf.count); rd_indent(); for (U32 i = 0; i < lf.count; ++i) { @@ -5387,10 +4191,10 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i case CV_LeafKind_PROCEDURE: { CV_LeafProcedure lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); - + String8 call_kind = cv_string_from_call_kind(lf.call_kind); String8 func_attribs = cv_string_from_function_attribs(scratch.arena, lf.attribs); - + rd_printf("Return type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.ret_itype)); rd_printf("Call Convention : %#x (%S)", lf.call_kind, call_kind); rd_printf("Function Attribs : %#x (%S)", lf.attribs, func_attribs); @@ -5402,7 +4206,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i String8 name = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Scope Type: %#x (%S)", lf.scope_string_id, cv_string_from_itype(scratch.arena, min_itype, lf.scope_string_id)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); @@ -5410,7 +4214,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i case CV_LeafKind_MODIFIER: { CV_LeafModifier lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); - + rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); rd_printf("Flags: %#x (%S)", lf.flags, cv_string_from_modifier_flags(scratch.arena, lf.flags)); } break; @@ -5420,7 +4224,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i CV_NumericParsed num = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &num); - + rd_printf("Entry type: %S", cv_string_from_itype(scratch.arena, min_itype, lf.entry_itype)); rd_printf("Index type: %S", cv_string_from_itype(scratch.arena, min_itype, lf.index_itype)); rd_printf("Length : %S", cv_string_from_numeric(scratch.arena, num)); @@ -5430,7 +4234,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i U16 member_type = 0; cursor += str8_deserial_read_struct(raw_leaf, cursor, &member_type); String8 raw_member = str8_skip(raw_leaf, cursor); - + rd_printf("list[%u] = %S", idx++, cv_string_from_leaf_name(arena, member_type)); rd_indent(); cursor += cv_print_leaf(arena, out, indent, min_itype, member_type, raw_member); @@ -5446,7 +4250,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); cursor += cv_read_numeric(raw_leaf, cursor, &num); cursor += str8_deserial_read_cstr(raw_leaf, cursor, &name); - + rd_printf("Name : %S", name); rd_printf("Attribs: %#x (%S)", lf.attribs, cv_string_from_field_attribs(scratch.arena, lf.attribs)); rd_printf("Type : %S", cv_string_from_itype(scratch.arena, min_itype, lf.itype)); @@ -5455,7 +4259,7 @@ cv_print_leaf(Arena *arena, String8List *out, String8 indent, CV_TypeIndex min_i case CV_LeafKind_LABEL: { CV_LeafLabel lf = {0}; cursor += str8_deserial_read_struct(raw_leaf, cursor, &lf); - + rd_printf("Kind: %S", cv_string_from_label_kind(scratch.arena, lf.kind)); } break; case CV_LeafKind_ENDPRECOMP: { @@ -5575,19 +4379,19 @@ internal void cv_print_symbols_c13(Arena *arena, String8List *out, String8 indent, CV_Arch arch, String8 raw_data) { Temp scratch = scratch_begin(&arena, 1); - + B32 scope_depth = 0; - + for (U64 cursor = 0; cursor < raw_data.size; ) { CV_SymbolHeader header = {0}; cursor += str8_deserial_read_struct(raw_data, cursor, &header); - + if (header.size >= sizeof(header.kind)) { Temp temp = temp_begin(scratch.arena); - + U64 symbol_end = cursor + (header.size - sizeof(header.kind)); String8 raw_symbol = str8_substr(raw_data, rng_1u64(cursor, symbol_end)); - + if (header.kind == CV_SymKind_END || header.kind == CV_SymKind_INLINESITE_END) { if (scope_depth > 0) { rd_unindent(); @@ -5596,25 +4400,25 @@ cv_print_symbols_c13(Arena *arena, String8List *out, String8 indent, CV_Arch arc rd_errorf("unbalanced scopes"); } } - + rd_printf("%S [%04llx-%04llx)", cv_string_from_symbol_type(temp.arena, header.kind), cursor, header.size-sizeof(header.size)); rd_indent(); cv_print_symbol(arena, out, indent, arch, CV_MinComplexTypeIndex, header.kind, raw_symbol); rd_unindent(); - + if (header.kind == CV_SymKind_BLOCK32 || header.kind == CV_SymKind_INLINESITE) { rd_indent(); ++scope_depth; } - + cursor = symbol_end; - + temp_end(temp); } else { rd_errorf("symbol must be at least two bytes long"); } } - + scratch_end(scratch); } @@ -5622,60 +4426,60 @@ internal void cv_print_lines_c13(Arena *arena, String8List *out, String8 indent, String8 raw_lines) { Temp scratch = scratch_begin(&arena, 1); - + U64 cursor = 0; - + CV_C13SubSecLinesHeader header = {0}; cursor += str8_deserial_read_struct(raw_lines, cursor, &header); - + B32 has_columns = !!(header.flags & CV_C13SubSecLinesFlag_HasColumns); if (has_columns) { rd_errorf("TOOD: columns"); } - + rd_printf("%04x:%08x-%08x, flags = %04x", header.sec, header.sec_off, header.len, header.flags); - + for (; cursor < raw_lines.size; ) { CV_C13File file = {0}; cursor += str8_deserial_read_struct(raw_lines, cursor, &file); - + rd_printf("file = %08x, line count = %u, block size %08x", file.file_off, file.num_lines, file.block_size); - + Temp temp = temp_begin(scratch.arena); String8List columns = {0}; for (U32 line_idx = 0; line_idx < file.num_lines; ++line_idx) { CV_C13Line line = {0}; cursor += str8_deserial_read_struct(raw_lines, cursor, &line); - + B32 always_step_in_line_number = line.off == 0xFEEFEE; B32 never_step_in_line_number = line.off == 0xF00F00; - + U32 ln = CV_C13LineFlags_Extract_LineNumber(line.flags); //U32 delta = CV_C13LineFlags_Extract_DeltaToEnd(line.flags); //B32 is_stmt = CV_C13LineFlags_Extract_Statement(line.flags); - + if (always_step_in_line_number || never_step_in_line_number) { str8_list_pushf(temp.arena, &columns, "%x %08X", ln, line.off); } else { str8_list_pushf(temp.arena, &columns, "%5u %08X", ln, line.off); } - + if ((line_idx+1) % 4 == 0 || (line_idx+1) == file.num_lines) { String8 line_str = str8_list_join(scratch.arena, &columns, &(StringJoin){.sep=str8_lit("\t")}); rd_printf("%S", line_str); - + temp_end(temp); temp = temp_begin(scratch.arena); MemoryZeroStruct(&columns); } } temp_end(temp); - + if (cursor < raw_lines.size) { rd_newline(); } } - + scratch_end(scratch); } @@ -5683,31 +4487,31 @@ internal void cv_print_file_checksums(Arena *arena, String8List *out, String8 indent, String8 raw_chksums) { Temp scratch = scratch_begin(&arena, 1); - + rd_printf("%-8s %-8s %-8s %-16s", "File", "Size", "Type", "Checksum"); for (U64 cursor = 0; cursor < raw_chksums.size; ) { CV_C13Checksum chksum = {0}; cursor += str8_deserial_read_struct(raw_chksums, cursor, &chksum); - + Temp temp = temp_begin(scratch.arena); String8 chksum_str = str8_lit("???"); U8 *chksum_ptr = str8_deserial_get_raw_ptr(raw_chksums, cursor, chksum.len); if (chksum_ptr) { chksum_str = rd_format_hex_array(temp.arena, chksum_ptr, chksum.len); } - + rd_printf("%08x %08x %-8S %S", chksum.name_off, chksum.len, cv_string_from_c13_checksum_kind(chksum.kind), chksum_str); - + temp_end(temp); - + cursor += chksum.len; cursor = AlignPow2(cursor, CV_FileCheckSumsAlign); } - + scratch_end(scratch); } @@ -5725,12 +4529,12 @@ internal void cv_print_inlinee_lines(Arena *arena, String8List *out, String8 indent, String8 raw_data) { Temp scratch = scratch_begin(&arena, 1); - + U64 cursor = 0; - + U32 inlinee_sig = ~0u; cursor += str8_deserial_read_struct(raw_data, cursor, &inlinee_sig); - + switch (inlinee_sig) { case CV_C13InlineeLinesSig_NORMAL: { rd_printf("%-8s %-8s %-8s", "Inlinee", "File ID", "Base LN"); @@ -5739,8 +4543,8 @@ cv_print_inlinee_lines(Arena *arena, String8List *out, String8 indent, String8 r cursor += str8_deserial_read_struct(raw_data, cursor, &line); rd_printf("%08x %08x %8u", line.inlinee, line.file_off, line.first_source_ln); } - - } break; + + } break; case CV_C13InlineeLinesSig_EXTRA_FILES: { rd_printf("%-8s %-8s %-8s %s", "Inlinee", "File ID", "Base LN", "Extra FileIDs"); for (; cursor < raw_data.size; ) { @@ -5750,7 +4554,7 @@ cv_print_inlinee_lines(Arena *arena, String8List *out, String8 indent, String8 r U32 extra_file_count = 0; cursor += str8_deserial_read_struct(raw_data, cursor, &line); cursor += str8_deserial_read_struct(raw_data, cursor, &extra_file_count); - + String8List extra_files_list = {0}; for (U32 i = 0; i < extra_file_count; ++i) { U32 file_id = 0; @@ -5758,30 +4562,30 @@ cv_print_inlinee_lines(Arena *arena, String8List *out, String8 indent, String8 r str8_list_pushf(temp.arena, &extra_files_list, "%08x", file_id); } String8 extra_files = str8_list_join(temp.arena, &extra_files_list, &(StringJoin){.sep=str8_lit(" ,")}); - + rd_printf("%08x %08x %u %S", line.inlinee, line.file_off, line.first_source_ln, extra_files); - + temp_end(temp); } } break; } - + scratch_end(scratch); } internal void cv_print_symbols_section(Arena *arena, - String8List *out, - String8 indent, - CV_Arch arch, - String8 raw_ss) + String8List *out, + String8 indent, + CV_Arch arch, + String8 raw_ss) { Temp scratch = scratch_begin(&arena, 1); - + U64 cursor = 0; U32 cv_sig = 0; cursor += str8_deserial_read_struct(raw_ss, cursor, &cv_sig); - + for (; cursor < raw_ss.size; ) { U64 sst_offset = 0; CV_C13SubSectionHeader ss_header = {0}; @@ -5804,11 +4608,11 @@ cv_print_symbols_section(Arena *arena, ss_ver = "C13"; } break; } - + U64 sst_end = cursor + ss_header.size; String8 raw_sst = str8_substr(raw_ss, rng_1u64(cursor, sst_end)); cursor = AlignPow2(sst_end, CV_C13SubSectionAlign); - + rd_printf("# %S %s [%llx-%llx)", cv_string_from_c13_subsection_kind(ss_header.kind), ss_ver, sst_offset, sst_end); rd_indent(); switch (ss_header.kind) { @@ -5848,7 +4652,7 @@ cv_print_symbols_section(Arena *arena, } rd_unindent(); } - + scratch_end(scratch); } @@ -5905,7 +4709,7 @@ cv_format_debug_sections(Arena *arena, String8List *out, String8 indent, String8 } } } - + for (U64 i = 0; i < section_count; ++i) { COFF_SectionHeader *header = §ions[i]; String8 sect_name = coff_name_from_section_header(string_table, header); @@ -5920,7 +4724,7 @@ cv_format_debug_sections(Arena *arena, String8List *out, String8 indent, String8 Temp scratch = scratch_begin(&arena, 1); CV_Signature sig = 0; str8_deserial_read_struct(raw_sect, 0, &sig); - + String8 raw_types = str8_skip(raw_sect, sizeof(sig)); CV_DebugT debug_t = {0}; if (sig == CV_Signature_C13) { @@ -5928,7 +4732,7 @@ cv_format_debug_sections(Arena *arena, String8List *out, String8 indent, String8 } else { NotImplemented; } - + rd_printf("# .debug$T No. %llx", i+1); rd_indent(); cv_print_debug_t(arena, out, indent, debug_t); @@ -5945,28 +4749,28 @@ coff_print_archive_member_header(Arena *arena, String8List *out, String8 indent, { 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) + 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; @@ -5983,38 +4787,38 @@ coff_print_section_table(Arena *arena, } 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"); - + "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}; @@ -6027,7 +4831,7 @@ coff_print_section_table(Arena *arena, 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"); @@ -6038,7 +4842,7 @@ coff_print_section_table(Arena *arena, 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"); @@ -6058,7 +4862,7 @@ coff_print_section_table(Arena *arena, 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"); @@ -6075,7 +4879,7 @@ coff_print_section_table(Arena *arena, 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"); @@ -6083,27 +4887,27 @@ coff_print_section_table(Arena *arena, 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 ); @@ -6122,17 +4926,17 @@ coff_print_section_table(Arena *arena, } 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(); @@ -6142,11 +4946,11 @@ coff_print_section_table(Arena *arena, 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); } @@ -6171,7 +4975,7 @@ coff_disasm_sections(Arena *arena, 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); @@ -6198,7 +5002,7 @@ coff_raw_data_sections(Arena *arena, 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); @@ -6211,100 +5015,100 @@ coff_raw_data_sections(Arena *arena, 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) + 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) + 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"); - + "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); @@ -6318,7 +5122,7 @@ coff_print_symbol_table(Arena *arena, 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 ); @@ -6328,10 +5132,10 @@ coff_print_symbol_table(Arena *arena, 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]; @@ -6339,7 +5143,7 @@ coff_print_symbol_table(Arena *arena, 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); + 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; @@ -6364,10 +5168,10 @@ coff_print_symbol_table(Arena *arena, } 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); + 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); + sd->length, sd->number_of_relocations, sd->number_of_ln, sd->check_sum); } } break; default: { @@ -6375,15 +5179,15 @@ coff_print_symbol_table(Arena *arena, } break; } } - + i += symbol->aux_symbol_count; rd_unindent(); } - + rd_unindent(); rd_newline(); } - + scratch_end(scratch); } @@ -6391,10 +5195,10 @@ 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); @@ -6403,7 +5207,7 @@ coff_print_big_obj_header(Arena *arena, String8List *out, String8 indent, COFF_B rd_printf("Symbol Table : %#x", header->symbol_table_foff); rd_printf("Symbol Count : %u", header->symbol_count ); rd_unindent(); - + scratch_end(scratch); } @@ -6411,11 +5215,11 @@ 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 ); @@ -6426,7 +5230,7 @@ coff_print_file_header(Arena *arena, String8List *out, String8 indent, COFF_File 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); } @@ -6434,10 +5238,10 @@ 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 ); @@ -6450,7 +5254,7 @@ coff_print_import(Arena *arena, String8List *out, String8 indent, COFF_ParsedArc rd_printf("Function : %S", header->func_name ); rd_printf("DLL : %S", header->dll_name ); rd_unindent(); - + scratch_end(scratch); } @@ -6458,26 +5262,26 @@ 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; @@ -6488,27 +5292,27 @@ coff_print_big_obj(Arena *arena, String8List *out, String8 indent, String8 raw_d goto exit; } if (contains_1u64(symbols_range, sect_headers_range.min) || - contains_1u64(symbols_range, sect_headers_range.max)) { + 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:; + + exit:; scratch_end(scratch); } @@ -6516,27 +5320,27 @@ 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; @@ -6547,50 +5351,50 @@ coff_print_obj(Arena *arena, String8List *out, String8 indent, String8 raw_data, goto exit; } if (contains_1u64(symbols_range, sect_headers_range.min) || - contains_1u64(symbols_range, sect_headers_range.max)) { + 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, Image_CoffPe); + dw_format(arena, out, indent, opts, &dwarf_input, arch, ExecutableImageKind_CoffPe); } - -exit:; + + exit:; scratch_end(scratch); } @@ -6598,30 +5402,30 @@ 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); @@ -6629,24 +5433,24 @@ coff_print_archive(Arena *arena, String8List *out, String8 indent, String8 raw_a } 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) { @@ -6664,29 +5468,29 @@ coff_print_archive(Arena *arena, String8List *out, String8 indent, String8 raw_a } } else { rd_errorf("Symbol index count %u doesn't match symbol count %u", - second_member.symbol_index_count, second_member.symbol_count); + 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) { @@ -6704,25 +5508,25 @@ coff_print_archive(Arena *arena, String8List *out, String8 indent, String8 raw_a 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); @@ -6745,13 +5549,13 @@ coff_print_archive(Arena *arena, String8List *out, String8 indent, String8 raw_a rd_errorf("unknown member format", member_offset); } break; } - + rd_unindent(); rd_newline(); } - + rd_unindent(); - + scratch_end(scratch); } @@ -6799,7 +5603,7 @@ pe_print_optional_header32(Arena *arena, String8List *out, String8 indent, PE_Op Temp scratch = scratch_begin(&arena, 1); String8 subsystem = pe_string_from_subsystem(opt_header->subsystem); String8 dll_chars = pe_string_from_dll_characteristics(scratch.arena, opt_header->dll_characteristics); - + rd_printf("# PE Optional Header 32"); rd_indent(); rd_printf("Magic : %#x", opt_header->magic); @@ -6829,10 +5633,10 @@ pe_print_optional_header32(Arena *arena, String8List *out, String8 indent, PE_Op rd_printf("Loader flags : %#x", opt_header->loader_flags); rd_printf("RVA and offset count : %u", opt_header->data_dir_count); rd_newline(); - + pe_print_data_directory_ranges(arena, out, indent, opt_header->data_dir_count, dirs); rd_newline(); - + rd_unindent(); scratch_end(scratch); } @@ -6843,7 +5647,7 @@ pe_print_optional_header32plus(Arena *arena, String8List *out, String8 indent, P Temp scratch = scratch_begin(&arena, 1); String8 subsystem = pe_string_from_subsystem(opt_header->subsystem); String8 dll_chars = pe_string_from_dll_characteristics(scratch.arena, opt_header->dll_characteristics); - + rd_printf("# PE Optional Header 32+"); rd_indent(); rd_printf("Magic : %#x", opt_header->magic); @@ -6872,10 +5676,10 @@ pe_print_optional_header32plus(Arena *arena, String8List *out, String8 indent, P rd_printf("Loader flags : %#x", opt_header->loader_flags); rd_printf("RVA and offset count : %u", opt_header->data_dir_count); rd_newline(); - + pe_print_data_directory_ranges(arena, out, indent, opt_header->data_dir_count, dirs); rd_newline(); - + rd_unindent(); scratch_end(scratch); } @@ -6884,14 +5688,14 @@ internal void pe_print_load_config32(Arena *arena, String8List *out, String8 indent, PE_LoadConfig32 *lc) { Temp scratch = scratch_begin(&arena, 1); - + String8 time_stamp = coff_string_from_time_stamp(scratch.arena, lc->time_stamp); String8 global_flag_clear = pe_string_from_global_flags(scratch.arena, lc->global_flag_clear); String8 global_flag_set = pe_string_from_global_flags(scratch.arena, lc->global_flag_set); - + rd_printf("# Load Config 32"); rd_indent(); - + rd_printf("Size: %m", lc->size); rd_printf("Time stamp: %#x (%S)", lc->time_stamp, time_stamp); rd_printf("Version: %u.%u", lc->major_version, lc->minor_version); @@ -6912,14 +5716,14 @@ pe_print_load_config32(Arena *arena, String8List *out, String8 indent, PE_LoadCo goto exit; } rd_newline(); - + rd_printf("SEH Handler Table: %#x", lc->seh_handler_table); rd_printf("SEH Handler Count: %u", lc->seh_handler_count); if (lc->size < OffsetOf(PE_LoadConfig64, guard_cf_check_func_ptr)) { goto exit; } rd_newline(); - + rd_printf("Guard CF Check Function: %#x", lc->guard_cf_check_func_ptr); rd_printf("Guard CF Dispatch Function: %#x", lc->guard_cf_dispatch_func_ptr); rd_printf("Guard CF Function Table: %#x", lc->guard_cf_func_table); @@ -6929,9 +5733,9 @@ pe_print_load_config32(Arena *arena, String8List *out, String8 indent, PE_LoadCo goto exit; } rd_newline(); - + rd_printf("Code integrity: { Flags = %#x, Catalog = %#x, Catalog Offset = %#x }", - lc->code_integrity.flags, lc->code_integrity.catalog, lc->code_integrity.catalog_offset); + lc->code_integrity.flags, lc->code_integrity.catalog, lc->code_integrity.catalog_offset); rd_printf("Guard address taken IAT entry table: %#x", lc->guard_address_taken_iat_entry_table); rd_printf("Guard address taken IAT entry count: %u", lc->guard_address_taken_iat_entry_count); rd_printf("Guard long jump target table: %#x", lc->guard_long_jump_target_table); @@ -6948,7 +5752,7 @@ pe_print_load_config32(Arena *arena, String8List *out, String8 indent, PE_LoadCo goto exit; } rd_newline(); - + rd_printf("Enclave config ptr: %#x", lc->enclave_config_ptr); rd_printf("Volatile metadata ptr: %#x", lc->volatile_metadata_ptr); rd_printf("Guard EH continuation table: %#x", lc->guard_eh_continue_table); @@ -6958,8 +5762,8 @@ pe_print_load_config32(Arena *arena, String8List *out, String8 indent, PE_LoadCo rd_printf("Guard XFG table dispatch func ptr: %#x", lc->guard_xfg_table_dispatch_func_ptr); rd_printf("Cast guard OS determined failure mode: %#x", lc->cast_guard_os_determined_failure_mode); rd_newline(); - -exit:; + + exit:; rd_unindent(); scratch_end(scratch); } @@ -6968,14 +5772,14 @@ internal void pe_print_load_config64(Arena *arena, String8List *out, String8 indent, PE_LoadConfig64 *lc) { Temp scratch = scratch_begin(&arena, 1); - + String8 time_stamp = coff_string_from_time_stamp(scratch.arena, lc->time_stamp); String8 global_flag_clear = pe_string_from_global_flags(scratch.arena, lc->global_flag_clear); String8 global_flag_set = pe_string_from_global_flags(scratch.arena, lc->global_flag_set); - + rd_printf("# Load Config 64"); rd_indent(); - + rd_printf("Size: %m", lc->size); rd_printf("Time stamp: %#x (%S)", lc->time_stamp, time_stamp); rd_printf("Version: %u.%u", lc->major_version, lc->minor_version); @@ -6996,14 +5800,14 @@ pe_print_load_config64(Arena *arena, String8List *out, String8 indent, PE_LoadCo goto exit; } rd_newline(); - + rd_printf("SEH Handler Table: %#llx", lc->seh_handler_table); rd_printf("SEH Handler Count: %llu", lc->seh_handler_count); if (lc->size < OffsetOf(PE_LoadConfig64, guard_cf_check_func_ptr)) { goto exit; } rd_newline(); - + rd_printf("Guard CF Check Function: %#llx", lc->guard_cf_check_func_ptr); rd_printf("Guard CF Dispatch Function: %#llx", lc->guard_cf_dispatch_func_ptr); rd_printf("Guard CF Function Table: %#llx", lc->guard_cf_func_table); @@ -7013,9 +5817,9 @@ pe_print_load_config64(Arena *arena, String8List *out, String8 indent, PE_LoadCo goto exit; } rd_newline(); - + rd_printf("Code integrity: { Flags = %#x, Catalog = %#x, Catalog Offset = %#x }", - lc->code_integrity.flags, lc->code_integrity.catalog, lc->code_integrity.catalog_offset); + lc->code_integrity.flags, lc->code_integrity.catalog, lc->code_integrity.catalog_offset); rd_printf("Guard address taken IAT entry table: %#llx", lc->guard_address_taken_iat_entry_table); rd_printf("Guard address taken IAT entry count: %llu", lc->guard_address_taken_iat_entry_count); rd_printf("Guard long jump target table: %#llx", lc->guard_long_jump_target_table); @@ -7032,7 +5836,7 @@ pe_print_load_config64(Arena *arena, String8List *out, String8 indent, PE_LoadCo goto exit; } rd_newline(); - + rd_printf("Enclave config ptr: %#llx", lc->enclave_config_ptr); rd_printf("Volatile metadata ptr: %#llx", lc->volatile_metadata_ptr); rd_printf("Guard EH continuation table: %#llx", lc->guard_eh_continue_table); @@ -7042,8 +5846,8 @@ pe_print_load_config64(Arena *arena, String8List *out, String8 indent, PE_LoadCo rd_printf("Guard XFG table dispatch func ptr: %#llx", lc->guard_xfg_table_dispatch_func_ptr); rd_printf("Cast guard OS determined failure mode: %#llx", lc->cast_guard_os_determined_failure_mode); rd_newline(); - -exit:; + + exit:; rd_unindent(); scratch_end(scratch); } @@ -7052,10 +5856,10 @@ internal void pe_print_tls(Arena *arena, String8List *out, String8 indent, PE_ParsedTLS tls) { Temp scratch = scratch_begin(&arena, 1); - + rd_printf("# TLS"); rd_indent(); - + String8 tls_chars = coff_string_from_section_flags(scratch.arena, tls.header.characteristics); rd_printf("Raw data start: %#llx", tls.header.raw_data_start); rd_printf("Raw data end: %#llx", tls.header.raw_data_end); @@ -7063,7 +5867,7 @@ pe_print_tls(Arena *arena, String8List *out, String8 indent, PE_ParsedTLS tls) rd_printf("Callbacks address: %#llx", tls.header.callbacks_address); rd_printf("Zero-fill size: %m", tls.header.zero_fill_size); rd_printf("Characteristics: %S", tls_chars); - + if (tls.callback_count) { rd_newline(); rd_printf("## Callbacks"); @@ -7073,10 +5877,10 @@ pe_print_tls(Arena *arena, String8List *out, String8 indent, PE_ParsedTLS tls) } rd_unindent(); } - + rd_unindent(); rd_newline(); - + scratch_end(scratch); } @@ -7084,22 +5888,22 @@ internal void pe_print_debug_diretory(Arena *arena, String8List *out, String8 indent, String8 raw_data, String8 raw_dir) { Temp scratch = scratch_begin(&arena, 1); - + rd_printf("# Debug Directory"); rd_indent(); - - PE_DebugInfoList debug_info_list = pe_parse_debug_directory(scratch.arena, raw_data, raw_dir); + + PE_DebugInfoList debug_info_list = pe_debug_info_list_from_raw_debug_dir(scratch.arena, raw_data, raw_dir); U64 i = 0; for (PE_DebugInfoNode *entry = debug_info_list.first; entry != 0; entry = entry->next, ++i) { PE_DebugInfo *de = &entry->v; - + if (entry != debug_info_list.first) { rd_newline(); } - + rd_printf("Entry[%llu]", i); rd_indent(); - + // print header rd_printf("Characteristics: %#x", de->header.characteristics); rd_printf("Time Stamp: %S", coff_string_from_time_stamp(scratch.arena, de->header.time_stamp)); @@ -7109,7 +5913,7 @@ pe_print_debug_diretory(Arena *arena, String8List *out, String8 indent, String8 rd_printf("Data virt off: %#x", de->header.voff); rd_printf("Data file off: %#x", de->header.foff); rd_newline(); - + // print directory contents rd_indent(); switch (de->header.type) { @@ -7127,20 +5931,20 @@ pe_print_debug_diretory(Arena *arena, String8List *out, String8 indent, String8 } break; case PE_DebugDirectoryType_COFF_GROUP: { U64 off = 0; - + // TODO: is this version? U32 unknown = 0; off += str8_deserial_read_struct(de->u.raw_data, off, &unknown); if (unknown != 0) { rd_printf("TODO: unknown: %u", unknown); } - + rd_printf("%-8s %-8s %-8s", "VOFF", "Size", "Name"); for (; off < de->u.raw_data.size; ) { U32 voff = 0; U32 size = 0; String8 name = str8_zero(); - + off += str8_deserial_read_struct(de->u.raw_data, off, &voff); off += str8_deserial_read_struct(de->u.raw_data, off, &size); if (voff == 0 && size == 0) { @@ -7148,7 +5952,7 @@ pe_print_debug_diretory(Arena *arena, String8List *out, String8 indent, String8 } off += str8_deserial_read_cstr(de->u.raw_data, off, &name); off = AlignPow2(off, 4); - + rd_printf("%08x %08x %S", voff, size, name); } } break; @@ -7171,10 +5975,10 @@ pe_print_debug_diretory(Arena *arena, String8List *out, String8 indent, String8 U8 saved_regs_size = PE_FPOEncoded_Extract_SAVED_REGS_SIZE(fpo->flags); PE_FPOType type = PE_FPOEncoded_Extract_FRAME_TYPE(fpo->flags); PE_FPOFlags flags = PE_FPOEncoded_Extract_FLAGS(fpo->flags); - + String8 type_string = pe_string_from_fpo_type(type); String8 flags_string = pe_string_from_fpo_flags(scratch.arena, flags); - + rd_printf("Function offset: %#x", fpo->func_code_off); rd_printf("Function size: %#x", fpo->func_size); rd_printf("Locals size: %u", fpo->locals_size); @@ -7191,21 +5995,21 @@ pe_print_debug_diretory(Arena *arena, String8List *out, String8 indent, String8 switch (de->u.codeview.magic) { case PE_CODEVIEW_PDB20_MAGIC: { PE_CvHeaderPDB20 *header = &de->u.codeview.pdb20.header; - + rd_printf("Time stamp: %S", coff_string_from_time_stamp(scratch.arena, header->time_stamp)); rd_printf("Age: %u", header->age); rd_printf("Name: %S", de->u.codeview.pdb20.path); } break; case PE_CODEVIEW_PDB70_MAGIC: { PE_CvHeaderPDB70 *header = &de->u.codeview.pdb70.header; - + rd_printf("GUID: %S", string_from_guid(scratch.arena, header->guid)); rd_printf("Age: %u", header->age); rd_printf("Name: %S", de->u.codeview.pdb70.path); } break; case PE_CODEVIEW_RDI_MAGIC: { PE_CvHeaderRDI *header = &de->u.codeview.rdi.header; - + rd_printf("GUID: %S", string_from_guid(scratch.arena, header->guid)); rd_printf("Name: %S", de->u.codeview.rdi.path); } break; @@ -7218,11 +6022,11 @@ pe_print_debug_diretory(Arena *arena, String8List *out, String8 indent, String8 PE_DebugMisc *misc = str8_deserial_get_raw_ptr(de->u.raw_data, 0, sizeof(*misc)); String8 type_string = pe_string_from_misc_type(misc->data_type); - + rd_printf("Data type: %S", type_string); rd_printf("Size: %u", misc->size); rd_printf("Unicode: %u", misc->unicode); - + switch (misc->data_type) { case PE_DebugMiscType_EXE_NAME: { String8 name; @@ -7238,10 +6042,10 @@ pe_print_debug_diretory(Arena *arena, String8List *out, String8 indent, String8 rd_unindent(); rd_unindent(); } - + rd_unindent(); rd_newline(); - + scratch_end(scratch); } @@ -7249,20 +6053,20 @@ internal void pe_print_export_table(Arena *arena, String8List *out, String8 indent, PE_ParsedExportTable exptab) { Temp scratch = scratch_begin(&arena, 1); - + String8 time_stamp = coff_string_from_time_stamp(scratch.arena, exptab.time_stamp); - + rd_printf("# Export Table"); rd_indent(); - + rd_printf("Characteristics: %u", exptab.flags); rd_printf("Time stamp: %S", time_stamp); rd_printf("Version: %u.%02u", exptab.major_ver, exptab.minor_ver); rd_printf("Ordinal base: %u", exptab.ordinal_base); rd_printf(""); - + rd_printf("%-4s %-8s %-8s %-8s", "No.", "Oridnal", "VOff", "Name"); - + for (U64 i = 0; i < exptab.export_count; ++i) { PE_ParsedExport *exp = exptab.exports+i; if (exp->forwarder.size) { @@ -7271,7 +6075,7 @@ pe_print_export_table(Arena *arena, String8List *out, String8 indent, PE_ParsedE rd_printf("%4u %8u %8x %S", i, exp->ordinal, exp->voff, exp->name); } } - + rd_unindent(); scratch_end(scratch); } @@ -7280,19 +6084,19 @@ internal void pe_print_static_import_table(Arena *arena, String8List *out, String8 indent, U64 image_base, PE_ParsedStaticImportTable imptab) { Temp scratch = scratch_begin(&arena, 1); - + if (imptab.count) { rd_printf("# Import Table"); rd_indent(); for (U64 dll_idx = 0; dll_idx < imptab.count; ++dll_idx) { PE_ParsedStaticDLLImport *dll = imptab.v+dll_idx; - + rd_printf("Name: %S", dll->name); rd_printf("Import address table: %#llx", image_base + dll->import_address_table_voff); rd_printf("Import name table: %#llx", image_base + dll->import_name_table_voff); rd_printf("Time stamp: %#x", dll->time_stamp); rd_newline(); - + if (dll->import_count) { rd_indent(); for (U64 imp_idx = 0; imp_idx < dll->import_count; ++imp_idx) { @@ -7309,7 +6113,7 @@ pe_print_static_import_table(Arena *arena, String8List *out, String8 indent, U64 } rd_unindent(); } - + scratch_end(scratch); } @@ -7320,10 +6124,10 @@ pe_print_delay_import_table(Arena *arena, String8List *out, String8 indent, U64 Temp scratch = scratch_begin(&arena, 1); rd_printf("# Delay Import Table"); rd_indent(); - + for (U64 dll_idx = 0; dll_idx < imptab.count; ++dll_idx) { PE_ParsedDelayDLLImport *dll = imptab.v+dll_idx; - + rd_printf("Attributes: %#08x", dll->attributes); rd_printf("Name: %S", dll->name); rd_printf("HMODULE address: %#llx", image_base + dll->module_handle_voff); @@ -7333,23 +6137,23 @@ pe_print_delay_import_table(Arena *arena, String8List *out, String8 indent, U64 rd_printf("Unload import name table: %#llx", image_base + dll->unload_table_voff); rd_printf("Time stamp: %#x", dll->time_stamp); rd_newline(); - + rd_indent(); for (U64 imp_idx = 0; imp_idx < dll->import_count; ++imp_idx) { PE_ParsedImport *imp = dll->imports+imp_idx; - + String8 bound = str8_lit("NULL"); if (imp_idx < dll->bound_table_count) { U64 bound_addr = dll->bound_table[imp_idx]; bound = push_str8f(scratch.arena, "%#llx", bound_addr); } - + String8 unload = str8_lit("NULL"); if (imp_idx < dll->unload_table_count) { U64 unload_addr = dll->unload_table[imp_idx]; unload = push_str8f(scratch.arena, "%#llx", unload_addr); } - + if (imp->type == PE_ParsedImport_Ordinal) { rd_printf("%-16S %-16S %#-4x", bound, unload, imp->u.ordinal); } else if (imp->type == PE_ParsedImport_Name) { @@ -7357,10 +6161,10 @@ pe_print_delay_import_table(Arena *arena, String8List *out, String8 indent, U64 } } rd_unindent(); - + rd_newline(); } - + rd_unindent(); scratch_end(scratch); } @@ -7370,7 +6174,7 @@ internal void pe_print_resources(Arena *arena, String8List *out, String8 indent, PE_ResourceDir *root) { Temp scratch = scratch_begin(&arena, 1); - + // setup stack struct stack_s { struct stack_s *next; @@ -7391,10 +6195,10 @@ pe_print_resources(Arena *arena, String8List *out, String8 indent, PE_ResourceDi stack->dir_name = str8_lit("ROOT"); stack->curr_name_node = root->named_list.first; stack->curr_id_node = root->id_list.first; - + if (stack) { rd_printf("# Resources"); - + // traverse resource tree while (stack) { if (stack->print_table) { @@ -7403,33 +6207,33 @@ pe_print_resources(Arena *arena, String8List *out, String8 indent, PE_ResourceDi if (stack->is_named) { rd_printf("[%u] %S { Time Stamp: %u, Version %u.%u Name Count: %u, ID Count %u, Characteristics: %u }", + stack->dir_idx, + stack->dir_name, + stack->table->time_stamp, + stack->table->major_version, stack->table->minor_version, + stack->table->named_list.count, stack->table->id_list.count, + stack->table->characteristics); + } else { + B32 is_actually_leaf = stack->table->id_list.count == 1 && + stack->table->id_list.first->data.kind != PE_ResDataKind_DIR; + if (is_actually_leaf) { + rd_printf("[%u] %u { Time Stamp: %u, Version %u.%u Name Count: %u, ID Count %u, Characteristics: %u }", stack->dir_idx, - stack->dir_name, + stack->dir_id, stack->table->time_stamp, stack->table->major_version, stack->table->minor_version, stack->table->named_list.count, stack->table->id_list.count, stack->table->characteristics); - } else { - B32 is_actually_leaf = stack->table->id_list.count == 1 && - stack->table->id_list.first->data.kind != PE_ResDataKind_DIR; - if (is_actually_leaf) { - rd_printf("[%u] %u { Time Stamp: %u, Version %u.%u Name Count: %u, ID Count %u, Characteristics: %u }", - stack->dir_idx, - stack->dir_id, - stack->table->time_stamp, - stack->table->major_version, stack->table->minor_version, - stack->table->named_list.count, stack->table->id_list.count, - stack->table->characteristics); } else { String8 id_str = pe_resource_kind_to_string(stack->dir_id); rd_printf("[%u] %S { Time Stamp: %u, Version %u.%u Name Count: %u, ID Count %u, Characteristics: %u }", - stack->dir_idx, - id_str, - stack->dir_id, - stack->table->time_stamp, - stack->table->major_version, stack->table->minor_version, - stack->table->named_list.count, stack->table->id_list.count, - stack->table->characteristics); + stack->dir_idx, + id_str, + stack->dir_id, + stack->table->time_stamp, + stack->table->major_version, stack->table->minor_version, + stack->table->named_list.count, stack->table->id_list.count, + stack->table->characteristics); } } } @@ -7454,12 +6258,12 @@ pe_print_resources(Arena *arena, String8List *out, String8 indent, PE_ResourceDi } else if (res->kind == PE_ResDataKind_COFF_LEAF) { COFF_ResourceDataEntry *entry = &res->u.leaf; rd_printf("[%u] %S Data VOFF: %#08x, Data Size: %#08x, Code Page: %u", - name_idx, res->id.u.string, entry->data_voff, entry->data_size, entry->code_page); + name_idx, res->id.u.string, entry->data_voff, entry->data_size, entry->code_page); } else { InvalidPath; } } - + while (stack->curr_id_node) { PE_ResourceNode *id_node = stack->curr_id_node; PE_Resource *res = &id_node->data; @@ -7483,58 +6287,58 @@ pe_print_resources(Arena *arena, String8List *out, String8 indent, PE_ResourceDi InvalidPath; } } - + if (stack->curr_id_node == 0 && stack->curr_name_node == 0) { rd_unindent(); } - + SLLStackPop(stack); yield:; } - + rd_newline(); } - + scratch_end(scratch); } internal void pe_print_exceptions_x8664(Arena *arena, - String8List *out, - String8 indent, - U64 section_count, - COFF_SectionHeader *sections, - String8 raw_data, - Rng1U64 except_frange, - RDI_Parsed *rdi) + String8List *out, + String8 indent, + U64 section_count, + COFF_SectionHeader *sections, + String8 raw_data, + Rng1U64 except_frange, + RDI_Parsed *rdi) { Temp scratch = scratch_begin(&arena, 1); - + String8 raw_except = str8_substr(raw_data, except_frange); U64 count = raw_except.size / sizeof(PE_IntelPdata); for (U64 i = 0; i < count; ++i) { Temp temp = temp_begin(scratch.arena); - + U64 pdata_offset = i * sizeof(PE_IntelPdata); PE_IntelPdata *pdata = str8_deserial_get_raw_ptr(raw_except, pdata_offset, sizeof(*pdata)); String8 pdata_name = rd_proc_name_from_voff(rdi, pdata->voff_first); - + U64 unwind_info_offset = coff_foff_from_voff(sections, section_count, pdata->voff_unwind_info); PE_UnwindInfo *uwinfo = str8_deserial_get_raw_ptr(raw_data, unwind_info_offset, sizeof(*uwinfo)); - + U8 version = PE_UNWIND_INFO_VERSION_FROM_HDR(uwinfo->header); U8 flags = PE_UNWIND_INFO_FLAGS_FROM_HDR(uwinfo->header); U8 frame_register = PE_UNWIND_INFO_REG_FROM_FRAME(uwinfo->frame); U8 frame_offset = PE_UNWIND_INFO_OFF_FROM_FRAME(uwinfo->frame); - + B32 is_chained = (flags & PE_UnwindInfoFlag_CHAINED) != 0; B32 has_handler_data = !is_chained && (flags & (PE_UnwindInfoFlag_EHANDLER | PE_UnwindInfoFlag_UHANDLER)) != 0; - + String8 flags_str = str8_zero(); { U64 f = flags; - + String8List flags_list = {0}; if (f & PE_UnwindInfoFlag_EHANDLER) { f &= ~PE_UnwindInfoFlag_EHANDLER; @@ -7556,20 +6360,20 @@ pe_print_exceptions_x8664(Arena *arena, } flags_str = str8_list_join(scratch.arena, &flags_list, &(StringJoin){.sep=str8_lit(", ")}); } - + U64 codes_offset = unwind_info_offset + sizeof(PE_UnwindInfo); PE_UnwindCode *code_ptr = str8_deserial_get_raw_ptr(raw_data, codes_offset, sizeof(*code_ptr) * uwinfo->codes_num); PE_UnwindCode *code_opl = code_ptr + uwinfo->codes_num; - + if (i > 0) { rd_newline(); } rd_printf("%08x %08x %08x %08x%s%S", - pdata_offset, - pdata->voff_first, - pdata->voff_one_past_last, - pdata->voff_unwind_info, - pdata_name.size ? " " : "", pdata_name); + pdata_offset, + pdata->voff_first, + pdata->voff_one_past_last, + pdata->voff_unwind_info, + pdata_name.size ? " " : "", pdata_name); rd_printf("Version: %u", version); rd_printf("Flags: %S", flags_str); rd_printf("Prolog Size: %#x", uwinfo->prolog_size); @@ -7580,10 +6384,10 @@ pe_print_exceptions_x8664(Arena *arena, for (; code_ptr < code_opl;) { Temp code_temp = temp_begin(scratch.arena); String8List code_list = {0}; - + U8 operation_code = PE_UNWIND_OPCODE_FROM_FLAGS(code_ptr[0].flags); U8 operation_info = PE_UNWIND_INFO_FROM_FLAGS(code_ptr[0].flags); - + str8_list_pushf(code_temp.arena, &code_list, "%#04x:", code_ptr[0].off_in_prolog); switch (operation_code) { case PE_UnwindOpCode_PUSH_NONVOL: { @@ -7657,35 +6461,35 @@ pe_print_exceptions_x8664(Arena *arena, code_ptr += 1; } break; } - + String8 code_line = str8_list_join(code_temp.arena, &code_list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", code_line); - + temp_end(code_temp); } rd_unindent(); - + if (is_chained) { U64 next_pdata_offset = codes_offset + sizeof(PE_UnwindCode) * AlignPow2(uwinfo->codes_num, 2); PE_IntelPdata *next_pdata = str8_deserial_get_raw_ptr(raw_data, next_pdata_offset, sizeof(*next_pdata)); rd_printf("Chained: %#08x %#08x %#08x", next_pdata->voff_first, next_pdata->voff_one_past_last, next_pdata->voff_unwind_info); } - + if (has_handler_data) { #define ExceptionHandlerDataFlag_FuncInfo (1 << 0) #define ExceptionHandlerDataFlag_FuncInfo4 (1 << 1) #define ExceptionHandlerDataFlag_ScopeTable (1 << 2) #define ExceptionHandlerDataFlag_GS (1 << 3u) - + U64 actual_code_count = PE_UNWIND_INFO_GET_CODE_COUNT(uwinfo->codes_num); U64 read_cursor = codes_offset + actual_code_count * sizeof(PE_UnwindCode); - + U32 handler = 0; read_cursor += str8_deserial_read_struct(raw_data, read_cursor, &handler); - + String8 handler_name = rd_proc_name_from_voff(rdi, handler); rd_printf("Handler: %#llx%s%S", handler, handler_name.size ? " " : "", handler_name); - + U32 handler_data_flags = 0; if (str8_match_lit("__GSHandlerCheck_EH4", handler_name, 0)) { handler_data_flags = ExceptionHandlerDataFlag_FuncInfo4; @@ -7702,11 +6506,11 @@ pe_print_exceptions_x8664(Arena *arena, } else if (str8_match_lit("__GSHandlerCheck_EH", handler_name, 0)) { handler_data_flags = ExceptionHandlerDataFlag_FuncInfo|ExceptionHandlerDataFlag_GS; } - + if (handler_data_flags & ExceptionHandlerDataFlag_FuncInfo) { MSCRT_FuncInfo func_info; read_cursor += mscrt_parse_func_info(arena, raw_data, section_count, sections, read_cursor, &func_info); - + rd_printf("Function Info:"); rd_indent(); rd_printf("Magic: %#x", func_info.magic); @@ -7716,7 +6520,7 @@ pe_print_exceptions_x8664(Arena *arena, rd_printf("Frame Offset Unwind Helper: %#x", func_info.frame_offset_unwind_helper); rd_printf("ES Flags: %#x", func_info.eh_flags); rd_unindent(); - + if (func_info.ip_map_count > 0) { rd_printf("IP to State Map:"); rd_indent(); @@ -7728,7 +6532,7 @@ pe_print_exceptions_x8664(Arena *arena, } rd_unindent(); } - + if (func_info.max_state > 0) { rd_printf("Unwind Map:"); rd_indent(); @@ -7740,7 +6544,7 @@ pe_print_exceptions_x8664(Arena *arena, } rd_unindent(); } - + for (U32 i = 0; i < func_info.try_block_map_count; ++i) { MSCRT_TryMapBlock try_block = func_info.try_block_map[i]; rd_printf("Try Map Block #%u", i); @@ -7760,7 +6564,7 @@ pe_print_exceptions_x8664(Arena *arena, rd_unindent(); rd_unindent(); } - + if (func_info.es_type_list.count) { rd_printf("Exception Specific Types:"); rd_indent(); @@ -7777,11 +6581,11 @@ pe_print_exceptions_x8664(Arena *arena, U32 func_info_voff = 0, unknown = 0; read_cursor += str8_deserial_read_struct(raw_data, read_cursor, &func_info_voff); read_cursor += str8_deserial_read_struct(raw_data, read_cursor, &unknown); - + U64 func_info_foff = coff_foff_from_voff(sections, section_count, func_info_voff); MSCRT_ParsedFuncInfoV4 func_info = {0}; mscrt_parse_func_info_v4(arena, raw_data, section_count, sections, func_info_foff, pdata->voff_first, &func_info); - + String8 header_str = str8_zero(); { String8List header_list = {0}; @@ -7808,12 +6612,12 @@ pe_print_exceptions_x8664(Arena *arena, } header_str = str8_list_join(scratch.arena, &header_list, &(StringJoin){.sep=str8_lit(", ")}); } - + rd_printf("Function Info V4:"); rd_indent(); rd_printf("Header: %#x %S", func_info.header, header_str); rd_printf("BBT Flags: %#x", func_info.bbt_flags); - + MSCRT_IP2State32V4 ip2state_map = func_info.ip2state_map; rd_printf("IP To State Map:"); rd_indent(); @@ -7823,7 +6627,7 @@ pe_print_exceptions_x8664(Arena *arena, rd_printf("%8d %08X %S", ip2state_map.states[i], ip2state_map.voffs[i], line_str); } rd_unindent(); - + if (func_info.header & MSCRT_FuncInfoV4Flag_UnwindMap) { MSCRT_UnwindMapV4 unwind_map = func_info.unwind_map; rd_printf("Unwind Map:"); @@ -7847,7 +6651,7 @@ pe_print_exceptions_x8664(Arena *arena, } rd_unindent(); } - + if (func_info.header & MSCRT_FuncInfoV4Flag_TryBlockMap) { MSCRT_TryBlockMapV4Array try_block_map = func_info.try_block_map; rd_printf("Try/Catch Blocks:"); @@ -7858,7 +6662,7 @@ pe_print_exceptions_x8664(Arena *arena, if (try_block->handlers.count) { for (U32 k = 0; k < try_block->handlers.count; ++k) { MSCRT_EhHandlerTypeV4 *handler = &try_block->handlers.v[k]; - + String8List line_list = {0}; str8_list_pushf(arena, &line_list, " "); str8_list_pushf(arena, &line_list, "CatchCodeVOff=%#08X", handler->catch_code_voff); @@ -7878,7 +6682,7 @@ pe_print_exceptions_x8664(Arena *arena, for (U32 icont = 0; icont < handler->catch_funclet_cont_addr_count; ++icont) { str8_list_pushf(arena, &line_list, "ContAddr[%u]=%#llx", icont, handler->catch_funclet_cont_addr[icont]); } - + String8 handler_str = str8_list_join(arena, &line_list, &(StringJoin){.sep=str8_lit(" ")}); rd_printf("%S", handler_str); } @@ -7890,10 +6694,10 @@ pe_print_exceptions_x8664(Arena *arena, if (handler_data_flags & ExceptionHandlerDataFlag_ScopeTable) { U32 scope_count = 0; read_cursor += str8_deserial_read_struct(raw_data, read_cursor, &scope_count); - + PE_HandlerScope *scopes = str8_deserial_get_raw_ptr(raw_data, read_cursor, sizeof(PE_HandlerScope)*scope_count); read_cursor += scope_count*sizeof(scopes[0]); - + rd_printf("Count of scope table entries: %u", scope_count); rd_indent(); rd_printf("%-8s %-8s %-8s %-8s", "Begin", "End", "Handler", "Target"); @@ -7906,7 +6710,7 @@ pe_print_exceptions_x8664(Arena *arena, if (handler_data_flags & ExceptionHandlerDataFlag_GS) { U32 gs_data = 0; read_cursor += str8_deserial_read_struct(raw_data, read_cursor, &gs_data); - + U32 flags = MSCRT_GSHandler_GetFlags(gs_data); U32 cookie_offset = MSCRT_GSHandler_GetCookieOffset(gs_data); U32 aligned_base_offset = 0; @@ -7915,7 +6719,7 @@ pe_print_exceptions_x8664(Arena *arena, read_cursor += str8_deserial_read_struct(raw_data, read_cursor, &aligned_base_offset); read_cursor += str8_deserial_read_struct(raw_data, read_cursor, &alignment); } - + String8 flags_str; { String8List flags_list = {0}; @@ -7940,28 +6744,28 @@ pe_print_exceptions_x8664(Arena *arena, rd_printf("Alignment: %x", alignment); } } - - #undef ExceptionHandlerDataFlag_FuncInfo - #undef ExceptionHandlerDataFlag_ScopeTable - #undef ExceptionHandlerDataFlag_GS + +#undef ExceptionHandlerDataFlag_FuncInfo +#undef ExceptionHandlerDataFlag_ScopeTable +#undef ExceptionHandlerDataFlag_GS } - + temp_end(temp); } - + scratch_end(scratch); } internal void pe_print_exceptions(Arena *arena, - String8List *out, - String8 indent, - COFF_MachineType machine, - U64 section_count, - COFF_SectionHeader *sections, - String8 raw_data, - Rng1U64 except_frange, - RDI_Parsed *rdi) + String8List *out, + String8 indent, + COFF_MachineType machine, + U64 section_count, + COFF_SectionHeader *sections, + String8 raw_data, + Rng1U64 except_frange, + RDI_Parsed *rdi) { if (dim_1u64(except_frange)) { rd_printf("# Exceptions"); @@ -7982,25 +6786,25 @@ pe_print_exceptions(Arena *arena, internal void pe_print_base_relocs(Arena *arena, - String8List *out, - String8 indent, - COFF_MachineType machine, - U64 image_base, - U64 section_count, - COFF_SectionHeader *sections, - String8 raw_data, - Rng1U64 base_reloc_franges, - RDI_Parsed *rdi) + String8List *out, + String8 indent, + COFF_MachineType machine, + U64 image_base, + U64 section_count, + COFF_SectionHeader *sections, + String8 raw_data, + Rng1U64 base_reloc_franges, + RDI_Parsed *rdi) { Temp scratch = scratch_begin(&arena, 1); - + String8 raw_base_relocs = str8_substr(raw_data, base_reloc_franges); PE_BaseRelocBlockList base_relocs = pe_base_reloc_block_list_from_data(scratch.arena, raw_base_relocs); - + if (base_relocs.count) { rd_printf("# Base Relocs"); rd_indent(); - + U32 addr_size = 0; switch (machine) { case COFF_MachineType_Unknown: break; @@ -8008,7 +6812,7 @@ pe_print_base_relocs(Arena *arena, case COFF_MachineType_X64: addr_size = 8; break; default: NotImplemented; } - + // convert blocks to string list U64 iblock = 0; for (PE_BaseRelocBlockNode *node = base_relocs.first; node != 0; node = node->next) { @@ -8060,10 +6864,10 @@ pe_print_base_relocs(Arena *arena, rd_unindent(); rd_newline(); } - + rd_unindent(); } - + scratch_end(scratch); } @@ -8071,28 +6875,28 @@ internal void pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Option opts, RDI_Parsed *rdi) { Temp scratch = scratch_begin(&arena, 1); - + PE_DosHeader *dos_header = str8_deserial_get_raw_ptr(raw_data, 0, sizeof(*dos_header)); if (!dos_header) { rd_errorf("not enough bytes to read DOS header"); goto exit; } Assert(dos_header->magic == PE_DOS_MAGIC); - + U32 pe_magic = 0; str8_deserial_read_struct(raw_data, dos_header->coff_file_offset, &pe_magic); if (pe_magic != PE_MAGIC) { rd_errorf("PE magic check failure, input file is not of PE format"); goto exit; } - + U64 file_header_off = dos_header->coff_file_offset+sizeof(pe_magic); COFF_FileHeader *file_header = str8_deserial_get_raw_ptr(raw_data, file_header_off, sizeof(*file_header)); if (!file_header) { rd_errorf("not enough bytes to read COFF header"); goto exit; } - + U64 opt_header_off = file_header_off + sizeof(*file_header); U16 opt_header_magic = 0; str8_deserial_read_struct(raw_data, opt_header_off, &opt_header_magic); @@ -8100,32 +6904,32 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op rd_errorf("unexpected optional header magic %#x", opt_header_magic); goto exit; } - + if (opt_header_magic == PE_PE32_MAGIC && file_header->optional_header_size < sizeof(PE_OptionalHeader32)) { rd_errorf("unexpected optional header size in COFF header %m, expected at least %m", file_header->optional_header_size, sizeof(PE_OptionalHeader32)); goto exit; } - + if (opt_header_magic == PE_PE32PLUS_MAGIC && file_header->optional_header_size < sizeof(PE_OptionalHeader32Plus)) { rd_errorf("unexpected optional header size %m, expected at least %m", file_header->optional_header_size, sizeof(PE_OptionalHeader32Plus)); goto exit; } - + U64 sections_off = file_header_off + sizeof(*file_header) + file_header->optional_header_size; COFF_SectionHeader *sections = str8_deserial_get_raw_ptr(raw_data, sections_off, sizeof(*sections)*file_header->section_count); if (!sections) { rd_errorf("not enough bytes to read COFF section headers"); goto exit; } - + U64 string_table_off = file_header->symbol_table_foff + sizeof(COFF_Symbol16) * file_header->symbol_count; String8 raw_string_table = str8_substr(raw_data, rng_1u64(string_table_off, raw_data.size)); - + COFF_Symbol32Array symbols = coff_symbol_array_from_data_16(scratch.arena, raw_data, file_header->symbol_table_foff, file_header->symbol_count); - + U8 *raw_opt_header = push_array(scratch.arena, U8, file_header->optional_header_size); str8_deserial_read_array(raw_data, opt_header_off, raw_opt_header, file_header->optional_header_size); - + if (opts & RD_Option_Headers) { coff_print_file_header(arena, out, indent, file_header); rd_newline(); @@ -8135,7 +6939,7 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op U64 image_base = 0; U64 dir_count = 0; PE_DataDirectory *dirs = 0; - + if (opt_header_magic == PE_PE32_MAGIC) { PE_OptionalHeader32 *opt_header = (PE_OptionalHeader32 *)raw_opt_header; image_base = opt_header->image_base; @@ -8145,7 +6949,7 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op rd_errorf("unable to read data directories"); goto exit; } - + if (opts & RD_Option_Headers) { pe_print_optional_header32(arena, out, indent, opt_header, dirs); } @@ -8158,12 +6962,12 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op rd_errorf("unable to read data directories"); goto exit; } - + if (opts & RD_Option_Headers) { pe_print_optional_header32plus(arena, out, indent, opt_header, dirs); } } - + // map data directory RVA to file offsets Rng1U64 *dirs_file_ranges = push_array(scratch.arena, Rng1U64, dir_count); Rng1U64 *dirs_virt_ranges = push_array(scratch.arena, Rng1U64, dir_count); @@ -8173,19 +6977,19 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op dirs_file_ranges[i] = r1u64(file_off, file_off+dir.virt_size); dirs_virt_ranges[i] = r1u64(dir.virt_off, dir.virt_off+dir.virt_size); } - + if (opts & RD_Option_Sections) { coff_print_section_table(arena, out, indent, raw_string_table, symbols, file_header->section_count, sections); } - + if (opts & RD_Option_Relocs) { coff_print_relocs(arena, out, indent, raw_data, raw_string_table, file_header->machine, file_header->section_count, sections, symbols); } - + if (opts & RD_Option_Symbols) { coff_print_symbol_table(arena, out, indent, raw_data, 0, raw_string_table, symbols); } - + if (opts & RD_Option_Exports) { PE_ParsedExportTable exptab = pe_exports_from_data(arena, file_header->section_count, @@ -8195,7 +6999,7 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op dirs_virt_ranges[PE_DataDirectoryIndex_EXPORT]); pe_print_export_table(arena, out, indent, exptab); } - + if (opts & RD_Option_Imports) { B32 is_pe32 = opt_header_magic == PE_PE32_MAGIC; PE_ParsedStaticImportTable static_imptab = pe_static_imports_from_data(arena, is_pe32, file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_IMPORT]); @@ -8203,35 +7007,35 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op pe_print_static_import_table(arena, out, indent, image_base, static_imptab); pe_print_delay_import_table(arena, out, indent, image_base, delay_imptab); } - + if (opts & RD_Option_Resources) { String8 raw_dir = str8_substr(raw_data, dirs_file_ranges[PE_DataDirectoryIndex_RESOURCES]); PE_ResourceDir *dir_root = pe_resource_table_from_directory_data(scratch.arena, raw_dir); pe_print_resources(arena, out, indent, dir_root); } - + if (opts & RD_Option_Exceptions) { pe_print_exceptions(arena, out, indent, file_header->machine, file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_EXCEPTIONS], rdi); } - + if (opts & RD_Option_Relocs) { pe_print_base_relocs(arena, out, indent, file_header->machine, image_base, file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_BASE_RELOC], rdi); } - + if (opts & RD_Option_Debug) { if (PE_DataDirectoryIndex_DEBUG < dir_count) { String8 raw_dir = str8_substr(raw_data, dirs_file_ranges[PE_DataDirectoryIndex_DEBUG]); pe_print_debug_diretory(arena, out, indent, raw_data, raw_dir); } } - + if (opts & RD_Option_Tls) { if (dim_1u64(dirs_file_ranges[PE_DataDirectoryIndex_TLS])) { PE_ParsedTLS tls = pe_tls_from_data(scratch.arena, file_header->machine, image_base, file_header->section_count, sections, raw_data, dirs_file_ranges[PE_DataDirectoryIndex_TLS]); pe_print_tls(arena, out, indent, tls); } } - + if (opts & RD_Option_LoadConfig) { String8 raw_lc = str8_substr(raw_data, dirs_file_ranges[PE_DataDirectoryIndex_LOAD_CONFIG]); if (raw_lc.size) { @@ -8257,7 +7061,7 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op } } } - + RD_MarkerArray *section_markers = 0; if (opts & (RD_Option_Disasm|RD_Option_Rawdata)) { if (rdi) { @@ -8266,21 +7070,21 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op section_markers = rd_section_markers_from_coff_symbol_table(scratch.arena, raw_string_table, file_header->section_count, symbols); } } - + if (opts & RD_Option_Rawdata) { coff_raw_data_sections(arena, out, indent, raw_data, 0, section_markers, file_header->section_count, sections); } - + if (opts & RD_Option_Disasm) { coff_disasm_sections(arena, out, indent, raw_data, file_header->machine, 0, 1, section_markers, file_header->section_count, sections); } - + if (opts & RD_Option_Dwarf) { DW_Input dwarf_input = dw_input_from_coff_section_table(scratch.arena, raw_data, raw_string_table, file_header->section_count, sections); - dw_format(arena, out, indent, opts, &dwarf_input, arch, Image_CoffPe); + dw_format(arena, out, indent, opts, &dwarf_input, arch, ExecutableImageKind_CoffPe); } - -exit:; + + exit:; scratch_end(scratch); } @@ -8289,25 +7093,25 @@ internal void elf_print_dwarf_expressions(Arena *arena, String8List *out, String8 indent, String8 raw_data) { Temp scratch = scratch_begin(&arena, 1); - + ELF_BinInfo bin = elf_bin_from_data(raw_data); Arch arch = arch_from_elf_machine(bin.hdr.e_machine); DW_Input dwarf_input = dw_input_from_elf_section_table(scratch.arena, raw_data, &bin); ELF_Class elf_class = bin.hdr.e_ident[ELF_Identifier_Class]; - ImageType image_type = elf_class == ELF_Class_32 ? Image_Elf32 : elf_class == ELF_Class_64 ? Image_Elf64 : ELF_Class_None; + ExecutableImageKind image_type = elf_class == ELF_Class_32 ? ExecutableImageKind_Elf32 : elf_class == ELF_Class_64 ? ExecutableImageKind_Elf64 : ELF_Class_None; B32 relaxed = 1; Rng1U64List cu_ranges = dw_unit_ranges_from_data(scratch.arena, dwarf_input.sec[DW_Section_Info].data); DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, &dwarf_input); - + if (bin.hdr.e_type == ELF_Type_Exec || bin.hdr.e_type == ELF_Type_Dyn) { U64 cu_idx = 0; for (Rng1U64Node *cu_range_n = cu_ranges.first; cu_range_n != 0; cu_range_n = cu_range_n->next, ++cu_idx) { Temp comp_temp = temp_begin(scratch.arena); - + U64 cu_base = cu_range_n->v.min; Rng1U64 cu_range = cu_range_n->v; DW_CompUnit cu = dw_cu_from_info_off(comp_temp.arena, &dwarf_input, lu_input, cu_range.min, relaxed); - + struct TagNode { struct TagNode *next; DW_Tag tag; @@ -8316,7 +7120,7 @@ elf_print_dwarf_expressions(Arena *arena, String8List *out, String8 indent, Stri struct TagNode *free_tags = 0; S32 lexical_block_depth = 0; - + for (U64 info_off = cu.first_tag_info_off, tag_size = 0; info_off < cu.info_range.max; info_off += tag_size) { DW_Tag tag = {0}; tag_size = dw_read_tag_cu(comp_temp.arena, &dwarf_input, &cu, info_off, &tag); @@ -8330,7 +7134,7 @@ elf_print_dwarf_expressions(Arena *arena, String8List *out, String8 indent, Stri n->tag = tag; SLLStackPush(tag_stack, n); } - + if (tag.kind == DW_Tag_Null) { if (tag_stack) { struct TagNode *n = tag_stack; @@ -8344,10 +7148,10 @@ elf_print_dwarf_expressions(Arena *arena, String8List *out, String8 indent, Stri } else if (tag.kind == DW_Tag_LexicalBlock || tag.kind == DW_Tag_SubProgram) { ++lexical_block_depth; if (tag.kind == DW_Tag_SubProgram) { - String8 expr = dw_exprloc_from_attrib(&dwarf_input, &cu, tag, DW_Attrib_FrameBase); - if (expr.size > 0) { - String8 expr_str = dw_format_expression_single_line(comp_temp.arena, expr, cu_base, cu.address_size, arch, cu.version, cu.ext, cu.format); - } + String8 expr = dw_exprloc_from_attrib(&dwarf_input, &cu, tag, DW_Attrib_FrameBase); + if (expr.size > 0) { + String8 expr_str = dw_format_expression_single_line(comp_temp.arena, expr, cu_base, cu.address_size, arch, cu.version, cu.ext, cu.format); + } } } else if (tag.kind == DW_Tag_Variable || tag.kind == DW_Tag_FormalParameter) { #if 0 @@ -8362,7 +7166,7 @@ elf_print_dwarf_expressions(Arena *arena, String8List *out, String8 indent, Stri rd_printf("%llx Local: %S", info_off, name); is_global_var = 0; } - + rd_indent(); if (value_class == DW_AttribClass_LocListPtr || value_class == DW_AttribClass_LocList) { DW_LocList location = dw_loclist_from_attrib_ptr(comp_temp.arena, &dwarf_input, &cu, location_attrib); @@ -8379,7 +7183,7 @@ elf_print_dwarf_expressions(Arena *arena, String8List *out, String8 indent, Stri } #endif } - + #if 0 if (tag.kind == DW_Tag_LexicalBlock || tag.kind == DW_Tag_CompileUnit || tag.kind == DW_Tag_InlinedSubroutine || tag.kind == DW_Tag_SubProgram) { Temp temp = temp_begin(comp_temp.arena); @@ -8391,13 +7195,13 @@ elf_print_dwarf_expressions(Arena *arena, String8List *out, String8 indent, Stri } #endif } - + temp_end(comp_temp); } } else { fprintf(stderr, "Skipping unexpected ELF type %u\n", bin.hdr.e_type); } - + scratch_end(scratch); } #endif diff --git a/src/raddump/raddump.h b/src/raddump/raddump.h index 0daad497..84271d08 100644 --- a/src/raddump/raddump.h +++ b/src/raddump/raddump.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RADDUMP_H @@ -49,20 +49,20 @@ typedef U64 RD_Option; #define RD_Option_DebugLineStr (1ull << 29) #define RD_Option_DebugStrOffsets (1ull << 30) #define RD_Option_Dwarf \ - (RD_Option_DebugInfo | \ - RD_Option_DebugAbbrev | \ - RD_Option_DebugLine | \ - RD_Option_DebugStr | \ - RD_Option_DebugLoc | \ - RD_Option_DebugRanges | \ - RD_Option_DebugARanges | \ - RD_Option_DebugAddr | \ - RD_Option_DebugLocLists | \ - RD_Option_DebugRngLists | \ - RD_Option_DebugPubNames | \ - RD_Option_DebugPubTypes | \ - RD_Option_DebugLineStr | \ - RD_Option_DebugStrOffsets) +(RD_Option_DebugInfo | \ +RD_Option_DebugAbbrev | \ +RD_Option_DebugLine | \ +RD_Option_DebugStr | \ +RD_Option_DebugLoc | \ +RD_Option_DebugRanges | \ +RD_Option_DebugARanges | \ +RD_Option_DebugAddr | \ +RD_Option_DebugLocLists | \ +RD_Option_DebugRngLists | \ +RD_Option_DebugPubNames | \ +RD_Option_DebugPubTypes | \ +RD_Option_DebugLineStr | \ +RD_Option_DebugStrOffsets) #define RD_Option_RelaxDwarfParser (1ull << 31ull) // RDI #define RD_Option_NoRdi (1ull << 32ull) @@ -80,6 +80,7 @@ typedef U64 RD_Option; #define RD_Option_RdiGlobalVars (1ull << 44ull) #define RD_Option_RdiGlobalVarsVMap (1ull << 45ull) #define RD_Option_RdiThreadVars (1ull << 46ull) +#define RD_Option_RdiConstants (1ull << 47ull) #define RD_Option_RdiProcedures (1ull << 48ull) #define RD_Option_RdiScopes (1ull << 49ull) #define RD_Option_RdiScopeVMap (1ull << 50ull) @@ -87,25 +88,26 @@ typedef U64 RD_Option; #define RD_Option_RdiNameMaps (1ull << 52ull) #define RD_Option_RdiStrings (1ull << 53ull) #define RD_Option_RdiAll (RD_Option_RdiDataSections | \ - RD_Option_RdiTopLevelInfo | \ - RD_Option_RdiBinarySections | \ - RD_Option_RdiFilePaths | \ - RD_Option_RdiSourceFiles | \ - RD_Option_RdiLineTables | \ - RD_Option_RdiSourceLineMaps | \ - RD_Option_RdiUnits | \ - RD_Option_RdiUnitVMap | \ - RD_Option_RdiTypeNodes | \ - RD_Option_RdiUserDefinedTypes | \ - RD_Option_RdiGlobalVars | \ - RD_Option_RdiGlobalVarsVMap | \ - RD_Option_RdiThreadVars | \ - RD_Option_RdiProcedures | \ - RD_Option_RdiScopes | \ - RD_Option_RdiScopeVMap | \ - RD_Option_RdiInlineSites | \ - RD_Option_RdiNameMaps | \ - RD_Option_RdiStrings) +RD_Option_RdiTopLevelInfo | \ +RD_Option_RdiBinarySections | \ +RD_Option_RdiFilePaths | \ +RD_Option_RdiSourceFiles | \ +RD_Option_RdiLineTables | \ +RD_Option_RdiSourceLineMaps | \ +RD_Option_RdiUnits | \ +RD_Option_RdiUnitVMap | \ +RD_Option_RdiTypeNodes | \ +RD_Option_RdiUserDefinedTypes | \ +RD_Option_RdiGlobalVars | \ +RD_Option_RdiGlobalVarsVMap | \ +RD_Option_RdiThreadVars | \ +RD_Option_RdiConstants | \ +RD_Option_RdiProcedures | \ +RD_Option_RdiScopes | \ +RD_Option_RdiScopeVMap | \ +RD_Option_RdiInlineSites | \ +RD_Option_RdiNameMaps | \ +RD_Option_RdiStrings) typedef struct RD_Marker @@ -185,37 +187,6 @@ internal void rd_print_disasm (Arena *arena, String8List *o internal String8 rd_format_hex_array(Arena *arena, U8 *ptr, U64 size); internal void rd_print_raw_data (Arena *arena, String8List *out, String8 indent, U64 bytes_per_row, U64 marker_count, RD_Marker *markers, String8 raw_data); -// RDI - -internal String8 rdi_string_from_data_section_kind(Arena *arena, RDI_SectionKind v); -internal String8 rdi_string_from_arch (Arena *arena, RDI_Arch v); -internal String8 rdi_string_from_language (Arena *arena, RDI_Language v); -internal String8 rdi_string_from_local_kind (Arena *arena, RDI_LocalKind v); -//internal String8 rdi_string_from_type_kind (Arena *arena, RDI_TypeKind v); -internal String8 rdi_string_from_member_kind (Arena *arena, RDI_MemberKind v); - -internal String8 rdi_string_from_binary_section_flags(Arena *arena, RDI_BinarySectionFlags flags); -internal String8 rdi_string_from_type_modifier (Arena *arena, RDI_TypeModifierFlags flags); -internal String8 rdi_string_from_udt_flags (Arena *arena, RDI_UDTFlags flags); -internal String8 rdi_string_from_link_flags (Arena *arena, RDI_LinkFlags flags); - -internal void rdi_print_data_sections (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi); -internal void rdi_print_top_level_info (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_TopLevelInfo *tli); -internal void rdi_print_binary_section (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_BinarySection *bin_section); -internal void rdi_print_file_path (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_FilePathNode *file_path); -internal void rdi_print_source_file (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_SourceFile *source_file); -internal void rdi_print_line_table (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_LineTable *line_table); -internal void rdi_print_source_line_map(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_SourceLineMap *map); -internal void rdi_print_unit (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Unit *unit); -internal void rdi_print_type_node (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_TypeNode *type); -internal void rdi_print_udt (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_UDT *udt); -internal void rdi_print_global_variable(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_GlobalVariable *gvar); -internal void rdi_print_thread_variable(Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_ThreadVariable *tvar); -internal void rdi_print_procedure (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Procedure *proc, RDI_Arch arch); -internal void rdi_print_scope (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, RDI_Scope *scope, RDI_Arch arch); -internal void rdi_print_inline_site (Arena *arena, String8List *out, String8 indent, RDI_Parsed *rdi, U64 idx, RDI_InlineSite *inline_site); -internal void rdi_print_vmap_entry (Arena *arena, String8List *out, String8 indent, RDI_VMapEntry *v); - // DWARF 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); @@ -228,8 +199,8 @@ internal void dw_print_debug_info (Arena *arena, String8List *out, String8 internal void dw_print_debug_abbrev (Arena *arena, String8List *out, String8 indent, DW_Input *input); internal void dw_print_debug_line (Arena *arena, String8List *out, String8 indent, DW_Input *input, DW_ListUnitInput lu_input, B32 relaxed); internal void dw_print_debug_str (Arena *arena, String8List *out, String8 indent, DW_Input *input); -internal void dw_print_debug_loc (Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ImageType image_type, B32 relaxed); -internal void dw_print_debug_ranges (Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ImageType image_type, B32 relaxed); +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); diff --git a/src/raddump/raddump_main.c b/src/raddump/raddump_main.c index d6fee2b4..f3be6eb5 100644 --- a/src/raddump/raddump_main.c +++ b/src/raddump/raddump_main.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #define BUILD_CONSOLE_INTERFACE 1 @@ -95,7 +95,7 @@ #include "radcon/radcon_pdb.c" #include "radcon/radcon_dwarf.c" #include "radcon/radcon.c" - + #include "linker/thread_pool/thread_pool.h" #include "linker/thread_pool/thread_pool.c" #include "linker/codeview_ext/codeview.h" @@ -116,9 +116,9 @@ global read_only struct } g_rd_dump_option_map[] = { { RD_Option_Help, "help", "Print help and exit" }, { RD_Option_Version, "version", "Print version and exit" }, - + { RD_Option_NoRdi, "nordi", "Don't load RAD Debug Info" }, - + { RD_Option_Headers, "headers", "Dump DOS header, file header, optional header, and/or archive header" }, { RD_Option_Sections, "sections", "Dump section headers as table" }, { RD_Option_Rawdata, "rawdata", "Dump raw section data" }, @@ -134,7 +134,7 @@ global read_only struct { RD_Option_LoadConfig, "loadconfig", "Dump load config" }, { RD_Option_Resources, "resources", "Dump resource directory" }, { RD_Option_LongNames, "longnames", "Dump archive long names" }, - + { RD_Option_DebugInfo, "debug_info", "Dump .debug_info" }, { RD_Option_DebugAbbrev, "debug_abbrev", "Dump .debug_abbrev" }, { RD_Option_DebugLine, "debug_line", "Dump .debug_line" }, @@ -151,7 +151,7 @@ global read_only struct { RD_Option_DebugStrOffsets, "debug_stroffsets", "Dump .debug_stroffsets" }, { RD_Option_Dwarf, "dwarf", "Dump all DWARF sections" }, { RD_Option_RelaxDwarfParser, "relax_dwarf_parser", "Relaxes version requirement on attribute and form encodings" }, - + { RD_Option_RdiDataSections, "rdi_data_sections", "Dump data sections" }, { RD_Option_RdiTopLevelInfo, "rdi_top_level_info", "Dump top level info" }, { RD_Option_RdiBinarySections, "rdi_binary_sections", "Dump binary sections" }, @@ -165,12 +165,13 @@ global read_only struct { RD_Option_RdiUserDefinedTypes, "rdi_udt", "Dump user defined types" }, { RD_Option_RdiGlobalVars, "rdi_global_vars", "Dump global variables" }, { RD_Option_RdiThreadVars, "rdi_thread_vars", "Dump thread variables" }, + { RD_Option_RdiConstants, "rdi_constants", "Dump constants" }, { RD_Option_RdiScopes, "rdi_scopes", "Dump scopes" }, { RD_Option_RdiScopeVMap, "rdi_scope_virtual_map", "Dump scope virtual map" }, { RD_Option_RdiInlineSites, "rdi_inline_sites", "Dump inline sites" }, { RD_Option_RdiNameMaps, "rdi_name_maps", "Dump name maps" }, { RD_Option_RdiStrings, "rdi_strings", "Dump strings" }, - + { RD_Option_Help, "h", "Alias for -help" }, { RD_Option_Version, "v", "Alias for -version" }, { RD_Option_Sections, "s", "Alias for -sections" }, @@ -186,7 +187,7 @@ internal void entry_point(CmdLine *cmdline) { Arena *arena = arena_alloc(); - + // make indent String8List *out = push_array(arena, String8List, 1); String8 indent; @@ -196,7 +197,7 @@ entry_point(CmdLine *cmdline) MemorySet(indent_buffer, ' ', indent_buffer_size); indent = str8(indent_buffer, 0); } - + // parse options RD_Option opts = 0; { @@ -212,16 +213,16 @@ entry_point(CmdLine *cmdline) break; } } - + if (opt == 0) { rd_errorf("Unknown argument: \"%S\"", cmd->string); goto exit; } - + opts |= opt; } } - + // print help if (opts & RD_Option_Help) { int longest_cmd_switch = 0; @@ -241,14 +242,14 @@ entry_point(CmdLine *cmdline) rd_unindent(); goto exit; } - + // print version if (opts & RD_Option_Version) { rd_printf(BUILD_TITLE_STRING_LITERAL); rd_printf("\traddump "); goto exit; } - + // input check if (cmdline->inputs.node_count == 0) { rd_errorf("No input file specified"); @@ -257,35 +258,35 @@ entry_point(CmdLine *cmdline) rd_errorf("Too many inputs specified, expected one"); goto exit; } - + // read input String8 file_path = str8_list_first(&cmdline->inputs); String8 raw_data = os_data_from_file_path(arena, file_path); - + // is read ok? if (raw_data.size == 0) { rd_errorf("Unable to read input file \"%S\"", file_path); goto exit; } - + // format input rd_format_preamble(arena, out, indent, file_path, raw_data); if (rd_is_rdi(raw_data)) { RDI_Parsed rdi = {0}; RDI_ParseStatus parse_status = rdi_parse(raw_data.str, raw_data.size, &rdi); switch (parse_status) { - case RDI_ParseStatus_Good: { - RD_Option rdi_print_opts = opts; - if ((rdi_print_opts & RD_Option_RdiAll) == 0) { - rdi_print_opts |= RD_Option_RdiAll; - } - rdi_print(arena, out, indent, &rdi, rdi_print_opts); - } break; - case RDI_ParseStatus_HeaderDoesNotMatch: rd_errorf("RDI Parse: header does not match"); break; - case RDI_ParseStatus_UnsupportedVersionNumber: rd_errorf("RDI Parse: unsupported version"); break; - case RDI_ParseStatus_InvalidDataSecionLayout: rd_errorf("RDI Parse: invalid data section layout"); break; - case RDI_ParseStatus_MissingRequiredSection: rd_errorf("RDI Parse: missing required section"); break; - default: rd_errorf("RDI Parse: unknown parse status %u", parse_status); break; + case RDI_ParseStatus_Good: { + RD_Option rdi_print_opts = opts; + if ((rdi_print_opts & RD_Option_RdiAll) == 0) { + rdi_print_opts |= RD_Option_RdiAll; + } + rdi_print(arena, out, indent, &rdi, rdi_print_opts); + } break; + case RDI_ParseStatus_HeaderDoesNotMatch: rd_errorf("RDI Parse: header does not match"); break; + case RDI_ParseStatus_UnsupportedVersionNumber: rd_errorf("RDI Parse: unsupported version"); break; + case RDI_ParseStatus_InvalidDataSecionLayout: rd_errorf("RDI Parse: invalid data section layout"); break; + case RDI_ParseStatus_MissingRequiredSection: rd_errorf("RDI Parse: missing required section"); break; + default: rd_errorf("RDI Parse: unknown parse status %u", parse_status); break; } } else if (coff_is_regular_archive(raw_data) || coff_is_thin_archive(raw_data)) { coff_print_archive(arena, out, indent, raw_data, opts); @@ -305,11 +306,10 @@ entry_point(CmdLine *cmdline) //elf_print_dwarf_expressions(arena, out, indent, raw_data); } -exit:; + exit:; // print formatted string String8 out_string = str8_list_join(arena, out, &(StringJoin){ .sep = str8_lit("\n"),}); fprintf(stdout, "%.*s", str8_varg(out_string)); - + arena_release(arena); } - diff --git a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.c b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.c new file mode 100644 index 00000000..e60dd482 --- /dev/null +++ b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.c @@ -0,0 +1,106 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//////////////////////////////// +//~ rjf: Baking Tasks + +//- rjf: unit vmap baking + +ASYNC_WORK_DEF(p2b_bake_unit_vmap_work) +{ + ProfBeginFunction(); + Arena *arena = async_root_thread_arena(p2b_async_root); + P2B_BakeUnitVMapIn *in = (P2B_BakeUnitVMapIn *)input; + RDIM_UnitVMapBakeResult *out = push_array(arena, RDIM_UnitVMapBakeResult, 1); + *out = rdim_bake_unit_vmap(arena, in->units); + ProfEnd(); + return out; +} + +//- rjf: line table baking + +ASYNC_WORK_DEF(p2b_bake_line_table_work) +{ + ProfBeginFunction(); + Arena *arena = async_root_thread_arena(p2b_async_root); + P2B_BakeLineTablesIn *in = (P2B_BakeLineTablesIn *)input; + RDIM_LineTableBakeResult *out = push_array(arena, RDIM_LineTableBakeResult, 1); + *out = rdim_bake_line_tables(arena, in->line_tables); + ProfEnd(); + return out; +} + +//- rjf: per-procedure chunk dumping + +ASYNC_WORK_DEF(p2b_dump_proc_chunk_work) +{ + ProfBeginFunction(); + Arena *arena = async_root_thread_arena(p2b_async_root); + P2B_DumpProcChunkIn *in = (P2B_DumpProcChunkIn *)input; + String8List *out = push_array(arena, String8List, 1); + RDI_LineTable *line_tables = in->line_tables_bake->line_tables; + RDI_U64 line_tables_count = in->line_tables_bake->line_tables_count; + RDI_U64 *line_table_voffs = in->line_tables_bake->line_table_voffs; + RDI_U64 line_table_voffs_count = in->line_tables_bake->line_table_voffs_count; + RDI_Line *line_table_lines = in->line_tables_bake->line_table_lines; + RDI_U64 line_table_lines_count = in->line_tables_bake->line_table_lines_count; + for(U64 idx = 0; idx < in->chunk->count; idx += 1) + { + // NOTE(rjf): breakpad does not support multiple voff ranges per procedure. + RDIM_Symbol *proc = &in->chunk->v[idx]; + RDIM_Scope *root_scope = proc->root_scope; + if(root_scope != 0 && root_scope->voff_ranges.first != 0) + { + // rjf: dump function record + RDIM_Rng1U64 voff_range = root_scope->voff_ranges.first->v; + str8_list_pushf(arena, out, "FUNC %I64x %I64x %I64x %S\n", voff_range.min, voff_range.max-voff_range.min, 0ull, proc->name); + + // rjf: dump function lines + U64 unit_idx = rdi_vmap_idx_from_voff(in->unit_vmap, in->unit_vmap_count, voff_range.min); + if(0 < unit_idx && unit_idx <= in->unit_count) + { + U32 line_table_idx = in->unit_line_table_idxs[unit_idx]; + if(0 < line_table_idx && line_table_idx <= line_tables_count) + { + // rjf: unpack unit line info + RDI_LineTable *line_table = &line_tables[line_table_idx]; + RDI_ParsedLineTable line_info = + { + line_table_voffs + line_table->voffs_base_idx, + line_table_lines + line_table->lines_base_idx, + 0, + line_table->lines_count, + 0 + }; + for(U64 voff = voff_range.min, last_voff = 0; + voff < voff_range.max && voff > last_voff;) + { + RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&line_info, voff); + if(line_info_idx < line_info.count) + { + RDI_Line *line = &line_info.lines[line_info_idx]; + U64 line_voff_min = line_info.voffs[line_info_idx]; + U64 line_voff_opl = line_info.voffs[line_info_idx+1]; + if(line->file_idx != 0) + { + str8_list_pushf(arena, out, "%I64x %I64x %I64u %I64u\n", + line_voff_min, + line_voff_opl-line_voff_min, + (U64)line->line_num, + (U64)line->file_idx); + } + last_voff = voff; + voff = line_voff_opl; + } + else + { + break; + } + } + } + } + } + } + ProfEnd(); + return out; +} diff --git a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.h b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.h new file mode 100644 index 00000000..1cc29d20 --- /dev/null +++ b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.h @@ -0,0 +1,47 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef RDI_BREAKPAD_FROM_PDB_H +#define RDI_BREAKPAD_FROM_PDB_H + +//////////////////////////////// +//~ rjf: Baking Tasks + +//- rjf: unit vmap baking + +typedef struct P2B_BakeUnitVMapIn P2B_BakeUnitVMapIn; +struct P2B_BakeUnitVMapIn +{ + RDIM_UnitChunkList *units; +}; +ASYNC_WORK_DEF(p2b_bake_unit_vmap_work); + +//- rjf: line table baking + +typedef struct P2B_BakeLineTablesIn P2B_BakeLineTablesIn; +struct P2B_BakeLineTablesIn +{ + RDIM_LineTableChunkList *line_tables; +}; +ASYNC_WORK_DEF(p2b_bake_line_table_work); + +//- rjf: per-procedure chunk dumping + +typedef struct P2B_DumpProcChunkIn P2B_DumpProcChunkIn; +struct P2B_DumpProcChunkIn +{ + RDI_VMapEntry *unit_vmap; + U32 unit_vmap_count; + U32 *unit_line_table_idxs; + U64 unit_count; + RDIM_LineTableBakeResult *line_tables_bake; + RDIM_SymbolChunkNode *chunk; +}; +ASYNC_WORK_DEF(p2b_dump_proc_chunk_work); + +//////////////////////////////// +//~ rjf: Globals + +global ASYNC_Root *p2b_async_root = 0; + +#endif // RDI_BREAKPAD_FROM_PDB_H diff --git a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c deleted file mode 100644 index 6e6b71d0..00000000 --- a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ rjf: Build Options - -#define BUILD_TITLE "rdi_breakpad_from_pdb" -#define BUILD_CONSOLE_INTERFACE 1 - -//////////////////////////////// -//~ rjf: Includes - -//- rjf: [lib] -#include "lib_rdi_format/rdi_format.h" -#include "lib_rdi_format/rdi_format.c" -#include "lib_rdi_format/rdi_format_parse.h" -#include "lib_rdi_format/rdi_format_parse.c" -#include "third_party/rad_lzb_simple/rad_lzb_simple.h" -#include "third_party/rad_lzb_simple/rad_lzb_simple.c" - -//- rjf: [h] -#include "base/base_inc.h" -#include "os/os_inc.h" -#include "path/path.h" -#include "async/async.h" -#include "rdi_make/rdi_make_local.h" -#include "coff/coff.h" -#include "coff/coff_parse.h" -#include "codeview/codeview.h" -#include "codeview/codeview_parse.h" -#include "codeview/codeview_enum.h" -#include "msf/msf.h" -#include "msf/msf_parse.h" -#include "pdb/pdb.h" -#include "pdb/pdb_parse.h" -#include "pdb/pdb_stringize.h" -#include "rdi_from_pdb/rdi_from_pdb.h" - -//- rjf: [c] -#include "base/base_inc.c" -#include "os/os_inc.c" -#include "path/path.c" -#include "async/async.c" -#include "rdi_make/rdi_make_local.c" -#include "coff/coff.c" -#include "coff/coff_parse.c" -#include "codeview/codeview.c" -#include "codeview/codeview_parse.c" -#include "codeview/codeview_enum.c" -#include "msf/msf.c" -#include "msf/msf_parse.c" -#include "pdb/pdb.c" -#include "pdb/pdb_parse.c" -#include "pdb/pdb_stringize.c" -#include "rdi_from_pdb/rdi_from_pdb.c" - -//////////////////////////////// -//~ rjf: Baking Tasks - -//- rjf: unit vmap baking - -typedef struct P2B_BakeUnitVMapIn P2B_BakeUnitVMapIn; -struct P2B_BakeUnitVMapIn -{ - RDIM_UnitChunkList *units; -}; - -ASYNC_WORK_DEF(p2b_bake_unit_vmap_work) -{ - ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; - P2B_BakeUnitVMapIn *in = (P2B_BakeUnitVMapIn *)input; - RDIM_UnitVMapBakeResult *out = push_array(arena, RDIM_UnitVMapBakeResult, 1); - *out = rdim_bake_unit_vmap(arena, in->units); - ProfEnd(); - return out; -} - -//- rjf: line table baking - -typedef struct P2B_BakeLineTablesIn P2B_BakeLineTablesIn; -struct P2B_BakeLineTablesIn -{ - RDIM_LineTableChunkList *line_tables; -}; - -ASYNC_WORK_DEF(p2b_bake_line_table_work) -{ - ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; - P2B_BakeLineTablesIn *in = (P2B_BakeLineTablesIn *)input; - RDIM_LineTableBakeResult *out = push_array(arena, RDIM_LineTableBakeResult, 1); - *out = rdim_bake_line_tables(arena, in->line_tables); - ProfEnd(); - return out; -} - -//- rjf: per-procedure chunk dumping - -typedef struct P2B_DumpProcChunkIn P2B_DumpProcChunkIn; -struct P2B_DumpProcChunkIn -{ - RDI_VMapEntry *unit_vmap; - U32 unit_vmap_count; - U32 *unit_line_table_idxs; - U64 unit_count; - RDIM_LineTableBakeResult *line_tables_bake; - RDIM_SymbolChunkNode *chunk; -}; - -ASYNC_WORK_DEF(p2b_dump_proc_chunk_work) -{ - ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; - P2B_DumpProcChunkIn *in = (P2B_DumpProcChunkIn *)input; - String8List *out = push_array(arena, String8List, 1); - RDI_LineTable *line_tables = in->line_tables_bake->line_tables; - RDI_U64 line_tables_count = in->line_tables_bake->line_tables_count; - RDI_U64 *line_table_voffs = in->line_tables_bake->line_table_voffs; - RDI_U64 line_table_voffs_count = in->line_tables_bake->line_table_voffs_count; - RDI_Line *line_table_lines = in->line_tables_bake->line_table_lines; - RDI_U64 line_table_lines_count = in->line_tables_bake->line_table_lines_count; - for(U64 idx = 0; idx < in->chunk->count; idx += 1) - { - // NOTE(rjf): breakpad does not support multiple voff ranges per procedure. - RDIM_Symbol *proc = &in->chunk->v[idx]; - RDIM_Scope *root_scope = proc->root_scope; - if(root_scope != 0 && root_scope->voff_ranges.first != 0) - { - // rjf: dump function record - RDIM_Rng1U64 voff_range = root_scope->voff_ranges.first->v; - str8_list_pushf(arena, out, "FUNC %I64x %I64x %I64x %S\n", voff_range.min, voff_range.max-voff_range.min, 0ull, proc->name); - - // rjf: dump function lines - U64 unit_idx = rdi_vmap_idx_from_voff(in->unit_vmap, in->unit_vmap_count, voff_range.min); - if(0 < unit_idx && unit_idx <= in->unit_count) - { - U32 line_table_idx = in->unit_line_table_idxs[unit_idx]; - if(0 < line_table_idx && line_table_idx <= line_tables_count) - { - // rjf: unpack unit line info - RDI_LineTable *line_table = &line_tables[line_table_idx]; - RDI_ParsedLineTable line_info = - { - line_table_voffs + line_table->voffs_base_idx, - line_table_lines + line_table->lines_base_idx, - 0, - line_table->lines_count, - 0 - }; - for(U64 voff = voff_range.min, last_voff = 0; - voff < voff_range.max && voff > last_voff;) - { - RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&line_info, voff); - if(line_info_idx < line_info.count) - { - RDI_Line *line = &line_info.lines[line_info_idx]; - U64 line_voff_min = line_info.voffs[line_info_idx]; - U64 line_voff_opl = line_info.voffs[line_info_idx+1]; - if(line->file_idx != 0) - { - str8_list_pushf(arena, out, "%I64x %I64x %I64u %I64u\n", - line_voff_min, - line_voff_opl-line_voff_min, - (U64)line->line_num, - (U64)line->file_idx); - } - last_voff = voff; - voff = line_voff_opl; - } - else - { - break; - } - } - } - } - } - } - ProfEnd(); - return out; -} - -//////////////////////////////// -//~ rjf: Entry Point - -internal void -entry_point(CmdLine *cmdline) -{ - //- rjf: initialize state, unpack command line - Arena *arena = arena_alloc(); - B32 do_help = (cmd_line_has_flag(cmdline, str8_lit("help")) || - cmd_line_has_flag(cmdline, str8_lit("h")) || - cmd_line_has_flag(cmdline, str8_lit("?"))); - P2R_User2Convert *user2convert = p2r_user2convert_from_cmdln(arena, cmdline); - user2convert->flags &= ~(P2R_ConvertFlag_Types|P2R_ConvertFlag_UDTs); - - //- rjf: display help - if(do_help || user2convert->errors.node_count != 0) - { - fprintf(stderr, "--- rdi_breakpad_from_pdb -----------------------------------------------------\n\n"); - - fprintf(stderr, "This utility converts debug information from PDBs into the textual Breakpad\n"); - fprintf(stderr, "symbol information format, used for various external utilities, using the RAD\n"); - fprintf(stderr, "Debug Info conversion systems. The following arguments are accepted:\n\n"); - - fprintf(stderr, "--exe: [optional] Specifies the path of the executable file for which the\n"); - fprintf(stderr, " debug info was generated.\n"); - fprintf(stderr, "--pdb: Specifies the path of the PDB debug info file to\n"); - fprintf(stderr, " convert.\n"); - fprintf(stderr, "--out: Specifies the path at which the output Breakpad debug\n"); - fprintf(stderr, " info will be written.\n\n"); - - if(!do_help) - { - for(String8Node *n = user2convert->errors.first; n != 0; n = n->next) - { - fprintf(stderr, "error(input): %.*s\n", str8_varg(n->string)); - } - } - os_abort(0); - } - - //- rjf: convert - P2R_Convert2Bake *convert2bake = 0; - ProfScope("convert") - { - convert2bake = p2r_convert(arena, user2convert); - } - - //- rjf: dump breakpad text - String8List dump = {0}; - ProfScope("dump breakpad text") - { - RDIM_BakeParams *params = &convert2bake->bake_params; - - //- rjf: kick off unit vmap baking - P2B_BakeUnitVMapIn bake_unit_vmap_in = {¶ms->units}; - ASYNC_Task *bake_unit_vmap_task = async_task_launch(arena, p2b_bake_unit_vmap_work, .input = &bake_unit_vmap_in); - - //- rjf: kick off line-table baking - P2B_BakeLineTablesIn bake_line_tables_in = {¶ms->line_tables}; - ASYNC_Task *bake_line_tables_task = async_task_launch(arena, p2b_bake_line_table_work, .input = &bake_line_tables_in); - - //- rjf: build unit -> line table idx array - U64 unit_count = params->units.total_count; - U32 *unit_line_table_idxs = push_array(arena, U32, unit_count+1); - { - U64 dst_idx = 1; - for(RDIM_UnitChunkNode *n = params->units.first; n != 0; n = n->next) - { - for(U64 n_idx = 0; n_idx < n->count; n_idx += 1, dst_idx += 1) - { - unit_line_table_idxs[dst_idx] = rdim_idx_from_line_table(n->v[n_idx].line_table); - } - } - } - - //- rjf: dump MODULE record - str8_list_pushf(arena, &dump, "MODULE windows x86_64 %I64x %S\n", params->top_level_info.exe_hash, params->top_level_info.exe_name); - - //- rjf: dump FILE records - ProfScope("dump FILE records") - { - for(RDIM_SrcFileChunkNode *n = params->src_files.first; n != 0; n = n->next) - { - for(U64 idx = 0; idx < n->count; idx += 1) - { - U64 file_idx = rdim_idx_from_src_file(&n->v[idx]); - String8 src_path = n->v[idx].normal_full_path; - str8_list_pushf(arena, &dump, "FILE %I64u %S\n", file_idx, src_path); - } - } - } - - //- rjf: join unit vmap - ProfBegin("join unit vmap"); - RDIM_UnitVMapBakeResult *bake_unit_vmap_out = async_task_join_struct(bake_unit_vmap_task, RDIM_UnitVMapBakeResult); - RDI_VMapEntry *unit_vmap = bake_unit_vmap_out->vmap.vmap; - U32 unit_vmap_count = bake_unit_vmap_out->vmap.count; - ProfEnd(); - - //- rjf: join line tables - ProfBegin("join line table"); - RDIM_LineTableBakeResult *bake_line_tables_out = async_task_join_struct(bake_line_tables_task, RDIM_LineTableBakeResult); - ProfEnd(); - - //- rjf: kick off FUNC & line record dump tasks - P2B_DumpProcChunkIn *dump_proc_chunk_in = push_array(arena, P2B_DumpProcChunkIn, params->procedures.chunk_count); - ASYNC_Task **dump_proc_chunk_tasks = push_array(arena, ASYNC_Task *, params->procedures.chunk_count); - ProfScope("kick off FUNC & line record dump tasks") - { - U64 task_idx = 0; - for(RDIM_SymbolChunkNode *n = params->procedures.first; n != 0; n = n->next, task_idx += 1) - { - dump_proc_chunk_in[task_idx].unit_vmap = unit_vmap; - dump_proc_chunk_in[task_idx].unit_vmap_count = unit_vmap_count; - dump_proc_chunk_in[task_idx].unit_line_table_idxs = unit_line_table_idxs; - dump_proc_chunk_in[task_idx].unit_count = unit_count; - dump_proc_chunk_in[task_idx].line_tables_bake = bake_line_tables_out; - dump_proc_chunk_in[task_idx].chunk = n; - dump_proc_chunk_tasks[task_idx] = async_task_launch(arena, p2b_dump_proc_chunk_work, .input = &dump_proc_chunk_in[task_idx]); - } - } - - //- rjf: join FUNC & line record dump tasks - ProfScope("join FUNC & line record dump tasks") - { - for(U64 idx = 0; idx < params->procedures.chunk_count; idx += 1) - { - String8List *out = async_task_join_struct(dump_proc_chunk_tasks[idx], String8List); - str8_list_concat_in_place(&dump, out); - } - } - } - - //- rjf: bake - String8 baked = {0}; - ProfScope("bake") - { - baked = str8_list_join(arena, &dump, 0); - } - - //- rjf: write - ProfScope("write") - { - OS_Handle output_file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Write, user2convert->output_name); - os_file_write(output_file, r1u64(0, baked.size), baked.str); - os_file_close(output_file); - } -} diff --git a/src/rdi_format/rdi_format.mdesk b/src/rdi_format/rdi_format.mdesk index aabc166d..a43bae13 100644 --- a/src/rdi_format/rdi_format.mdesk +++ b/src/rdi_format/rdi_format.mdesk @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -62,7 +62,7 @@ ""; "// \"raddbg\\0\\0\""; "#define RDI_MAGIC_CONSTANT 0x0000676264646172"; - "#define RDI_ENCODING_VERSION 11"; + "#define RDI_ENCODING_VERSION 12"; ""; "////////////////////////////////////////////////////////////////"; "//~ Format Types & Functions"; @@ -145,18 +145,21 @@ RDI_SectionTable: {GlobalVariables global_variables RDI_GlobalVariable 0x0016 - U32 ""} {GlobalVMap global_vmap RDI_VMapEntry 0x0017 - - ""} {ThreadVariables thread_variables RDI_ThreadVariable 0x0018 - U32 ""} - {Procedures procedures RDI_Procedure 0x0019 - U32 ""} - {Scopes scopes RDI_Scope 0x001A - U32 ""} - {ScopeVOffData scope_voff_data RDI_U64 0x001B - U32 ""} - {ScopeVMap scope_vmap RDI_VMapEntry 0x001C - - ""} - {InlineSites inline_sites RDI_InlineSite 0x001D - U32 ""} - {Locals locals RDI_Local 0x001E - U32 ""} - {LocationBlocks location_blocks RDI_LocationBlock 0x001F - U32 ""} - {LocationData location_data RDI_U8 0x0020 - U32 ""} - {NameMaps name_maps RDI_NameMap 0x0021 - U32 ""} - {NameMapBuckets name_map_buckets RDI_NameMapBucket 0x0022 - U32 ""} - {NameMapNodes name_map_nodes RDI_NameMapNode 0x0023 - U32 ""} - {COUNT count RDI_U8 0x0024 - - ""} + {Constants constants RDI_Constant 0x0019 - U32 ""} + {Procedures procedures RDI_Procedure 0x001A - U32 ""} + {Scopes scopes RDI_Scope 0x001B - U32 ""} + {ScopeVOffData scope_voff_data RDI_U64 0x001C - U32 ""} + {ScopeVMap scope_vmap RDI_VMapEntry 0x001D - - ""} + {InlineSites inline_sites RDI_InlineSite 0x001E - U32 ""} + {Locals locals RDI_Local 0x001F - U32 ""} + {LocationBlocks location_blocks RDI_LocationBlock 0x0020 - U32 ""} + {LocationData location_data RDI_U8 0x0021 - U32 ""} + {ConstantValueData constant_value_data RDI_U8 0x0022 - U32 ""} + {ConstantValueTable constant_value_table RDI_U32 0x0023 - U32 ""} + {NameMaps name_maps RDI_NameMap 0x0024 - U32 ""} + {NameMapBuckets name_map_buckets RDI_NameMapBucket 0x0025 - U32 ""} + {NameMapNodes name_map_nodes RDI_NameMapNode 0x0026 - U32 ""} + {COUNT count RDI_U8 0x0027 - - ""} } @table(name value) @@ -170,10 +173,10 @@ RDI_SectionEncodingTable: RDI_SectionMemberTable: { {encoding RDI_SectionEncoding ""} - {pad RDI_U32 ""} - {off RDI_U64 ""} - {encoded_size RDI_U64 ""} - {unpacked_size RDI_U64 ""} + {pad RDI_U32 ""} + {off RDI_U64 ""} + {encoded_size RDI_U64 ""} + {unpacked_size RDI_U64 ""} } @enum(RDI_U32) RDI_SectionKind: @@ -1024,6 +1027,14 @@ RDI_ThreadVariableMemberTable: {container_idx RDI_U32 ""} } +@table(name type desc) +RDI_ConstantMemberTable: +{ + {name_string_idx RDI_U32 ""} + {type_idx RDI_U32 ""} + {constant_value_idx RDI_U32 ""} +} + @table(name type desc) RDI_ProcedureMemberTable: { @@ -1199,6 +1210,11 @@ RDI_LocationRegMemberTable: @expand(RDI_ThreadVariableMemberTable a) `$(a.type) $(a.name)` } +@struct RDI_Constant: +{ + @expand(RDI_ConstantMemberTable a) `$(a.type) $(a.name)` +} + @struct RDI_Procedure: { @expand(RDI_ProcedureMemberTable a) `$(a.type) $(a.name)` @@ -1388,11 +1404,12 @@ RDI_NameMapKindTable: {NULL 0} {GlobalVariables 1} {ThreadVariables 2} - {Procedures 3} - {Types 4} - {LinkNameProcedures 5} - {NormalSourcePaths 6} - {COUNT 7} + {Constants 3} + {Procedures 4} + {Types 5} + {LinkNameProcedures 6} + {NormalSourcePaths 7} + {COUNT 8} } @table(name type desc) @@ -1467,12 +1484,12 @@ RDI_NameMapNodeMemberTable: @gen(functions) ``` RDI_PROC RDI_U64 rdi_hash(RDI_U8 *ptr, RDI_U64 size); +RDI_PROC RDI_U8 *rdi_string_from_type_kind(RDI_TypeKind kind, RDI_U64 *size_out); RDI_PROC RDI_U32 rdi_size_from_basic_type_kind(RDI_TypeKind kind); RDI_PROC RDI_U32 rdi_addr_size_from_arch(RDI_Arch arch); RDI_PROC RDI_EvalConversionKind rdi_eval_conversion_kind_from_typegroups(RDI_EvalTypeGroup in, RDI_EvalTypeGroup out); RDI_PROC RDI_S32 rdi_eval_op_typegroup_are_compatible(RDI_EvalOp op, RDI_EvalTypeGroup group); RDI_PROC RDI_U8 *rdi_explanation_string_from_eval_conversion_kind(RDI_EvalConversionKind kind, RDI_U64 *size_out); -RDI_PROC RDI_U8 *rdi_string_from_type_kind(RDI_TypeKind kind, RDI_U64 *size_out); ``` @gen(functions) @c_file diff --git a/src/rdi_format/rdi_format_local.c b/src/rdi_format/rdi_format_local.c index 5e134430..11fe38f3 100644 --- a/src/rdi_format/rdi_format_local.c +++ b/src/rdi_format/rdi_format_local.c @@ -1,9 +1,12 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "lib_rdi_format/rdi_format.c" #include "lib_rdi_format/rdi_format_parse.c" +//////////////////////////////// +//~ rjf: RDI Decompression + internal void rdi_decompress_parsed(U8 *decompressed_data, U64 decompressed_size, RDI_Parsed *og_rdi) { @@ -50,3 +53,1205 @@ rdi_decompress_parsed(U8 *decompressed_data, U64 decompressed_size, RDI_Parsed * } } +//////////////////////////////// +//~ rjf: Lookup Helpers + +internal String8 +str8_from_rdi_string_idx(RDI_Parsed *rdi, U32 idx) +{ + String8 result = {0}; + result.str = rdi_string_from_idx(rdi, idx, &result.size); + return result; +} + +//////////////////////////////// +//~ rjf: String <=> Enum + +internal String8 +rdi_string_from_data_section_kind(Arena *arena, RDI_SectionKind v) +{ + String8 result = {0}; + switch(v) + { + default:{result = push_str8f(arena, "", v);}break; +#define X(name, lower, type) case RDI_SectionKind_##name:{result = str8_lit(#name);}break; + RDI_SectionKind_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_arch(Arena *arena, RDI_Arch v) +{ + String8 result = {0}; + switch(v) + { + default:{result = push_str8f(arena, "", v);} break; +#define X(name) case RDI_Arch_##name:{result = str8_lit(#name);} break; + RDI_Arch_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_language(Arena *arena, RDI_Language v) +{ + String8 result = {0}; + switch(v) + { + default:{result = push_str8f(arena, "", v);}break; +#define X(name) case RDI_Language_##name:{result = str8_lit(#name);}break; + RDI_Language_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_local_kind(Arena *arena, RDI_LocalKind v) +{ + String8 result = {0}; + switch(v) + { + default:{result = push_str8f(arena, "", v);}break; +#define X(name) case RDI_LocalKind_##name:{result = str8_lit(#name);}break; + RDI_LocalKind_XList +#undef X + } + return result; +} + +#if 0 +internal String8 +rdi_string_from_type_kind(Arena *arena, RDI_TypeKind v) +{ + String8 result = {0}; + switch(v) + { + default:{result = push_str8f(arena, "", v);}break; +#define X(name) case RDI_TypeKind_##name:{result = str8_lit(#name);}break; + RDI_TypeKind_XList +#undef X + } + return result; +} +#endif + +internal String8 +rdi_string_from_member_kind(Arena *arena, RDI_MemberKind v) +{ + String8 result = {0}; + switch(v) + { + default:{result = push_str8f(arena, "", v);}break; +#define X(name) case RDI_MemberKind_##name:{result = str8_lit(#name);}break; + RDI_MemberKind_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_name_map_kind(RDI_NameMapKind kind) +{ + String8 result = {0}; + switch(kind) + { + default:{}break; +#define X(name) case RDI_NameMapKind_##name:{result = str8_lit(#name);}break; + RDI_NameMapKind_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_reg_code_x86(U64 reg_code) +{ + String8 result = {0}; + switch(reg_code) + { + default:{}break; +#define X(name, value) case RDI_RegCodeX86_##name:{result = str8_lit(#name);}break; + RDI_RegCodeX86_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_reg_code_x64(U64 reg_code) +{ + String8 result = {0}; + switch(reg_code) + { + default:{}break; +#define X(name, value) case RDI_RegCodeX64_##name:{result = str8_lit(#name);}break; + RDI_RegCodeX64_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_reg_code(Arena *arena, RDI_Arch arch, U64 reg_code) +{ + String8 result = {0}; + switch(arch) + { + default: + case RDI_Arch_NULL: {result = push_str8f(arena, "??? (%llu)", reg_code);}break; + case RDI_Arch_X86: {result = rdi_string_from_reg_code_x86(reg_code);}break; + case RDI_Arch_X64: {result = rdi_string_from_reg_code_x64(reg_code);}break; + } + return result; +} + +internal String8 +rdi_string_from_eval_op(Arena *arena, RDI_EvalOp op) +{ + String8 result = {0}; + switch(op) + { + default:{result = push_str8f(arena, "%#x", op);}break; +#define X(name) case RDI_EvalOp_##name:{result = str8_lit("#name");}break; + RDI_EvalOp_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_eval_type_group(Arena *arena, RDI_EvalTypeGroup eval_type_group) +{ + String8 result = {0}; + switch(eval_type_group) + { + default:{result = push_str8f(arena, "%#x", eval_type_group);}break; +#define X(name) case RDI_EvalTypeGroup_##name:{result = str8_lit("#name");}break; + RDI_EvalTypeGroup_XList +#undef X + } + return result; +} + +internal String8 +rdi_string_from_binary_section_flags(Arena *arena, RDI_BinarySectionFlags flags) +{ + Temp scratch = scratch_begin(&arena, 1); + String8List list = {0}; +#define X(name) if (flags & RDI_BinarySectionFlag_##name) { flags &= ~RDI_BinarySectionFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } + RDI_BinarySectionFlags_XList; +#undef X + StringJoin join = {.sep = str8_lit("|")}; + String8 result = str8_list_join(arena, &list, &join); + if(result.size == 0) { result = str8_lit("None"); } + scratch_end(scratch); + return result; +} + +internal String8 +rdi_string_from_type_modifier_flags(Arena *arena, RDI_TypeModifierFlags flags) +{ + Temp scratch = scratch_begin(&arena, 1); + String8List list = {0}; +#define X(name) if(flags & RDI_TypeModifierFlag_##name) { flags &= ~RDI_TypeModifierFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } + RDI_TypeModifierFlags_XList; +#undef X + StringJoin join = {.sep = str8_lit("|")}; + String8 result = str8_list_join(arena, &list, &join); + if(result.size == 0) { result = str8_lit("None"); } + scratch_end(scratch); + return result; +} + +internal String8 +rdi_string_from_udt_flags(Arena *arena, RDI_UDTFlags flags) +{ + Temp scratch = scratch_begin(&arena, 1); + String8List list = {0}; +#define X(name) if (flags & RDI_UDTFlag_##name) { flags &= ~RDI_UDTFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } + RDI_UDTFlags_XList; +#undef X + StringJoin join = {.sep = str8_lit("|")}; + String8 result = str8_list_join(arena, &list, &join); + if(result.size == 0) { result = str8_lit("None"); } + scratch_end(scratch); + return result; +} + +internal String8 +rdi_string_from_link_flags(Arena *arena, RDI_LinkFlags flags) +{ + Temp scratch = scratch_begin(&arena, 1); + String8List list = {0}; +#define X(name) if (flags & RDI_LinkFlag_##name) { flags &= ~RDI_LinkFlag_##name; str8_list_push(scratch.arena, &list, str8_lit(#name)); } + RDI_LinkFlags_XList; +#undef X + StringJoin join = {.sep = str8_lit("|")}; + String8 result = str8_list_join(arena, &list, &join); + if(result.size == 0) { result = str8_lit("None"); } + scratch_end(scratch); + return result; +} + +internal String8 +rdi_string_from_bytecode(Arena *arena, RDI_Arch arch, String8 bc) +{ + Temp scratch = scratch_begin(&arena, 1); + String8List fmt = {0}; + for(U64 cursor = 0; cursor < bc.size; ) + { + RDI_EvalOp op = RDI_EvalOp_Stop; + cursor += str8_deserial_read_struct(bc, cursor, &op); + + U16 ctrlbits = rdi_eval_op_ctrlbits_table[op]; + U32 imm_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); + + String8 imm = {0}; + cursor += str8_deserial_read_block(bc, cursor, imm_size, &imm); + if (imm.size != imm_size) { + str8_list_pushf(scratch.arena, &fmt, "(ERROR: not enough bytes to read immediate)"); + break; + } + + String8 imm_fmt = {0}; + switch (op) { + case RDI_EvalOp_Stop: goto exit; + case RDI_EvalOp_Noop: break; + case RDI_EvalOp_Cond: break; + case RDI_EvalOp_Skip: { + imm_fmt = push_str8f(scratch.arena, "%u", *(U16 *)imm.str); + } break; + case RDI_EvalOp_MemRead: { + imm_fmt = push_str8f(scratch.arena, "%u", *(U8 *)imm.str); + } break; + case RDI_EvalOp_RegRead: { + U32 regread = *(U32 *)imm.str; + RDI_RegCode reg_code = Extract8(regread, 0); + U8 byte_size = Extract8(regread, 1); + U8 byte_off = Extract8(regread, 2); + String8 reg_str = rdi_string_from_reg_code(scratch.arena, arch, reg_code); + imm_fmt = push_str8f(scratch.arena, "%S+%I64u, Size: %u", reg_str, byte_off, byte_size); + } break; + case RDI_EvalOp_RegReadDyn: break; + case RDI_EvalOp_FrameOff: { + imm_fmt = push_str8f(scratch.arena, "%+lld", *(S64 *)imm.str); + } break; + case RDI_EvalOp_ModuleOff: { + imm_fmt = push_str8f(scratch.arena, "%u", *(U32 *)imm.str); + } break; + case RDI_EvalOp_TLSOff: { + imm_fmt = push_str8f(scratch.arena, "%u", *(U32 *)imm.str); + } break; + case RDI_EvalOp_ConstU8: { + imm_fmt = push_str8f(scratch.arena, "%u", *(U8 *)imm.str); + } break; + case RDI_EvalOp_ConstU16: { + imm_fmt = push_str8f(scratch.arena, "%u", *(U16 *)imm.str); + } break; + case RDI_EvalOp_ConstU32: { + imm_fmt = push_str8f(scratch.arena, "%u", *(U32 *)imm.str); + } break; + case RDI_EvalOp_ConstU64: { + imm_fmt = push_str8f(scratch.arena, "%llu", *(U64 *)imm.str); + } break; + case RDI_EvalOp_ConstU128: { + imm_fmt = push_str8f(scratch.arena, "Lo: %llu, Hi: %llu", *(U64 *)imm.str, *((U64 *)imm.str + 1)); + } break; + case RDI_EvalOp_ConstString: { + U8 size = *(U8 *)imm.str; + String8 string = {0}; + cursor += str8_deserial_read_block(bc, cursor, size, &string); + + imm_fmt = push_str8f(scratch.arena, "(%u) \"%S\"", size, string); + } break; + case RDI_EvalOp_Abs: + case RDI_EvalOp_Neg: + case RDI_EvalOp_Add: + case RDI_EvalOp_Sub: + case RDI_EvalOp_Mul: + case RDI_EvalOp_Div: + case RDI_EvalOp_Mod: + case RDI_EvalOp_LShift: + case RDI_EvalOp_RShift: + case RDI_EvalOp_BitAnd: + case RDI_EvalOp_BitOr: + case RDI_EvalOp_BitXor: + case RDI_EvalOp_BitNot: + case RDI_EvalOp_LogAnd: + case RDI_EvalOp_LogOr: + case RDI_EvalOp_LogNot: + case RDI_EvalOp_EqEq: + case RDI_EvalOp_NtEq: + case RDI_EvalOp_LsEq: + case RDI_EvalOp_GrEq: + case RDI_EvalOp_Less: + case RDI_EvalOp_Grtr: { + U8 eval_type_group = *(U8 *)imm.str; + imm_fmt = rdi_string_from_eval_type_group(scratch.arena, eval_type_group); + } break; + case RDI_EvalOp_Trunc: + case RDI_EvalOp_TruncSigned: { + U8 trunc = *(U8 *)imm.str; + imm_fmt = push_str8f(scratch.arena, "%u", trunc); + } break; + case RDI_EvalOp_Convert: { + U16 convert = *(U16 *)imm.str; + U8 in = Extract8(convert, 0); + U8 out = Extract8(convert, 1); + String8 in_str = rdi_string_from_eval_type_group(scratch.arena, in); + String8 out_str = rdi_string_from_eval_type_group(scratch.arena, out); + imm_fmt = push_str8f(scratch.arena, "in: %S out: %S", in_str, out_str); + } break; + case RDI_EvalOp_Pick: { + U8 pick = *(U8 *)imm.str; + imm_fmt = push_str8f(scratch.arena, "%u", pick); + } break; + case RDI_EvalOp_Pop: break; + case RDI_EvalOp_Insert: { + U8 insert = *(U8 *)imm.str; + imm_fmt = push_str8f(scratch.arena, "%u", insert); + } break; + case RDI_EvalOp_ValueRead: { + U8 bytes_to_read = *(U8 *)imm.str; + imm_fmt = push_str8f(scratch.arena, "%u", bytes_to_read); + } break; + case RDI_EvalOp_ByteSwap: { + U8 byte_size = *(U8 *)imm.str; + imm_fmt = push_str8f(scratch.arena, "%u", byte_size); + } break; + case RDI_EvalOp_CallSiteValue: { + U32 call_site_bc_size = *(U32 *)imm.str; + String8 call_site_bc = {0}; + cursor += str8_deserial_read_block(bc, cursor, call_site_bc_size, &call_site_bc); + + String8 call_site_str = rdi_string_from_bytecode(scratch.arena, arch, call_site_bc); + imm_fmt = push_str8f(scratch.arena, "%S", call_site_str); + } break; + case RDI_EvalOp_PartialValue: { + U32 partial_value_size = *(U32 *)imm.str; + imm_fmt = push_str8f(scratch.arena, "%u", partial_value_size); + } break; + case RDI_EvalOp_PartialValueBit: { + U64 partial_value = *(U64 *)imm.str; + U32 bit_size = Extract32(partial_value, 0); + U32 bit_off = Extract32(partial_value, 1); + imm_fmt = push_str8f(scratch.arena, "Off: %u, Size: %u", bit_size, bit_off); + } break; + } + + String8 op_str = rdi_string_from_eval_op(scratch.arena, op); + if (imm_fmt.size) { + str8_list_pushf(scratch.arena, &fmt, "RDI_EvalOp_%S(%S)", op_str, imm_fmt); + } else { + str8_list_pushf(scratch.arena, &fmt, "RDI_EvalOp_%S", op_str); + } + } + exit:; + + String8 result = str8_list_join(arena, &fmt, &(StringJoin){.sep = str8_lit(", ")}); + + scratch_end(scratch); + return result; +} + +internal String8List +rdi_strings_from_locations(Arena *arena, RDI_Parsed *rdi, RDI_Arch arch, Rng1U64 location_block_range) +{ + String8List strings = {0}; + Temp scratch = scratch_begin(&arena, 1); + U64 location_block_count = 0; + U64 location_data_size = 0; + RDI_LocationBlock *location_block_array = rdi_table_from_name(rdi, LocationBlocks, &location_block_count); + RDI_U8 *location_data = rdi_table_from_name(rdi, LocationData, &location_data_size); + Rng1U64 location_block_range_clamped = r1u64(ClampTop(location_block_range.min, location_block_count), + ClampTop(location_block_range.max, location_block_count)); + for(U64 block_idx = location_block_range_clamped.min; + block_idx < location_block_range_clamped.max; + block_idx +=1) + { + String8 qualifier = {0}; + String8 location_info = {0}; + RDI_LocationBlock *block_ptr = &location_block_array[block_idx]; + if(block_ptr->scope_off_first == 0 && block_ptr->scope_off_opl == max_U32) + { + qualifier = str8_lit("*always*"); + } + else + { + qualifier = push_str8f(scratch.arena, "[%#08x, %#08x): ", block_ptr->scope_off_first, block_ptr->scope_off_opl); + } + if(block_ptr->location_data_off >= location_data_size) + { + location_info = push_str8f(scratch.arena, "", block_ptr->location_data_off); + } + else + { + U8 *loc_data_opl = location_data + location_data_size; + U8 *loc_base_ptr = location_data + block_ptr->location_data_off; + RDI_LocationKind kind = *(RDI_LocationKind *)loc_base_ptr; + switch(kind) + { + default: + { + location_info = push_str8f(scratch.arena, "\?\?\? (%u)", kind); + }break; + case RDI_LocationKind_AddrBytecodeStream: + { + String8 bc = str8_range(loc_base_ptr + 1, loc_data_opl); + String8 bc_str = rdi_string_from_bytecode(scratch.arena, arch, bc); + location_info = push_str8f(scratch.arena, "AddrBytecodeStream(%S)", bc_str); + }break; + case RDI_LocationKind_ValBytecodeStream: + { + String8 bc = str8_range(loc_base_ptr + 1, loc_data_opl); + String8 bc_str = rdi_string_from_bytecode(scratch.arena, arch, bc); + location_info = push_str8f(scratch.arena, "ValBytecodeStream(%S)", bc_str); + }break; + case RDI_LocationKind_AddrRegPlusU16: + { + if(loc_base_ptr + sizeof(RDI_LocationRegPlusU16) > loc_data_opl) + { + location_info = push_str8f(scratch.arena, "AddrRegPlusU16(\?\?\?)"); + } + else + { + RDI_LocationRegPlusU16 *loc = (RDI_LocationRegPlusU16*)loc_base_ptr; + location_info = push_str8f(scratch.arena, "AddrRegPlusU16(reg: %S, off: %u)", rdi_string_from_reg_code(scratch.arena, arch, loc->reg_code), loc->offset); + } + }break; + case RDI_LocationKind_AddrAddrRegPlusU16: + { + if(loc_base_ptr + sizeof(RDI_LocationRegPlusU16) > loc_data_opl) + { + location_info = push_str8f(scratch.arena, "AddrAddrRegPlusU16(\?\?\?)"); + } + else + { + RDI_LocationRegPlusU16 *loc = (RDI_LocationRegPlusU16 *)loc_base_ptr; + location_info = push_str8f(scratch.arena, "AddrAddrRegisterPlusU16(reg: %S, off: %u)", rdi_string_from_reg_code(scratch.arena, arch, loc->reg_code), loc->offset); + } + }break; + case RDI_LocationKind_ValReg: + { + if(loc_base_ptr + sizeof(RDI_LocationReg) > loc_data_opl) + { + location_info = push_str8f(scratch.arena, "ValReg(\?\?\?)"); + } + else + { + RDI_LocationReg *loc = (RDI_LocationReg*)loc_base_ptr; + location_info = push_str8f(scratch.arena, "ValReg(reg: %S)", rdi_string_from_reg_code(scratch.arena, arch, loc->reg_code)); + } + } break; + } + } + str8_list_pushf(arena, &strings, "%S: %S", qualifier, location_info); + } + scratch_end(scratch); + return strings; +} + +//////////////////////////////// +//~ rjf: RDI Dumping + +internal String8List +rdi_dump_list_from_parsed(Arena *arena, RDI_Parsed *rdi, RDI_DumpSubsetFlags flags) +{ + String8List strings = {0}; + String8 indent = str8_lit(" "); +#define dump(str) str8_list_push(arena, &strings, (str)) +#define dumpf(...) str8_list_pushf(arena, &strings, __VA_ARGS__) +#define DumpSubset(name) if(flags & RDI_DumpSubsetFlag_##name) DeferLoop(dumpf("# %S\n\n", rdi_name_title_from_dump_subset_table[RDI_DumpSubset_##name]), dump(str8_lit("\n"))) + + ////////////////////////////// + //- rjf: dump data sections + // + DumpSubset(DataSections) + { + for EachIndex(idx, rdi->sections_count) + { + Temp scratch = scratch_begin(&arena, 1); + RDI_SectionKind kind = (RDI_SectionKind)idx; + RDI_Section *section = &rdi->sections[idx]; + String8 kind_str = rdi_string_from_data_section_kind(scratch.arena, kind); + dumpf("data_section[%5llu] = {%#08llx, %7u, %7u}, %S\n", idx, section->off, section->encoded_size, section->unpacked_size, kind_str); + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump top-level-info + // + DumpSubset(TopLevelInfo) + { + RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); + Temp scratch = scratch_begin(&arena, 1); + dumpf("arch =%S\n", rdi_string_from_arch(scratch.arena, tli->arch)); + dumpf("exe_name ='%S'\n", str8_from_rdi_string_idx(rdi, tli->exe_name_string_idx)); + dumpf("voff_max =%#08llx\n", tli->voff_max); + dumpf("producer_name='%S'\n", str8_from_rdi_string_idx(rdi, tli->producer_name_string_idx)); + scratch_end(scratch); + } + + ////////////////////////////// + //- rjf: dump binary sections + // + DumpSubset(BinarySections) + { + U64 count = 0; + RDI_BinarySection *v = rdi_table_from_name(rdi, BinarySections, &count); + for EachIndex(idx, count) + { + Temp scratch = scratch_begin(&arena, 1); + RDI_BinarySection *bin_section = &v[idx]; + dumpf("binary_section[%I64u]:\n", idx); + dumpf(" name ='%S'\n", str8_from_rdi_string_idx(rdi, bin_section->name_string_idx)); + dumpf(" flags =%S\n", rdi_string_from_binary_section_flags(scratch.arena, bin_section->flags)); + dumpf(" voff_first=%#08x\n", bin_section->voff_first); + dumpf(" voff_opl =%#08x\n", bin_section->voff_opl); + dumpf(" foff_first=%#08x\n", bin_section->foff_first); + dumpf(" foff_opl =%#08x\n", bin_section->foff_opl); + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump file paths + // + DumpSubset(FilePaths) + { + U64 count = 0; + RDI_FilePathNode *v = rdi_table_from_name(rdi, FilePathNodes, &count); + RDI_FilePathNode *nil = &v[0]; + for EachIndex(idx, count) + { + RDI_FilePathNode *root = &v[idx]; + if(root->parent_path_node != 0) { continue; } + S64 depth = 0; + for(RDI_FilePathNode *n = root, *rec_next = nil; n != nil; n = rec_next) + { + // rjf: dump + if(n->source_file_idx == 0) + { + dumpf("%.*s[%I64u] '%S'\n", depth*2, indent.str, (U64)(n - v), str8_from_rdi_string_idx(rdi, n->name_string_idx)); + } + else + { + dumpf("%.*s[%I64u] '%S': source_file=%u\n", depth*2, indent.str, (U64)(n - v), str8_from_rdi_string_idx(rdi, n->name_string_idx), n->source_file_idx); + } + + // rjf: find next node + rec_next = nil; + if(n->first_child) + { + rec_next = rdi_element_from_name_idx(rdi, FilePathNodes, n->first_child); + depth += 1; + } + else for(RDI_FilePathNode *p = n; + p != nil && p != root; + p = rdi_element_from_name_idx(rdi, FilePathNodes, p->parent_path_node), depth -= 1) + { + if(p->next_sibling) + { + rec_next = rdi_element_from_name_idx(rdi, FilePathNodes, p->next_sibling); + break; + } + } + } + } + } + + ////////////////////////////// + //- rjf: dump source files + // + DumpSubset(SourceFiles) + { + U64 source_file_count = 0; + RDI_SourceFile *source_file_array = rdi_table_from_name(rdi, SourceFiles, &source_file_count); + for(U64 i = 0; i < source_file_count; ++i) + { + RDI_SourceFile *source_file = &source_file_array[i]; + dumpf("source_file[%4llu] = { file_path_node_idx = %4u, source_line_map = %4u, path = '%S' }\n", + i, + source_file->file_path_node_idx, + source_file->source_line_map_idx, + str8_from_rdi_string_idx(rdi, source_file->normal_full_path_string_idx)); + } + } + + ////////////////////////////// + //- rjf: dump units + // + DumpSubset(Units) + { + U64 count = 0; + RDI_Unit *v = rdi_table_from_name(rdi, Units, &count); + for EachIndex(idx, count) + { + RDI_Unit *unit = &v[idx]; + Temp scratch = scratch_begin(&arena, 1); + dumpf("unit[%I64u]:\n", idx); + dumpf(" unit_name ='%S'\n", str8_from_rdi_string_idx(rdi, unit->unit_name_string_idx)); + dumpf(" compiler_name ='%S'\n", str8_from_rdi_string_idx(rdi, unit->compiler_name_string_idx)); + dumpf(" source_file_path =%u\n", unit->source_file_path_node); + dumpf(" object_file_path =%u\n", unit->object_file_path_node); + dumpf(" archive_file_path=%u\n", unit->archive_file_path_node); + dumpf(" build_path =%u\n", unit->build_path_node); + dumpf(" language =%S\n", rdi_string_from_language(scratch.arena, unit->language)); + dumpf(" line_table_idx =%u\n", unit->line_table_idx); + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump unit vmap + // + DumpSubset(UnitVMap) + { + U64 count = 0; + RDI_VMapEntry *v = rdi_table_from_name(rdi, UnitVMap, &count); + for EachIndex(idx, count) + { + dumpf("%I64x -> #%I64u\n", v[idx].voff, v[idx].idx); + } + } + + ////////////////////////////// + //- rjf: dump line tables + // + DumpSubset(LineTables) + { + U64 count = 0; + RDI_LineTable *v = rdi_table_from_name(rdi, LineTables, &count); + for EachIndex(idx, count) + { + RDI_LineTable *line_table = &v[idx]; + RDI_ParsedLineTable parsed_line_table = {0}; + rdi_parsed_from_line_table(rdi, line_table, &parsed_line_table); + dumpf("line_table[%I64u]:\n", idx); + for EachIndex(line_idx, parsed_line_table.count) + { + U64 first = parsed_line_table.voffs[line_idx]; + U64 opl = parsed_line_table.voffs[line_idx + 1]; + RDI_Line *line = parsed_line_table.lines + line_idx; + RDI_Column *col = 0; + if(line_idx < parsed_line_table.col_count) + { + col = parsed_line_table.cols + line_idx; + } + if(col == 0) + { + dumpf(" [0x%08I64x,0x%08I64x) file=%u; line=%u\n", first, opl, line->file_idx, line->line_num); + } + else + { + dumpf(" [0x%08I64x,0x%08I64x) file=%u; line=%u; columns=[%u,%u)\n", first, opl, line->file_idx, line->line_num, col->col_first, col->col_opl); + } + } + } + } + + ////////////////////////////// + //- rjf: dump source line maps + // + DumpSubset(SourceLineMaps) + { + U64 count = 0; + RDI_SourceLineMap *v = rdi_table_from_name(rdi, SourceLineMaps, &count); + for EachIndex(idx, count) + { + Temp scratch = scratch_begin(&arena, 1); + RDI_ParsedSourceLineMap line_map = {0}; + rdi_parsed_from_source_line_map(rdi, &v[idx], &line_map); + dumpf("source_line_map[%I64u]:\n", idx); + for EachIndex(line_num_idx, line_map.count) + { + Temp temp = temp_begin(scratch.arena); + String8List list = {0}; + U32 voff_lo = line_map.ranges[line_num_idx]; + U32 voff_hi = ClampTop(line_map.ranges[line_num_idx + 1], line_map.voff_count); + for(U64 voff_idx = voff_lo; voff_idx < voff_hi; voff_idx += 1) + { + str8_list_pushf(temp.arena, &list, "%#llx", line_map.voffs[voff_idx]); + } + String8 voffs_string = str8_list_join(temp.arena, &list, &(StringJoin){.sep = str8_lit(", ")}); + dumpf(" %u: %S\n", line_map.nums[line_num_idx], voffs_string); + temp_end(temp); + } + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump type nodes + // + DumpSubset(TypeNodes) + { + U64 count = 0; + RDI_TypeNode *v = rdi_table_from_name(rdi, TypeNodes, &count); + for EachIndex(idx, count) + { + Temp scratch = scratch_begin(&arena, 1); + RDI_TypeNode *type = &v[idx]; + String8 type_kind_str = {0}; + type_kind_str.str = rdi_string_from_type_kind(type->kind, &type_kind_str.size); + dumpf("type[%I64u]:\n", idx); + dumpf(" kind =%S\n", type_kind_str); + if(type->kind == RDI_TypeKind_Modifier) + { + dumpf(" flags =%S\n", rdi_string_from_type_modifier_flags(scratch.arena, type->flags)); + } + else if(type->flags != 0) + { + dumpf(" flags=%#x (missing stringizer path)\n", type->flags); + } + dumpf(" byte_size =%u\n", type->byte_size); + if(RDI_TypeKind_FirstBuiltIn <= type->kind && type->kind <= RDI_TypeKind_LastBuiltIn) + { + dumpf(" built_in.name ='%S'\n", str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx)); + } + else if(type->kind == RDI_TypeKind_Array) + { + dumpf(" constructed.direct_type =%u\n", type->constructed.direct_type_idx); + dumpf(" constructed.array_count =%u\n", type->constructed.count); + } + else if(type->kind == RDI_TypeKind_Function) + { + U32 param_idx_count = 0; + U32 *param_idx_array = rdi_idx_run_from_first_count(rdi, type->constructed.param_idx_run_first, type->constructed.count, ¶m_idx_count); + String8List param_idx_strings = {0}; + for(U32 param_idx = 0; param_idx < param_idx_count; param_idx += 1) + { + str8_list_pushf(scratch.arena, ¶m_idx_strings, "%u", param_idx_array[param_idx]); + } + String8 param_idx_str = str8_list_join(scratch.arena, ¶m_idx_strings, &(StringJoin){.pre = str8_lit("["), .sep = str8_lit(", "), .post = str8_lit("]")}); + dumpf(" constructed.params =%S\n", param_idx_str); + dumpf(" return_type =%u\n", type->constructed.direct_type_idx); + } + else if(type->kind == RDI_TypeKind_Method) + { + U32 param_idx_count = 0; + U32 *param_idx_array = rdi_idx_run_from_first_count(rdi, type->constructed.param_idx_run_first, type->constructed.count, ¶m_idx_count); + String8 this_type_str = str8_lit("\?\?\?"); + if(param_idx_count > 0) + { + this_type_str = push_str8f(scratch.arena, "%u", param_idx_array[0]); + param_idx_count -= 1; + param_idx_array += 1; + } + String8List param_idx_strings = {0}; + for(U32 param_idx = 0; param_idx < param_idx_count; param_idx += 1) + { + str8_list_pushf(scratch.arena, ¶m_idx_strings, "%u", param_idx_array[param_idx]); + } + String8 param_idx_str = str8_list_join(scratch.arena, ¶m_idx_strings, &(StringJoin){.pre = str8_lit("["), .sep = str8_lit(", "), .post = str8_lit("]")}); + dumpf(" constructed.this_type =%S\n", this_type_str); + dumpf(" constructed.params =%S\n", param_idx_str); + dumpf(" return_type =%u\n", type->constructed.direct_type_idx); + } + else if(RDI_TypeKind_FirstConstructed <= type->kind && type->kind <= RDI_TypeKind_LastConstructed) + { + dumpf(" constructed.direct_type =%u\n", type->constructed.direct_type_idx); + } + else if(RDI_TypeKind_FirstUserDefined <= type->kind && type->kind <= RDI_TypeKind_LastUserDefined) + { + dumpf(" user_defined.name ='%S'\n", str8_from_rdi_string_idx(rdi, type->user_defined.name_string_idx)); + dumpf(" user_defined.direct_type=%u\n", type->user_defined.direct_type_idx); + dumpf(" user_defined.udt =%u\n", type->user_defined.udt_idx); + } + else if(type->kind == RDI_TypeKind_Bitfield) + { + dumpf(" bitfield.off =%u\n", type->bitfield.off); + dumpf(" bitfield.size =%u\n", type->bitfield.size); + } + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump user defined types + // + DumpSubset(UserDefinedTypes) + { + U64 count = 0; + RDI_UDT *v = rdi_table_from_name(rdi, UDTs, &count); + U64 all_members_count = 0; + RDI_Member *all_members = rdi_table_from_name(rdi, Members, &all_members_count); + U64 all_enum_members_count = 0; + RDI_EnumMember *all_enum_members = rdi_table_from_name(rdi, EnumMembers, &all_enum_members_count); + for EachIndex(idx, count) + { + RDI_UDT *udt = &v[idx]; + Temp scratch = scratch_begin(&arena, 1); + dumpf("udt[%I64u]:\n", idx); + dumpf(" self_type=%u\n", udt->self_type_idx); + dumpf(" flags =%S\n", rdi_string_from_udt_flags(scratch.arena, udt->flags)); + if(udt->file_idx != 0) + { + dumpf(" loc ={file=%u; line=%u; col=%u}\n", udt->file_idx, udt->line, udt->col); + } + if(udt->flags & RDI_UDTFlag_EnumMembers) + { + U32 member_hi = ClampTop(udt->member_first + udt->member_count, all_enum_members_count); + U32 member_lo = ClampTop(udt->member_first, member_hi); + if(member_lo < member_hi) + { + dumpf(" enum_members=\n"); + dumpf(" {\n"); + for(U32 enum_member_idx = member_lo; enum_member_idx < member_hi; enum_member_idx += 1) + { + RDI_EnumMember *enum_member = &all_enum_members[enum_member_idx]; + dumpf(" { %llu, '%S' }\n", enum_member->val, str8_from_rdi_string_idx(rdi, enum_member->name_string_idx)); + } + dumpf(" }\n"); + } + } + else + { + U32 member_hi = ClampTop(udt->member_first + udt->member_count, all_members_count); + U32 member_lo = ClampTop(udt->member_first, member_hi); + if(member_lo < member_hi) + { + dumpf(" members=\n"); + dumpf(" {\n"); + for(U32 member_idx = member_lo; member_idx < member_hi; member_idx += 1) + { + RDI_Member *member = &all_members[member_idx]; + String8 kind_str = rdi_string_from_member_kind(scratch.arena, member->kind); + String8 name_str = str8_from_rdi_string_idx(rdi, member->name_string_idx); + dumpf(" { kind=%S, type=%u, off=%u, name='%S' }\n", kind_str, member->type_idx, member->off, name_str); + } + dumpf(" }\n"); + } + } + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump global variables + // + DumpSubset(GlobalVariables) + { + U64 count = 0; + RDI_GlobalVariable *v = rdi_table_from_name(rdi, GlobalVariables, &count); + for EachIndex(idx, count) + { + RDI_GlobalVariable *gvar = &v[idx]; + Temp scratch = scratch_begin(&arena, 1); + dumpf("global_variable[%I64u]:\n", idx); + dumpf(" name ='%S'\n", str8_from_rdi_string_idx(rdi, gvar->name_string_idx)); + dumpf(" link_flags =%S\n", rdi_string_from_link_flags(scratch.arena, gvar->link_flags)); + dumpf(" voff =%#08x\n", gvar->voff); + dumpf(" type_idx =%u\n", gvar->type_idx); + dumpf(" container_idx=%u\n", gvar->container_idx); + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump global variables vmap + // + DumpSubset(GlobalVariablesVMap) + { + U64 count = 0; + RDI_VMapEntry *v = rdi_table_from_name(rdi, GlobalVMap, &count); + for EachIndex(idx, count) + { + dumpf("%I64x -> #%I64u\n", v[idx].voff, v[idx].idx); + } + } + + ////////////////////////////// + //- rjf: dump thread variables + // + DumpSubset(ThreadVariables) + { + U64 count = 0; + RDI_ThreadVariable *v = rdi_table_from_name(rdi, ThreadVariables, &count); + for EachIndex(idx, count) + { + RDI_ThreadVariable *tvar = &v[idx]; + Temp scratch = scratch_begin(&arena, 1); + dumpf("thread_variable[%I64u]:\n", idx); + dumpf(" name ='%S'\n", str8_from_rdi_string_idx(rdi, tvar->name_string_idx)); + dumpf(" link_flags =%S\n", rdi_string_from_link_flags(scratch.arena, tvar->link_flags)); + dumpf(" tls_off =%#08x\n", tvar->tls_off); + dumpf(" type_idx =%u\n", tvar->type_idx); + dumpf(" container_idx=%u\n", tvar->container_idx); + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump constants + // + DumpSubset(Constants) + { + U64 count = 0; + RDI_Constant *v = rdi_table_from_name(rdi, Constants, &count); + for EachIndex(idx, count) + { + RDI_Constant *cnst = &v[idx]; + dumpf("constant[%I64u]:\n", idx); + dumpf(" name ='%S'\n", str8_from_rdi_string_idx(rdi, cnst->name_string_idx)); + dumpf(" type_idx ='%u'\n", cnst->type_idx); + } + } + + ////////////////////////////// + //- rjf: dump procedures + // + DumpSubset(Procedures) + { + RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); + U64 count = 0; + RDI_Procedure *v = rdi_table_from_name(rdi, Procedures, &count); + for EachIndex(idx, count) + { + RDI_Procedure *proc = &v[idx]; + Temp scratch = scratch_begin(&arena, 1); + String8List frame_base_location_strings = rdi_strings_from_locations(scratch.arena, rdi, tli->arch, r1u64(proc->frame_base_location_first, proc->frame_base_location_opl)); + dumpf("procedure[%I64u]:\n", idx); + dumpf(" name ='%S'\n", str8_from_rdi_string_idx(rdi, proc->name_string_idx)); + dumpf(" link_name ='%S'\n", str8_from_rdi_string_idx(rdi, proc->link_name_string_idx)); + dumpf(" link_flags =%S\n", rdi_string_from_link_flags(scratch.arena, proc->link_flags)); + dumpf(" type_idx =%u\n", proc->type_idx); + dumpf(" root_scope_idx =%u\n", proc->root_scope_idx); + dumpf(" container_idx =%u\n", proc->container_idx); + dumpf(" frame_base (first=%u, opl=%u)=\n", proc->frame_base_location_first, proc->frame_base_location_opl); + dumpf(" {\n"); + for(String8Node *n = frame_base_location_strings.first; n != 0; n = n->next) + { + dumpf(" %S\n", n->string); + } + dumpf(" }\n"); + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump scopes + // + DumpSubset(Scopes) + { + RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); + U64 scope_voffs_count = 0; + U64 *scope_voffs = rdi_table_from_name(rdi, ScopeVOffData, &scope_voffs_count); + U64 locals_count = 0; + RDI_Local *locals = rdi_table_from_name(rdi, Locals, &locals_count); + U64 count = 0; + RDI_Scope *v = rdi_table_from_name(rdi, Scopes, &count); + RDI_Scope *nil = &v[0]; + for EachIndex(idx, count) + { + if(v[idx].parent_scope_idx != 0) { continue; } + RDI_Scope *root = &v[idx]; + S64 depth = 0; + for(RDI_Scope *scope = root, *rec_next = nil; scope != nil; scope = rec_next) + { + // rjf: scope list(voff_range) => string + String8 voff_range_list_string = {0}; + { + U32 voff_range_lo = ClampTop(scope->voff_range_first, scope_voffs_count); + U32 voff_range_hi = ClampTop(scope->voff_range_opl, scope_voffs_count); + U32 voff_range_count = (voff_range_hi - voff_range_lo); + U64 *voff_ptr = scope_voffs + voff_range_lo; + Temp scratch = scratch_begin(&arena, 1); + String8List list = {0}; + for(U64 i = 0; i+2 <= voff_range_count; i += 2) + { + str8_list_pushf(scratch.arena, &list, "[%#llx, %#llx)", voff_ptr[i+0], voff_ptr[i+1]); + } + voff_range_list_string = str8_list_join(arena, &list, &(StringJoin){.sep = str8_lit(", ")}); + scratch_end(scratch); + } + + // rjf: scope procedure -> name + String8 procedure_name = str8_from_rdi_string_idx(rdi, rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx)->name_string_idx); + if(procedure_name.size == 0) + { + procedure_name = str8_lit("???"); + } + + // rjf: scope inline site -> name + String8 inline_site_name = str8_from_rdi_string_idx(rdi, rdi_element_from_name_idx(rdi, InlineSites, scope->inline_site_idx)->name_string_idx); + if(inline_site_name.size == 0) + { + inline_site_name = str8_lit("???"); + } + + // rjf: dump + dumpf("%.*sscope[%I64u]:\n", depth*2, indent.str, (U64)(scope - v)); + dumpf("%.*s{\n", depth*2, indent.str); + dumpf("%.*s proc_idx =%u ('%S')\n", depth*2, indent.str, scope->proc_idx, procedure_name); + dumpf("%.*s first_child_scope_idx =%u\n", depth*2, indent.str, scope->first_child_scope_idx); + dumpf("%.*s next_sibling_scope_idx=%u\n", depth*2, indent.str, scope->next_sibling_scope_idx); + if(scope->inline_site_idx != 0) + { + dumpf("%.*s inline_site_idx =%u ('%S')\n", depth*2, indent.str, scope->inline_site_idx, inline_site_name); + } + dumpf("%.*s voff_ranges =%S\n", depth*2, indent.str, voff_range_list_string); + dumpf("%.*s locals=\n", depth*2, indent.str); + dumpf("%.*s {\n", depth*2, indent.str); + { + U32 local_lo = ClampTop(scope->local_first, locals_count); + U32 local_hi = ClampTop(local_lo + scope->local_count, locals_count); + if(local_lo < local_hi) + { + for(U32 local_idx = local_lo; local_idx < local_hi; local_idx += 1) + { + Temp scratch = scratch_begin(&arena, 1); + RDI_Local *local_ptr = &locals[local_idx]; + dumpf("%.*s local[%u]:\n", depth*2, indent.str, local_idx); + dumpf("%.*s kind =%S\n", depth*2, indent.str, rdi_string_from_local_kind(scratch.arena, local_ptr->kind)); + dumpf("%.*s name ='%S'\n", depth*2, indent.str, str8_from_rdi_string_idx(rdi, local_ptr->name_string_idx)); + dumpf("%.*s type_idx=%u\n", depth*2, indent.str, local_ptr->type_idx); + dumpf("%.*s locations=\n", depth*2, indent.str); + dumpf("%.*s {\n", depth*2, indent.str); + if(local_ptr->location_first < local_ptr->location_opl) + { + String8List locations_strings = rdi_strings_from_locations(arena, rdi, tli->arch, r1u64(local_ptr->location_first, local_ptr->location_opl)); + for(String8Node *n = locations_strings.first; n != 0; n = n->next) + { + dumpf("%.*s %S\n", depth*2, indent.str, n->string); + } + } + dumpf("%.*s }\n", depth*2, indent.str); + scratch_end(scratch); + } + } + } + dumpf("%.*s }\n", depth*2, indent.str); + + // rjf: get next recursion + rec_next = nil; + if(scope->first_child_scope_idx) + { + rec_next = rdi_element_from_name_idx(rdi, Scopes, scope->first_child_scope_idx); + depth += 1; + } + else for(RDI_Scope *p = scope; + p != nil; + p = rdi_element_from_name_idx(rdi, Scopes, p->parent_scope_idx), depth -= 1) + { + dumpf("%.*s} [/%I64u] \n", depth*2, indent.str, (U64)(p-v)); + if(p->next_sibling_scope_idx != 0) + { + rec_next = rdi_element_from_name_idx(rdi, Scopes, p->next_sibling_scope_idx); + break; + } + } + } + } + } + + ////////////////////////////// + //- rjf: dump scope vmap + // + DumpSubset(ScopeVMap) + { + U64 count = 0; + RDI_VMapEntry *v = rdi_table_from_name(rdi, ScopeVMap, &count); + for EachIndex(idx, count) + { + dumpf("%I64x -> #%I64u\n", v[idx].voff, v[idx].idx); + } + } + + ////////////////////////////// + //- rjf: dump inline sites + // + DumpSubset(InlineSites) + { + U64 count = 0; + RDI_InlineSite *v = rdi_table_from_name(rdi, InlineSites, &count); + for EachIndex(idx, count) + { + RDI_InlineSite *inline_site = &v[idx]; + Temp scratch = scratch_begin(&arena, 1); + String8 inline_site_idx = push_str8f(scratch.arena, "inline_site[%u]", idx); + String8 type_idx = push_str8f(scratch.arena, "type_idx = %u,", inline_site->type_idx); + String8 owner_type_idx = push_str8f(scratch.arena, "owner_type_idx = %u,", inline_site->owner_type_idx); + String8 line_table_idx = push_str8f(scratch.arena, "line_table_idx = %u,", inline_site->line_table_idx); + dumpf("%-20S = { %-25S %-25S %-25S name = '%-20S' }\n", + inline_site_idx, + type_idx, + owner_type_idx, + line_table_idx, + str8_from_rdi_string_idx(rdi, inline_site->name_string_idx)); + scratch_end(scratch); + } + } + + ////////////////////////////// + //- rjf: dump name maps + // + DumpSubset(NameMaps) + { + Temp scratch = scratch_begin(&arena, 1); + U64 count = 0; + RDI_NameMap *v = rdi_table_from_name(rdi, NameMaps, &count); + for EachIndex(idx, count) + { + if(idx > 0) { dumpf("\n"); } + RDI_ParsedNameMap name_map = {0}; + rdi_parsed_from_name_map(rdi, &v[idx], &name_map); + dumpf("name_map[%S]:\n", rdi_string_from_name_map_kind(idx)); + for EachIndex(bucket_idx, name_map.bucket_count) + { + if(name_map.buckets[bucket_idx].node_count == 0) { continue; } + dumpf(" bucket[%I64u]:\n", bucket_idx); + RDI_NameMapNode *node_ptr = name_map.nodes + name_map.buckets[bucket_idx].first_node; + RDI_NameMapNode *node_opl = node_ptr + name_map.buckets[bucket_idx].node_count; + for(;node_ptr < node_opl; node_ptr += 1) + { + Temp temp = temp_begin(scratch.arena); + String8 str = str8_from_rdi_string_idx(rdi, node_ptr->string_idx); + String8 indices = {0}; + if(node_ptr->match_count == 1) + { + indices = push_str8f(temp.arena, "%u", node_ptr->match_idx_or_idx_run_first); + } + else + { + U32 idx_count = 0; + U32 *idx_array = rdi_idx_run_from_first_count(rdi, node_ptr->match_idx_or_idx_run_first, node_ptr->match_count, &idx_count); + String8List idx_strings = {0}; + for(U32 idx_i = 0; idx_i < idx_count; idx_i += 1) + { + U32 idx = idx_array[idx_i]; + str8_list_pushf(temp.arena, &idx_strings, "%u"); + } + indices = str8_list_join(scratch.arena, &idx_strings, &(StringJoin){.sep = str8_lit(", ")}); + } + dumpf(" match \"%S\": %S\n", str, indices); + temp_end(temp); + } + } + } + scratch_end(scratch); + } + + ////////////////////////////// + //- rjf: dump strings + // + DumpSubset(Strings) + { + U64 count = 0; + U32 *v = rdi_table_from_name(rdi, StringTable, &count); + for EachIndex(idx, count) + { + dumpf("string[%I64u]: \"%S\"\n", idx, str8_from_rdi_string_idx(rdi, idx)); + } + } + +#undef DumpSubset +#undef dumpf +#undef dump + return strings; +} diff --git a/src/rdi_format/rdi_format_local.h b/src/rdi_format/rdi_format_local.h index 5adc29c6..0dea0f1c 100644 --- a/src/rdi_format/rdi_format_local.h +++ b/src/rdi_format/rdi_format_local.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RDI_FORMAT_LOCAL_H @@ -7,6 +7,96 @@ #include "lib_rdi_format/rdi_format.h" #include "lib_rdi_format/rdi_format_parse.h" +//////////////////////////////// +//~ rjf: RDI Dumping Flags + +#define RDI_DumpSubset_XList \ +X(DataSections, data_sections, "DATA SECTIONS")\ +X(TopLevelInfo, top_level_info, "TOP LEVEL INFO")\ +X(BinarySections, binary_sections, "BINARY SECTIONS")\ +X(FilePaths, file_paths, "FILE PATHS")\ +X(SourceFiles, source_files, "SOURCE FILES")\ +X(LineTables, line_tables, "LINE TABLES")\ +X(SourceLineMaps, source_line_maps, "SOURCE LINE MAPS")\ +X(Units, units, "UNITS")\ +X(UnitVMap, unit_vmap, "UNIT VMAP")\ +X(TypeNodes, type_nodes, "TYPE NODES")\ +X(UserDefinedTypes, user_defined_types, "USER DEFINED TYPES")\ +X(GlobalVariables, global_variables, "GLOBAL VARIABLES")\ +X(GlobalVariablesVMap, global_variables_vmap, "GLOBAL VARIABLE VMAP")\ +X(ThreadVariables, thread_variables, "THREAD VARIABLES")\ +X(Constants, constants, "CONSTANTS")\ +X(Procedures, procedures, "PROCEDURES")\ +X(Scopes, scopes, "SCOPES")\ +X(ScopeVMap, scope_vmap, "SCOPE VMAP")\ +X(InlineSites, inline_sites, "INLINE SITES")\ +X(NameMaps, name_maps, "NAME MAPS")\ +X(Strings, strings, "STRINGS")\ + +typedef enum RDI_DumpSubset +{ +#define X(name, name_lower, title) RDI_DumpSubset_##name, + RDI_DumpSubset_XList +#undef X +} +RDI_DumpSubset; + +typedef U32 RDI_DumpSubsetFlags; +enum +{ +#define X(name, name_lower, title) RDI_DumpSubsetFlag_##name = (1< Enum + +internal String8 rdi_string_from_data_section_kind(Arena *arena, RDI_SectionKind v); +internal String8 rdi_string_from_arch (Arena *arena, RDI_Arch v); +internal String8 rdi_string_from_language (Arena *arena, RDI_Language v); +internal String8 rdi_string_from_local_kind (Arena *arena, RDI_LocalKind v); +#if 0 // TODO(rjf): conflicts with RDI... +internal String8 rdi_string_from_type_kind (Arena *arena, RDI_TypeKind v); +#endif +internal String8 rdi_string_from_member_kind (Arena *arena, RDI_MemberKind v); +internal String8 rdi_string_from_name_map_kind(RDI_NameMapKind kind); + +internal String8 rdi_string_from_binary_section_flags(Arena *arena, RDI_BinarySectionFlags flags); +internal String8 rdi_string_from_type_modifier (Arena *arena, RDI_TypeModifierFlags flags); +internal String8 rdi_string_from_udt_flags (Arena *arena, RDI_UDTFlags flags); +internal String8 rdi_string_from_link_flags (Arena *arena, RDI_LinkFlags flags); +internal String8 rdi_string_from_bytecode(Arena *arena, RDI_Arch arch, String8 bc); +internal String8List rdi_strings_from_locations(Arena *arena, RDI_Parsed *rdi, RDI_Arch arch, Rng1U64 location_block_range); + +//////////////////////////////// +//~ rjf: RDI Dumping + +internal String8List rdi_dump_list_from_parsed(Arena *arena, RDI_Parsed *rdi, RDI_DumpSubsetFlags flags); + #endif // RDI_FORMAT_LOCAL_H diff --git a/src/rdi_from_coff/rdi_from_coff.c b/src/rdi_from_coff/rdi_from_coff.c new file mode 100644 index 00000000..d10d1b25 --- /dev/null +++ b/src/rdi_from_coff/rdi_from_coff.c @@ -0,0 +1,79 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +internal RDI_Arch +c2r_rdi_arch_from_coff_machine(COFF_MachineType machine) +{ + switch (machine) { + case COFF_MachineType_X86: return RDI_Arch_X86; + case COFF_MachineType_X64: return RDI_Arch_X64; + + case COFF_MachineType_Unknown: + case COFF_MachineType_Am33: + case COFF_MachineType_Arm: + case COFF_MachineType_Arm64: + case COFF_MachineType_ArmNt: + case COFF_MachineType_Ebc: + case COFF_MachineType_Ia64: + case COFF_MachineType_M32R: + case COFF_MachineType_Mips16: + case COFF_MachineType_MipsFpu: + case COFF_MachineType_MipsFpu16: + case COFF_MachineType_PowerPc: + case COFF_MachineType_PowerPcFp: + case COFF_MachineType_R4000: + case COFF_MachineType_RiscV32: + case COFF_MachineType_RiscV64: + case COFF_MachineType_Sh3: + case COFF_MachineType_Sh3Dsp: + case COFF_MachineType_Sh4: + case COFF_MachineType_Sh5: + case COFF_MachineType_Thumb: + case COFF_MachineType_WceMipsV2: + NotImplemented; + default: + return RDI_Arch_NULL; + } +} + +internal RDI_BinarySectionFlags +c2r_rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags) +{ + RDI_BinarySectionFlags result = 0; + if(flags & COFF_SectionFlag_MemRead) + { + result |= RDI_BinarySectionFlag_Read; + } + if(flags & COFF_SectionFlag_MemWrite) + { + result |= RDI_BinarySectionFlag_Write; + } + if(flags & COFF_SectionFlag_MemExecute) + { + result |= RDI_BinarySectionFlag_Execute; + } + return(result); +} + +internal RDIM_BinarySectionList +c2r_rdi_binary_sections_from_coff_sections(Arena *arena, String8 image_data, String8 string_table, U64 sectab_count, COFF_SectionHeader *sectab) +{ + ProfBeginFunction(); + + RDIM_BinarySectionList binary_sections = {0}; + + for (U64 isec = 0; isec < sectab_count; ++isec) { + COFF_SectionHeader *coff_sec = §ab[isec]; + RDIM_BinarySection *sec = rdim_binary_section_list_push(arena, &binary_sections); + + sec->name = coff_name_from_section_header(string_table, coff_sec); + sec->flags = c2r_rdi_binary_section_flags_from_coff_section_flags(coff_sec->flags); + sec->voff_first = coff_sec->voff; + sec->voff_opl = coff_sec->voff + coff_sec->vsize; + sec->foff_first = coff_sec->foff; + sec->foff_opl = coff_sec->foff + coff_sec->fsize; + } + + ProfEnd(); + return binary_sections; +} diff --git a/src/rdi_from_coff/rdi_from_coff.h b/src/rdi_from_coff/rdi_from_coff.h new file mode 100644 index 00000000..521fe8db --- /dev/null +++ b/src/rdi_from_coff/rdi_from_coff.h @@ -0,0 +1,11 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef RDI_FROM_COFF_H +#define RDI_FROM_COFF_H + +internal RDI_Arch c2r_rdi_arch_from_coff_machine(COFF_MachineType machine); +internal RDI_BinarySectionFlags c2r_rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags); +internal RDIM_BinarySectionList c2r_rdi_binary_sections_from_coff_sections(Arena *arena, String8 image_data, String8 string_table, U64 sectab_count, COFF_SectionHeader *sectab); + +#endif // RDI_FROM_COFF_H diff --git a/src/rdi_from_dwarf/rdi_from_dwarf.c b/src/rdi_from_dwarf/rdi_from_dwarf.c index 8d600762..f89a7560 100644 --- a/src/rdi_from_dwarf/rdi_from_dwarf.c +++ b/src/rdi_from_dwarf/rdi_from_dwarf.c @@ -1,72 +1,11 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -internal D2R_User2Convert * -d2r_user2convert_from_cmdln(Arena *arena, CmdLine *cmdline) -{ - D2R_User2Convert *result = push_array(arena, D2R_User2Convert, 1); - - String8 exe_name = cmd_line_string(cmdline, str8_lit("exe")); - String8 debug_name = cmd_line_string(cmdline, str8_lit("debug")); - String8 out_name = cmd_line_string(cmdline, str8_lit("out")); - - // error check params - if (exe_name.size == 0 && debug_name.size == 0) { - str8_list_pushf(arena, &result->errors, "Missing one of the required parameters: '--exe:' or '--debug:'"); - } - if (out_name.size == 0) { - str8_list_pushf(arena, &result->errors, "Missing required parameter: '--out:'"); - } - - // get input EXE or ELF - if (exe_name.size > 0) { - String8 exe_data = os_data_from_file_path(arena, exe_name); - if (exe_data.size == 0) { - str8_list_pushf(arena, &result->errors, "Could not load input EXE file from '%S'", exe_name); - } else { - result->input_exe_name = exe_name; - result->input_exe_data = exe_data; - } - } - - // get input DEBUG - if (debug_name.size > 0) { - String8 debug_data = os_data_from_file_path(arena, debug_name); - if (debug_data.size == 0) { - str8_list_pushf(arena, &result->errors, "Could not load input DEBUG file from '%S'", debug_name); - } else { - result->input_debug_name = debug_name; - result->input_debug_data = debug_data; - } - } - - result->output_name = out_name; - result->flags = ~0ull; - - String8List only_names = cmd_line_strings(cmdline, str8_lit("only")); - String8List omit_names = cmd_line_strings(cmdline, str8_lit("omit")); - - if (only_names.node_count > 0) { - result->flags = 0; - for (String8Node *i = only_names.first; i != 0; i = i->next) { -#define X(t,n,k) if (str8_match_lit(Stringify(n), i->string, StringMatchFlag_CaseInsensitive)) \ - result->flags |= D2R_ConvertFlag_##t; - RDI_SectionKind_XList -#undef X - } - } - - if (omit_names.node_count > 0) { - for (String8Node *i = omit_names.first; i != 0; i = i->next) { -#define X(t,n,k) if (str8_match_lit(Stringify(n), i->string, StringMatchFlag_CaseInsensitive)) \ - result->flags &= ~D2R_ConvertFlag_##t; - RDI_SectionKind_XList -#undef X - } - } - - return result; -} +// TODO: +// +// [ ] Currently converter relies on clang's -gdwarf-aranges to generate compile unit ranges, +// however it is optional and in case it is missing converter has to generate the ranges from scopes. +// [ ] Error handling internal RDI_RegCode d2r_rdi_reg_from_dw_reg_code_x64(U64 reg_code) @@ -93,14 +32,14 @@ d2r_rdi_reg_from_dw_reg_code_x86(U64 reg_code) } internal RDI_RegCode -d2r_rdi_reg_from_dw_reg_code(RDI_Arch arch, U64 reg_code) +d2r_rdi_reg_from_dw_reg_code(Arch arch, U64 reg_code) { switch (arch) { - case RDI_Arch_NULL: return 0; - case RDI_Arch_X64: return d2r_rdi_reg_from_dw_reg_code_x64(reg_code); - case RDI_Arch_X86: return d2r_rdi_reg_from_dw_reg_code_x86(reg_code); + case Arch_Null: return 0; + case Arch_x64: return d2r_rdi_reg_from_dw_reg_code_x64(reg_code); + case Arch_x86: return d2r_rdi_reg_from_dw_reg_code_x86(reg_code); + default: InvalidPath; } - InvalidPath; return 0; } @@ -129,30 +68,30 @@ internal RDIM_Type * d2r_type_from_attrib(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind) { RDIM_Type *type = 0; - + // find attrib DW_Attrib *attrib = dw_attrib_from_tag(input, cu, tag, kind); - + // does tag have this attribute? if (attrib->attrib_kind == kind) { DW_AttribClass value_class = dw_value_class_from_attrib(cu, attrib); - + if (value_class == DW_AttribClass_Reference) { // resolve reference DW_Reference ref = dw_ref_from_attrib_ptr(input, cu, attrib); - + // TODO: support for external compile unit references AssertAlways(ref.cu == cu); - + // find or create type type = d2r_find_or_create_type_from_offset(arena, type_table, ref.info_off); } else { Assert(!"unexpected attrib class"); } } else if (attrib->attrib_kind == DW_Attrib_Null) { - type = type_table->void_type; + type = rdim_builtin_type_from_kind(*type_table->types, RDI_TypeKind_NULL); } - + return type; } @@ -161,13 +100,22 @@ d2r_range_list_from_tag(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 imag { // collect non-contiguous range Rng1U64List ranges = dw_rnglist_from_attrib(arena, input, cu, tag, DW_Attrib_Ranges); - + + // debase ranges + for (Rng1U64Node *range_n = ranges.first; range_n != 0; range_n = range_n->next) { + // TODO: error handling + AssertAlways(range_n->v.min >= image_base); + AssertAlways(range_n->v.max >= image_base); + range_n->v.min -= image_base; + range_n->v.max -= image_base; + } + // collect contiguous range DW_Attrib *lo_pc_attrib = dw_attrib_from_tag(input, cu, tag, DW_Attrib_LowPc); DW_Attrib *hi_pc_attrib = dw_attrib_from_tag(input, cu, tag, DW_Attrib_HighPc); if (lo_pc_attrib->attrib_kind != DW_Attrib_Null && hi_pc_attrib->attrib_kind != DW_Attrib_Null) { U64 lo_pc = dw_address_from_attrib_ptr(input, cu, lo_pc_attrib); - + U64 hi_pc; DW_AttribClass hi_pc_class = dw_value_class_from_attrib(cu, hi_pc_attrib); if (hi_pc_class == DW_AttribClass_Address) { @@ -178,17 +126,17 @@ d2r_range_list_from_tag(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 imag } else { AssertAlways(!"undefined attrib encoding"); } - + // TODO: error handling AssertAlways(lo_pc >= image_base); AssertAlways(hi_pc >= image_base); AssertAlways(lo_pc <= hi_pc); - + U64 lo_voff = lo_pc - image_base; U64 hi_voff = hi_pc - image_base; rng1u64_list_push(arena, &ranges, rng_1u64(lo_voff, hi_voff)); } - + return ranges; } @@ -196,7 +144,7 @@ internal RDIM_Type ** d2r_collect_proc_params(Arena *arena, D2R_TypeTable *type_table, DW_Input *input, DW_CompUnit *cu, DW_TagNode *cur_node, U64 *param_count_out) { Temp scratch = scratch_begin(&arena, 1); - + RDIM_TypeList list = {0}; B32 has_vargs = 0; for (DW_TagNode *i = cur_node->first_child; i != 0; i = i->sibling) { @@ -209,445 +157,690 @@ d2r_collect_proc_params(Arena *arena, D2R_TypeTable *type_table, DW_Input *input has_vargs = 1; } } - + if (has_vargs) { RDIM_TypeNode *n = push_array(scratch.arena, RDIM_TypeNode, 1); n->v = type_table->varg_type; SLLQueuePush(list.first, list.last, n); ++list.count; } - + // collect params *param_count_out = list.count; RDIM_Type **params = rdim_array_from_type_list(arena, list); - + scratch_end(scratch); return params; } +internal RDI_TypeKind +d2r_unsigned_type_kind_from_size(U64 byte_size) +{ + RDI_TypeKind result = RDI_TypeKind_NULL; + switch (byte_size) { + case 1: result = RDI_TypeKind_U8; break; + case 2: result = RDI_TypeKind_U16; break; + case 4: result = RDI_TypeKind_U32; break; + case 8: result = RDI_TypeKind_U64; break; + } + return result; +} + +internal RDI_TypeKind +d2r_signed_type_kind_from_size(U64 byte_size) +{ + RDI_TypeKind result = RDI_TypeKind_NULL; + switch (byte_size) { + case 1: result = RDI_TypeKind_S8; break; + case 2: result = RDI_TypeKind_S16; break; + case 4: result = RDI_TypeKind_S32; break; + case 8: result = RDI_TypeKind_S64; break; + } + return result; +} + +internal RDI_EvalTypeGroup +d2r_type_group_from_type_kind(RDI_TypeKind x) +{ + switch (x) { + case RDI_TypeKind_NULL: + case RDI_TypeKind_Void: + case RDI_TypeKind_Handle: + break; + case RDI_TypeKind_UChar8: + case RDI_TypeKind_UChar16: + case RDI_TypeKind_UChar32: + case RDI_TypeKind_U8: + case RDI_TypeKind_U16: + case RDI_TypeKind_U32: + case RDI_TypeKind_U64: + case RDI_TypeKind_U128: + case RDI_TypeKind_U256: + case RDI_TypeKind_U512: + return RDI_EvalTypeGroup_U; + case RDI_TypeKind_Char8: + case RDI_TypeKind_Char16: + case RDI_TypeKind_Char32: + case RDI_TypeKind_S8: + case RDI_TypeKind_S16: + case RDI_TypeKind_S32: + case RDI_TypeKind_S64: + case RDI_TypeKind_S128: + case RDI_TypeKind_S256: + case RDI_TypeKind_S512: + return RDI_EvalTypeGroup_S; + case RDI_TypeKind_F32: + return RDI_EvalTypeGroup_F32; + case RDI_TypeKind_F64: + return RDI_EvalTypeGroup_F64; + default: InvalidPath; + } + return RDI_EvalTypeGroup_Other; +} internal RDIM_EvalBytecode -d2r_bytecode_from_expression(Arena *arena, U64 image_base, U64 address_size, RDI_Arch arch, DW_ListUnit *addr_lu, String8 expr) +d2r_bytecode_from_expression(Arena *arena, + DW_Input *input, + U64 image_base, + U64 address_size, + Arch arch, + DW_ListUnit *addr_lu, + String8 expr, + DW_CompUnit *cu, + B32 *is_addr_out) { + Temp scratch = scratch_begin(&arena, 1); + RDIM_EvalBytecode bc = {0}; - + + *is_addr_out = 0; + + struct Frame { + struct Frame *next; + RDI_EvalTypeGroup value_type; + }; + struct Frame *stack = 0; +#define push_of_type(type) do { \ +struct Frame *f = push_array(scratch.arena, struct Frame, 1); \ +f->value_type = d2r_type_group_from_type_kind(type); \ +SLLStackPush(stack, f); \ +} while (0) +#define pop_type() stack->value_type; SLLStackPop(stack) +#define peek_type() stack->value_type + + + RDI_TypeKind addr_type_kind = RDI_TypeKind_NULL; + if (address_size == 4) { + addr_type_kind = RDI_TypeKind_U32; + } else if (address_size == 8) { + addr_type_kind = RDI_TypeKind_U64; + } + + for (U64 cursor = 0; cursor < expr.size; ) { U8 op = 0; cursor += str8_deserial_read_struct(expr, cursor, &op); - + U64 size_param; switch (op) { - case DW_ExprOp_Lit0: case DW_ExprOp_Lit1: case DW_ExprOp_Lit2: - case DW_ExprOp_Lit3: case DW_ExprOp_Lit4: case DW_ExprOp_Lit5: - case DW_ExprOp_Lit6: case DW_ExprOp_Lit7: case DW_ExprOp_Lit8: - case DW_ExprOp_Lit9: case DW_ExprOp_Lit10: case DW_ExprOp_Lit11: - case DW_ExprOp_Lit12: case DW_ExprOp_Lit13: case DW_ExprOp_Lit14: - case DW_ExprOp_Lit15: case DW_ExprOp_Lit16: case DW_ExprOp_Lit17: - case DW_ExprOp_Lit18: case DW_ExprOp_Lit19: case DW_ExprOp_Lit20: - case DW_ExprOp_Lit21: case DW_ExprOp_Lit22: case DW_ExprOp_Lit23: - case DW_ExprOp_Lit24: case DW_ExprOp_Lit25: case DW_ExprOp_Lit26: - case DW_ExprOp_Lit27: case DW_ExprOp_Lit28: case DW_ExprOp_Lit29: - case DW_ExprOp_Lit30: case DW_ExprOp_Lit31: { - U64 lit = op - DW_ExprOp_Lit0; - rdim_bytecode_push_uconst(arena, &bc, lit); - } break; - - case DW_ExprOp_Const1U: size_param = 1; goto const_unsigned; - case DW_ExprOp_Const2U: size_param = 2; goto const_unsigned; - case DW_ExprOp_Const4U: size_param = 4; goto const_unsigned; - case DW_ExprOp_Const8U: size_param = 8; goto const_unsigned; - const_unsigned: { - U64 val = 0; - cursor += str8_deserial_read(expr, cursor, &val, size_param, size_param); - rdim_bytecode_push_uconst(arena, &bc, val); - } break; - - case DW_ExprOp_Const1S:size_param = 1; goto const_signed; - case DW_ExprOp_Const2S:size_param = 2; goto const_signed; - case DW_ExprOp_Const4S:size_param = 4; goto const_signed; - case DW_ExprOp_Const8S:size_param = 8; goto const_signed; - const_signed: { - S64 val = 0; - cursor += str8_deserial_read(expr, cursor, &val, size_param, size_param); - val = extend_sign64(val, size_param); - rdim_bytecode_push_sconst(arena, &bc, val); - } break; - - case DW_ExprOp_ConstU: { - U64 val = 0; - cursor += str8_deserial_read_uleb128(expr, cursor, &val); - rdim_bytecode_push_uconst(arena, &bc, val); - } break; - - case DW_ExprOp_ConstS: { - S64 val = 0; - cursor += str8_deserial_read_sleb128(expr, cursor, &val); - rdim_bytecode_push_sconst(arena, &bc, val); - } break; - - case DW_ExprOp_Addr: { - U64 addr = 0; - cursor += str8_deserial_read(expr, cursor, &addr, address_size, address_size); - if (addr >= image_base) { - U64 voff = addr - image_base; - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_ModuleOff, voff); - } else { - // TODO: error handling - AssertAlways(!"unable to relocate address"); - } - } break; - - case DW_ExprOp_Reg0: case DW_ExprOp_Reg1: case DW_ExprOp_Reg2: - case DW_ExprOp_Reg3: case DW_ExprOp_Reg4: case DW_ExprOp_Reg5: - case DW_ExprOp_Reg6: case DW_ExprOp_Reg7: case DW_ExprOp_Reg8: - case DW_ExprOp_Reg9: case DW_ExprOp_Reg10: case DW_ExprOp_Reg11: - case DW_ExprOp_Reg12: case DW_ExprOp_Reg13: case DW_ExprOp_Reg14: - case DW_ExprOp_Reg15: case DW_ExprOp_Reg16: case DW_ExprOp_Reg17: - case DW_ExprOp_Reg18: case DW_ExprOp_Reg19: case DW_ExprOp_Reg20: - case DW_ExprOp_Reg21: case DW_ExprOp_Reg22: case DW_ExprOp_Reg23: - case DW_ExprOp_Reg24: case DW_ExprOp_Reg25: case DW_ExprOp_Reg26: - case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29: - case DW_ExprOp_Reg30: case DW_ExprOp_Reg31: { - U64 reg_code_dw = op - DW_ExprOp_Reg0; - RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); - U32 regread_param = RDI_EncodeRegReadParam(reg_code_rdi, 8, 0); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegRead, regread_param); - } break; - - case DW_ExprOp_RegX: { - U64 reg_code_dw = 0; - cursor += str8_deserial_read_uleb128(expr, cursor, ®_code_dw); - RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); - U32 regread_param = RDI_EncodeRegReadParam(reg_code_rdi, 8, 0); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegRead, regread_param); - } break; - - case DW_ExprOp_ImplicitValue: { - U64 value_size = 0; - cursor += str8_deserial_read_uleb128(expr, cursor, &value_size); - - String8 val = str8_substr(expr, rng_1u64(cursor, cursor + value_size)); - if (val.size <= sizeof(U64)) { - U64 val64 = 0; - MemoryCopy(&val64, val.str, val.size); - rdim_bytecode_push_uconst(arena, &bc, val64); - } else { - // TODO: currenlty no way to encode string in RDIM_EvalBytecodeOp - NotImplemented; - } - } break; - - case DW_ExprOp_Piece: { - NotImplemented; - } break; - - case DW_ExprOp_BitPiece: { - NotImplemented; - } break; - - case DW_ExprOp_Pick: { - U8 stack_idx = 0; - cursor += str8_deserial_read_struct(expr, cursor, &stack_idx); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Pick, stack_idx); - } break; - - case DW_ExprOp_PlusUConst: { - U64 addend = 0; - cursor += str8_deserial_read_uleb128(expr, cursor, &addend); - rdim_bytecode_push_uconst(arena, &bc, addend); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, 0); - } break; - - case DW_ExprOp_Skip: { - S16 skip = 0; - cursor += str8_deserial_read_struct(expr, cursor, &skip); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Skip, skip); - } break; - - case DW_ExprOp_Bra: { - NotImplemented; - } break; - - case DW_ExprOp_BReg0: case DW_ExprOp_BReg1: case DW_ExprOp_BReg2: - case DW_ExprOp_BReg3: case DW_ExprOp_BReg4: case DW_ExprOp_BReg5: - case DW_ExprOp_BReg6: case DW_ExprOp_BReg7: case DW_ExprOp_BReg8: - case DW_ExprOp_BReg9: case DW_ExprOp_BReg10: case DW_ExprOp_BReg11: - case DW_ExprOp_BReg12: case DW_ExprOp_BReg13: case DW_ExprOp_BReg14: - case DW_ExprOp_BReg15: case DW_ExprOp_BReg16: case DW_ExprOp_BReg17: - case DW_ExprOp_BReg18: case DW_ExprOp_BReg19: case DW_ExprOp_BReg20: - case DW_ExprOp_BReg21: case DW_ExprOp_BReg22: case DW_ExprOp_BReg23: - case DW_ExprOp_BReg24: case DW_ExprOp_BReg25: case DW_ExprOp_BReg26: - case DW_ExprOp_BReg27: case DW_ExprOp_BReg28: case DW_ExprOp_BReg29: - case DW_ExprOp_BReg30: case DW_ExprOp_BReg31: { - U64 reg_code_dw = op - DW_ExprOp_BReg0; - S64 reg_off = 0; - cursor += str8_deserial_read_sleb128(expr, cursor, ®_off); + case DW_ExprOp_Lit0: case DW_ExprOp_Lit1: case DW_ExprOp_Lit2: + case DW_ExprOp_Lit3: case DW_ExprOp_Lit4: case DW_ExprOp_Lit5: + case DW_ExprOp_Lit6: case DW_ExprOp_Lit7: case DW_ExprOp_Lit8: + case DW_ExprOp_Lit9: case DW_ExprOp_Lit10: case DW_ExprOp_Lit11: + case DW_ExprOp_Lit12: case DW_ExprOp_Lit13: case DW_ExprOp_Lit14: + case DW_ExprOp_Lit15: case DW_ExprOp_Lit16: case DW_ExprOp_Lit17: + case DW_ExprOp_Lit18: case DW_ExprOp_Lit19: case DW_ExprOp_Lit20: + case DW_ExprOp_Lit21: case DW_ExprOp_Lit22: case DW_ExprOp_Lit23: + case DW_ExprOp_Lit24: case DW_ExprOp_Lit25: case DW_ExprOp_Lit26: + case DW_ExprOp_Lit27: case DW_ExprOp_Lit28: case DW_ExprOp_Lit29: + case DW_ExprOp_Lit30: case DW_ExprOp_Lit31: { + U64 lit = op - DW_ExprOp_Lit0; + + rdim_bytecode_push_uconst(arena, &bc, lit); + push_of_type(RDI_TypeKind_U64); + } break; - RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegReadDyn, reg_code_rdi); - rdim_bytecode_push_sconst(arena, &bc, reg_off); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, 0); - } break; - - case DW_ExprOp_BRegX: { - U64 reg_code_dw = 0; - S64 reg_off = 0; - cursor += str8_deserial_read_uleb128(expr, cursor, ®_code_dw); - cursor += str8_deserial_read_sleb128(expr, cursor, ®_off); - - RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegReadDyn, reg_code_rdi); - rdim_bytecode_push_sconst(arena, &bc, reg_off); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, 0); - } break; - - case DW_ExprOp_FBReg: { - S64 frame_off = 0; - cursor += str8_deserial_read_sleb128(expr, cursor, &frame_off); - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_FrameOff, frame_off); - } break; - - case DW_ExprOp_Deref: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_MemRead, address_size); - } break; - - case DW_ExprOp_DerefSize: { - U8 deref_size_in_bytes = 0; - cursor += str8_deserial_read_struct(expr, cursor, &deref_size_in_bytes); - if (0 < deref_size_in_bytes && deref_size_in_bytes <= address_size) { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_MemRead, deref_size_in_bytes); - } else { - // TODO: error handling - AssertAlways(!"ill formed expression"); - } - } break; - - case DW_ExprOp_XDerefSize: { - // TODO: error handling - AssertAlways(!"no suitable conversion"); - } break; - - case DW_ExprOp_Call2: - case DW_ExprOp_Call4: - case DW_ExprOp_CallRef: { - // TODO: error handling - AssertAlways(!"calls are not supported"); - } break; - - case DW_ExprOp_ImplicitPointer: - case DW_ExprOp_GNU_ImplicitPointer: { - // TODO: - AssertAlways(!"sample"); - } break; - - case DW_ExprOp_Convert: - case DW_ExprOp_GNU_Convert: { - // TODO: - AssertAlways(!"sample"); - } break; - - case DW_ExprOp_GNU_ParameterRef: { - // TODO: - AssertAlways(!"sample"); - } break; - - case DW_ExprOp_DerefType: - case DW_ExprOp_GNU_DerefType: { - // TODO: - AssertAlways(!"sample"); - } break; - - case DW_ExprOp_ConstType: - case DW_ExprOp_GNU_ConstType: { - // TODO: - AssertAlways(!"sample"); - } break; - - case DW_ExprOp_RegvalType: { - // TODO: - AssertAlways(!"sample"); - } break; - - case DW_ExprOp_EntryValue: - case DW_ExprOp_GNU_EntryValue: { - // TODO: - AssertAlways(!"sample"); - } break; - - case DW_ExprOp_Addrx: { - U64 addr_idx = 0; - cursor += str8_deserial_read_uleb128(expr, cursor, &addr_idx); - U64 addr = dw_addr_from_list_unit(addr_lu, addr_idx); - if (addr != max_U64) { + case DW_ExprOp_Const1U: { + U8 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_uconst(arena, &bc, val); + push_of_type(RDI_TypeKind_U8); + } break; + case DW_ExprOp_Const2U: { + U16 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_uconst(arena, &bc, val); + push_of_type(RDI_TypeKind_U16); + } break; + case DW_ExprOp_Const4U: { + U32 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_uconst(arena, &bc, val); + push_of_type(RDI_TypeKind_U32); + } break; + case DW_ExprOp_Const8U: { + U64 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_uconst(arena, &bc, val); + push_of_type(RDI_TypeKind_U64); + } break; + + case DW_ExprOp_Const1S: { + S8 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_sconst(arena, &bc, val); + push_of_type(RDI_TypeKind_S8); + } break; + case DW_ExprOp_Const2S: { + S16 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_sconst(arena, &bc, val); + push_of_type(RDI_TypeKind_S16); + } break; + case DW_ExprOp_Const4S: { + S32 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_sconst(arena, &bc, val); + push_of_type(RDI_TypeKind_S32); + } break; + case DW_ExprOp_Const8S: { + S64 val = 0; + cursor += str8_deserial_read_struct(expr, cursor, &val); + + rdim_bytecode_push_sconst(arena, &bc, val); + push_of_type(RDI_TypeKind_S64); + } break; + + case DW_ExprOp_ConstU: { + U64 val = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, &val); + + rdim_bytecode_push_uconst(arena, &bc, val); + push_of_type(RDI_TypeKind_U64); + } break; + + case DW_ExprOp_ConstS: { + S64 val = 0; + cursor += str8_deserial_read_sleb128(expr, cursor, &val); + + rdim_bytecode_push_sconst(arena, &bc, val); + push_of_type(RDI_TypeKind_S64); + } break; + + case DW_ExprOp_Addr: { + U64 addr = 0; + cursor += str8_deserial_read(expr, cursor, &addr, address_size, address_size); if (addr >= image_base) { U64 voff = addr - image_base; rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_ModuleOff, voff); + push_of_type(addr_type_kind); } else { // TODO: error handling AssertAlways(!"unable to relocate address"); } - } else { + + *is_addr_out = 1; + } break; + + case DW_ExprOp_Reg0: case DW_ExprOp_Reg1: case DW_ExprOp_Reg2: + case DW_ExprOp_Reg3: case DW_ExprOp_Reg4: case DW_ExprOp_Reg5: + case DW_ExprOp_Reg6: case DW_ExprOp_Reg7: case DW_ExprOp_Reg8: + case DW_ExprOp_Reg9: case DW_ExprOp_Reg10: case DW_ExprOp_Reg11: + case DW_ExprOp_Reg12: case DW_ExprOp_Reg13: case DW_ExprOp_Reg14: + case DW_ExprOp_Reg15: case DW_ExprOp_Reg16: case DW_ExprOp_Reg17: + case DW_ExprOp_Reg18: case DW_ExprOp_Reg19: case DW_ExprOp_Reg20: + case DW_ExprOp_Reg21: case DW_ExprOp_Reg22: case DW_ExprOp_Reg23: + case DW_ExprOp_Reg24: case DW_ExprOp_Reg25: case DW_ExprOp_Reg26: + case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29: + case DW_ExprOp_Reg30: case DW_ExprOp_Reg31: { + U64 reg_code_dw = op - DW_ExprOp_Reg0; + U64 reg_size = dw_reg_size_from_code(arch, reg_code_dw); + U64 reg_pos = dw_reg_pos_from_code(arch, reg_code_dw); + + RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); + U32 regread_param = RDI_EncodeRegReadParam(reg_code_rdi, reg_size, reg_pos); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegRead, regread_param); + push_of_type(d2r_unsigned_type_kind_from_size(reg_size)); + } break; + + case DW_ExprOp_RegX: { + U64 reg_code_dw = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, ®_code_dw); + + U64 reg_size = dw_reg_size_from_code(arch, reg_code_dw); + U64 reg_pos = dw_reg_pos_from_code(arch, reg_code_dw); + + RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); + U32 regread_param = RDI_EncodeRegReadParam(reg_code_rdi, reg_size, reg_pos); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegRead, regread_param); + push_of_type(d2r_unsigned_type_kind_from_size(reg_size)); + + *is_addr_out = 1; + } break; + + case DW_ExprOp_ImplicitValue: { + U64 val_size = 0; + String8 val = {0}; + cursor += str8_deserial_read_uleb128(expr, cursor, &val_size); + cursor += str8_deserial_read_block(expr, cursor, val_size, &val); + if (val.size <= sizeof(U64)) { + U64 val64 = 0; + MemoryCopy(&val64, val.str, val.size); + + rdim_bytecode_push_uconst(arena, &bc, val64); + push_of_type(d2r_unsigned_type_kind_from_size(val_size)); + } else { + // TODO: currenlty no way to encode string in RDIM_EvalBytecodeOp + NotImplemented; + } + } break; + + case DW_ExprOp_Piece: { + U64 piece_byte_size = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, &piece_byte_size); + + U64 partial_value_size32 = safe_cast_u32(piece_byte_size); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_PartialValue, partial_value_size32); + } break; + + case DW_ExprOp_BitPiece: { + U64 piece_bit_size = 0; + U64 piece_bit_off = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, &piece_bit_size); + cursor += str8_deserial_read_uleb128(expr, cursor, &piece_bit_off); + + U32 piece_bit_size32 = safe_cast_u32(piece_bit_size); + U32 piece_bit_off32 = safe_cast_u32(piece_bit_off); + + U64 partial_value = ((U64)piece_bit_size32 << 32) | (U64)piece_bit_off32; + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_PartialValueBit, partial_value); + } break; + + case DW_ExprOp_Pick: { + U8 stack_idx = 0; + cursor += str8_deserial_read_struct(expr, cursor, &stack_idx); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Pick, stack_idx); + } break; + + case DW_ExprOp_PlusUConst: { + U64 addend = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, &addend); + rdim_bytecode_push_uconst(arena, &bc, addend); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, RDI_EvalTypeGroup_U); + } break; + + case DW_ExprOp_Skip: { + S16 skip = 0; + cursor += str8_deserial_read_struct(expr, cursor, &skip); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Skip, skip); + } break; + + case DW_ExprOp_Bra: { + NotImplemented; + } break; + + case DW_ExprOp_BReg0: case DW_ExprOp_BReg1: case DW_ExprOp_BReg2: + case DW_ExprOp_BReg3: case DW_ExprOp_BReg4: case DW_ExprOp_BReg5: + case DW_ExprOp_BReg6: case DW_ExprOp_BReg7: case DW_ExprOp_BReg8: + case DW_ExprOp_BReg9: case DW_ExprOp_BReg10: case DW_ExprOp_BReg11: + case DW_ExprOp_BReg12: case DW_ExprOp_BReg13: case DW_ExprOp_BReg14: + case DW_ExprOp_BReg15: case DW_ExprOp_BReg16: case DW_ExprOp_BReg17: + case DW_ExprOp_BReg18: case DW_ExprOp_BReg19: case DW_ExprOp_BReg20: + case DW_ExprOp_BReg21: case DW_ExprOp_BReg22: case DW_ExprOp_BReg23: + case DW_ExprOp_BReg24: case DW_ExprOp_BReg25: case DW_ExprOp_BReg26: + case DW_ExprOp_BReg27: case DW_ExprOp_BReg28: case DW_ExprOp_BReg29: + case DW_ExprOp_BReg30: case DW_ExprOp_BReg31: { + U64 reg_code_dw = op - DW_ExprOp_BReg0; + S64 reg_off = 0; + cursor += str8_deserial_read_sleb128(expr, cursor, ®_off); + + RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegReadDyn, reg_code_rdi); + if (reg_off > 0) { + rdim_bytecode_push_sconst(arena, &bc, reg_off); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, RDI_EvalTypeGroup_S); + } + push_of_type(RDI_TypeKind_S64); + + *is_addr_out = 1; + } break; + + case DW_ExprOp_BRegX: { + U64 reg_code_dw = 0; + S64 reg_off = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, ®_code_dw); + cursor += str8_deserial_read_sleb128(expr, cursor, ®_off); + + RDI_RegCode reg_code_rdi = d2r_rdi_reg_from_dw_reg_code(arch, reg_code_dw); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RegReadDyn, reg_code_rdi); + if (reg_off > 0) { + rdim_bytecode_push_sconst(arena, &bc, reg_off); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, RDI_EvalTypeGroup_S); + } + push_of_type(RDI_TypeKind_S64); + + *is_addr_out = 1; + } break; + + case DW_ExprOp_FBReg: { + S64 frame_off = 0; + cursor += str8_deserial_read_sleb128(expr, cursor, &frame_off); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_FrameOff, frame_off); + + *is_addr_out = 1; + } break; + + case DW_ExprOp_Deref: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_MemRead, address_size); + } break; + + case DW_ExprOp_DerefSize: { + U8 deref_size_in_bytes = 0; + cursor += str8_deserial_read_struct(expr, cursor, &deref_size_in_bytes); + if (0 < deref_size_in_bytes && deref_size_in_bytes <= address_size) { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_MemRead, deref_size_in_bytes); + } else { + // TODO: error handling + AssertAlways(!"ill formed expression"); + } + } break; + + case DW_ExprOp_XDerefSize: { // TODO: error handling - AssertAlways(!"out of bounds index"); - } - } break; - - case DW_ExprOp_CallFrameCfa: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_FrameOff, 0); - } break; - - case DW_ExprOp_FormTlsAddress: { - // TODO: - AssertAlways(!"RDI_EvalOp_TLSOff accepts immediate"); - } break; - - case DW_ExprOp_PushObjectAddress: { - AssertAlways(!"sample"); - } break; - - case DW_ExprOp_Nop: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Noop, 0); - } break; - - case DW_ExprOp_Eq: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_EqEq, 0); - } break; - - case DW_ExprOp_Ge: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_GrEq, 0); - } break; - - case DW_ExprOp_Gt: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Grtr, 0); - } break; - - case DW_ExprOp_Le: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_LsEq, 0); - } break; - - case DW_ExprOp_Lt: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Less, 0); - } break; - - case DW_ExprOp_Ne: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_NtEq, 0); - } break; - - case DW_ExprOp_Shl: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_LShift, 0); - } break; - - case DW_ExprOp_Shr: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RShift, 0); - } break; - - case DW_ExprOp_Shra: { - // TODO: - AssertAlways(!"sample"); - } break; - - case DW_ExprOp_Xor: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitXor, 0); - } break; - - case DW_ExprOp_XDeref: { - // TODO: error handling - Assert(!"multiple address spaces are not supported"); - } break; - - case DW_ExprOp_Abs: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Abs, 0); - } break; - - case DW_ExprOp_And: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitAnd, 0); - } break; - - case DW_ExprOp_Div: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Div, 0); - } break; - - case DW_ExprOp_Minus: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Sub, 0); - } break; - - case DW_ExprOp_Mod: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Mod, 0); - } break; - - case DW_ExprOp_Mul: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Mul, 0); - } break; - - case DW_ExprOp_Neg: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Neg, 0); - } break; - - case DW_ExprOp_Not: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitNot, 0); - } break; - - case DW_ExprOp_Or: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitOr, 0); - } break; - - case DW_ExprOp_Plus: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, 0); - } break; - - case DW_ExprOp_Rot: { - AssertAlways(!"no suitable conversion"); - } break; - - case DW_ExprOp_Swap: { - AssertAlways(!"no suitable conversion"); - } break; - - case DW_ExprOp_Dup: { - AssertAlways(!"no suitable conversion"); - } break; - - case DW_ExprOp_Drop: { - AssertAlways(!"no suitable conversion"); - } break; - - case DW_ExprOp_Over: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Pick, 1); - } break; - - case DW_ExprOp_StackValue: { - rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Stop, 0); - } break; - - default: InvalidPath; break; + AssertAlways(!"no suitable conversion"); + } break; + + case DW_ExprOp_Call2: + case DW_ExprOp_Call4: + case DW_ExprOp_CallRef: { + // TODO: error handling + AssertAlways(!"calls are not supported"); + } break; + + case DW_ExprOp_ImplicitPointer: + case DW_ExprOp_GNU_ImplicitPointer: { + // TODO: + AssertAlways(!"sample"); + } break; + + case DW_ExprOp_Convert: + case DW_ExprOp_GNU_Convert: { + U64 type_info_off = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, &type_info_off); + + RDI_EvalTypeGroup in = stack ? d2r_type_group_from_type_kind(stack->value_type) : RDI_EvalTypeGroup_Other; + RDI_EvalTypeGroup out = RDI_EvalTypeGroup_Other; + + if (type_info_off == 0) { + // + // 2.5.1 + // Instead of a base type, elements can have a generic type, + // which is an integral type that has the size of an address + // on the target machine and unspecified signedness. + // + out = d2r_type_group_from_type_kind(addr_type_kind); + } else { + // find ref tag + DW_TagNode *tag_node = dw_tag_node_from_info_off(cu, type_info_off); + DW_Tag tag = tag_node->tag; + if (tag.kind == DW_Tag_BaseType) { + // extract encoding attribute + DW_ATE encoding = dw_const_u64_from_attrib(input, cu, tag, DW_Attrib_Encoding); + + // DW_ATE -> RDI_EvalTypeGroup + switch (encoding) { + case DW_ATE_SignedChar: + case DW_ATE_Signed: out = RDI_EvalTypeGroup_S; break; + case DW_ATE_UnsignedChar: + case DW_ATE_Unsigned: out = RDI_EvalTypeGroup_U; break; + case DW_ATE_Float: { + U64 byte_size = dw_const_u64_from_attrib(input, cu, tag, DW_Attrib_ByteSize); + switch (byte_size) { + case 4: out = RDI_EvalTypeGroup_F32; break; + case 8: out = RDI_EvalTypeGroup_F64; break; + default: InvalidPath; + } + } break; + default: InvalidPath; + } + } else { + AssertAlways(!"unexpected tag"); // TODO: error handling + } + } + + if (in == RDI_EvalTypeGroup_Other) { + push_of_type(out); + break; + } + + // TODO: error handling + AssertAlways(in != RDI_EvalTypeGroup_Other); + AssertAlways(out != RDI_EvalTypeGroup_Other); + + U16 operand = (U16)in | ((U16)out << 8); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Convert, operand); + } break; + + case DW_ExprOp_GNU_ParameterRef: { + // TODO: + AssertAlways(!"sample"); + } break; + + case DW_ExprOp_DerefType: + case DW_ExprOp_GNU_DerefType: { + // TODO: + AssertAlways(!"sample"); + } break; + + case DW_ExprOp_ConstType: + case DW_ExprOp_GNU_ConstType: { + // TODO: + AssertAlways(!"sample"); + } break; + + case DW_ExprOp_RegvalType: { + // TODO: + AssertAlways(!"sample"); + } break; + + case DW_ExprOp_EntryValue: + case DW_ExprOp_GNU_EntryValue: { + U64 entry_value_expr_size = 0; + String8 entry_value_expr = {0}; + cursor += str8_deserial_read_uleb128(expr, cursor, &entry_value_expr_size); + cursor += str8_deserial_read_block(expr, cursor, entry_value_expr_size, &entry_value_expr); + + B32 dummy = 0; + RDIM_EvalBytecode call_site_bc = d2r_bytecode_from_expression(arena, input, image_base, address_size, arch, addr_lu, entry_value_expr, cu, &dummy); + + U32 encoded_size32 = safe_cast_u32(call_site_bc.encoded_size); + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_CallSiteValue, encoded_size32); + rdim_bytecode_concat_in_place(&bc, &call_site_bc); + } break; + + case DW_ExprOp_Addrx: { + U64 addr_idx = 0; + cursor += str8_deserial_read_uleb128(expr, cursor, &addr_idx); + U64 addr = dw_addr_from_list_unit(addr_lu, addr_idx); + if (addr != max_U64) { + if (addr >= image_base) { + U64 voff = addr - image_base; + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_ModuleOff, voff); + } else { + // TODO: error handling + AssertAlways(!"unable to relocate address"); + } + } else { + // TODO: error handling + AssertAlways(!"out of bounds index"); + } + } break; + + case DW_ExprOp_CallFrameCfa: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_FrameOff, 0); + } break; + + case DW_ExprOp_FormTlsAddress: { + // TODO: + AssertAlways(!"RDI_EvalOp_TLSOff accepts immediate"); + } break; + + case DW_ExprOp_PushObjectAddress: { + AssertAlways(!"sample"); + } break; + + case DW_ExprOp_Nop: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Noop, 0); + } break; + + case DW_ExprOp_Eq: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_EqEq, peek_type()); + } break; + + case DW_ExprOp_Ge: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_GrEq, peek_type()); + } break; + + case DW_ExprOp_Gt: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Grtr, peek_type()); + } break; + + case DW_ExprOp_Le: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_LsEq, peek_type()); + } break; + + case DW_ExprOp_Lt: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Less, peek_type()); + } break; + + case DW_ExprOp_Ne: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_NtEq, peek_type()); + } break; + + case DW_ExprOp_Shl: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_LShift, peek_type()); + } break; + + case DW_ExprOp_Shr: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RShift, RDI_EvalTypeGroup_U); + } break; + + case DW_ExprOp_Shra: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_RShift, RDI_EvalTypeGroup_S); + } break; + + case DW_ExprOp_Xor: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitXor, peek_type()); + } break; + + case DW_ExprOp_XDeref: { + // TODO: error handling + Assert(!"multiple address spaces are not supported"); + } break; + + case DW_ExprOp_Abs: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Abs, peek_type()); + } break; + + case DW_ExprOp_And: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitAnd, peek_type()); + } break; + + case DW_ExprOp_Div: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Div, peek_type()); + } break; + + case DW_ExprOp_Minus: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Sub, peek_type()); + } break; + + case DW_ExprOp_Mod: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Mod, peek_type()); + } break; + + case DW_ExprOp_Mul: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Mul, peek_type()); + } break; + + case DW_ExprOp_Neg: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Neg, peek_type()); + } break; + + case DW_ExprOp_Not: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitNot, peek_type()); + } break; + + case DW_ExprOp_Or: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_BitOr, peek_type()); + } break; + + case DW_ExprOp_Plus: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Add, peek_type()); + } break; + + case DW_ExprOp_Rot: { + AssertAlways(!"no suitable conversion"); + } break; + + case DW_ExprOp_Swap: { + AssertAlways(!"no suitable conversion"); + } break; + + case DW_ExprOp_Dup: { + AssertAlways(!"no suitable conversion"); + } break; + + case DW_ExprOp_Drop: { + AssertAlways(!"no suitable conversion"); + } break; + + case DW_ExprOp_Over: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Pick, 1); + } break; + + case DW_ExprOp_StackValue: { + rdim_bytecode_push_op(arena, &bc, RDI_EvalOp_Stop, 0); + } break; + + default: InvalidPath; break; } } - + +#undef peek_type +#undef pop_type +#undef push_of_type + scratch_end(scratch); return bc; } internal RDIM_Location * -d2r_transpile_expression(Arena *arena, U64 image_base, U64 address_size, RDI_Arch arch, DW_ListUnit *addr_lu, String8 expr) +d2r_transpile_expression(Arena *arena, DW_Input *input, U64 image_base, U64 address_size, Arch arch, DW_ListUnit *addr_lu, DW_CompUnit *cu, String8 expr) { RDIM_Location *loc = 0; if (expr.size) { + B32 is_addr = 0; + RDIM_EvalBytecode bytecode = d2r_bytecode_from_expression(arena, input, image_base, address_size, arch, addr_lu, expr, cu, &is_addr); + loc = push_array(arena, RDIM_Location, 1); - loc->kind = RDI_LocationKind_AddrBytecodeStream; - loc->bytecode = d2r_bytecode_from_expression(arena, image_base, address_size, arch, addr_lu, expr); + loc->kind = is_addr ? RDI_LocationKind_AddrBytecodeStream : RDI_LocationKind_ValBytecodeStream; + loc->bytecode = bytecode; } return loc; } -internal RDIM_LocationSet -d2r_convert_loclist(Arena *arena, RDIM_ScopeChunkList *scopes, U64 image_base, U64 address_size, RDI_Arch arch, DW_ListUnit *addr_lu, DW_LocList loclist) +internal RDIM_Location * +d2r_location_from_attrib(Arena *arena, DW_Input *input, DW_CompUnit *cu, U64 image_base, Arch arch, DW_Tag tag, DW_AttribKind kind) { - RDIM_LocationSet locset = {0}; - for (DW_LocNode *loc_n = loclist.first; loc_n != 0; loc_n = loc_n->next) { - RDIM_Location *location = d2r_transpile_expression(arena, image_base, address_size, arch, addr_lu, loc_n->v.expr); - RDIM_Rng1U64 voff_range = { .min = loc_n->v.range.min - image_base, .min = loc_n->v.range.max - image_base }; - rdim_location_set_push_case(arena, scopes, &locset, voff_range, location); - } - return locset; + String8 expr = dw_exprloc_from_attrib(input, cu, tag, kind); + RDIM_Location *location = d2r_transpile_expression(arena, input, image_base, cu->address_size, arch, cu->addr_lu, cu, expr); + return location; } internal RDIM_LocationSet @@ -657,70 +850,126 @@ d2r_locset_from_attrib(Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_Scope *curr_scope, U64 image_base, - U64 address_size, - RDI_Arch arch, - DW_ListUnit *addr_lu, + Arch arch, DW_Tag tag, DW_AttribKind kind) { - RDIM_LocationSet result = {0}; - + RDIM_LocationSet locset = {0}; + + // extract attrib from tag 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_LocList || attrib_class == DW_AttribClass_LocListPtr) { Temp scratch = scratch_begin(&arena, 1); + + // extract location list from attrib DW_LocList loclist = dw_loclist_from_attrib_ptr(scratch.arena, input, cu, attrib); - result = d2r_convert_loclist(arena, scopes, image_base, address_size, arch, addr_lu, loclist); + + // convert location list to RDIM location set + for (DW_LocNode *loc_n = loclist.first; loc_n != 0; loc_n = loc_n->next) { + RDIM_Location *location = d2r_transpile_expression(arena, input, image_base, cu->address_size, arch, cu->addr_lu, cu, loc_n->v.expr); + RDIM_Rng1U64 voff_range = { .min = loc_n->v.range.min - image_base, .max = loc_n->v.range.max - image_base }; + rdim_location_set_push_case(arena, scopes, &locset, voff_range, location); + } + + scratch_end(scratch); } else if (attrib_class == DW_AttribClass_ExprLoc) { - String8 expr = dw_exprloc_from_attrib_ptr(input, cu, attrib); - RDIM_Location *location = d2r_transpile_expression(arena, image_base, address_size, arch, addr_lu, expr); + // extract expression from attrib + String8 expr = dw_exprloc_from_attrib_ptr(input, cu, attrib); + + // convert expression and inherit life-time ranges from enclosed scope + RDIM_Location *location = d2r_transpile_expression(arena, input, image_base, cu->address_size, arch, cu->addr_lu, cu, expr); for (RDIM_Rng1U64Node *range_n = curr_scope->voff_ranges.first; range_n != 0; range_n = range_n->next) { - rdim_location_set_push_case(arena, scopes, &result, range_n->v, location); + rdim_location_set_push_case(arena, scopes, &locset, range_n->v, location); } } else if (attrib_class != DW_AttribClass_Null) { AssertAlways(!"unexpected attrib class"); } + + return locset; +} - return result; +internal RDIM_LocationSet +d2r_var_locset_from_tag(Arena *arena, + DW_Input *input, + DW_CompUnit *cu, + RDIM_ScopeChunkList *scopes, + RDIM_Scope *curr_scope, + U64 image_base, + Arch arch, + DW_Tag tag) +{ + RDIM_LocationSet locset = {0}; + + B32 has_const_value = dw_tag_has_attrib(input, cu, tag, DW_Attrib_ConstValue); + B32 has_location = dw_tag_has_attrib(input, cu, tag, DW_Attrib_Location); + + if (has_const_value && has_location) { + // TODO: error handling + AssertAlways(!"unexpected variable encoding"); + } + + if (has_const_value) { + // extract const value + U64 const_value = dw_u64_from_attrib(input, cu, tag, DW_Attrib_ConstValue); + + // make value byte code + RDIM_EvalBytecode bc = {0}; + rdim_bytecode_push_uconst(arena, &bc, const_value); + + // fill out location + RDIM_Location *loc = push_array(arena, RDIM_Location, 1); + loc->kind = RDI_LocationKind_ValBytecodeStream; + loc->bytecode = bc; + + // push location cases + for (RDIM_Rng1U64Node *range_n = curr_scope->voff_ranges.first; range_n != 0; range_n = range_n->next) { + rdim_location_set_push_case(arena, scopes, &locset, range_n->v, loc); + } + } else if (has_location) { + locset = d2r_locset_from_attrib(arena, input, cu, scopes, curr_scope, image_base, arch, tag, DW_Attrib_Location); + } + + return locset; } internal D2R_CompUnitContribMap d2r_cu_contrib_map_from_aranges(Arena *arena, DW_Input *input, U64 image_base) { Temp scratch = scratch_begin(&arena, 1); - + String8 aranges_data = input->sec[DW_Section_ARanges].data; Rng1U64List unit_range_list = dw_unit_ranges_from_data(scratch.arena, aranges_data); - + D2R_CompUnitContribMap cm = {0}; cm.count = 0; - cm.info_off_arr = push_array(arena, U64, unit_range_list.count); - cm.voff_range_arr = push_array(arena, RDIM_Rng1U64List, unit_range_list.count); - + cm.info_off_arr = push_array(arena, U64, unit_range_list.count); + cm.voff_range_arr = push_array(arena, RDIM_Rng1U64ChunkList, unit_range_list.count); + for (Rng1U64Node *range_n = unit_range_list.first; range_n != 0; range_n = range_n->next) { String8 unit_data = str8_substr(aranges_data, range_n->v); U64 unit_cursor = 0; - + U64 unit_length = 0; U64 unit_length_size = str8_deserial_read_dwarf_packed_size(unit_data, unit_cursor, &unit_length); if (unit_length_size == 0) { continue; } unit_cursor += unit_length_size; - + DW_Version version = 0; U64 version_size = str8_deserial_read_struct(unit_data, unit_cursor, &version); if (version_size == 0) { continue; } unit_cursor += version; - + if (version != DW_Version_2) { AssertAlways(!"unknown .debug_aranges version"); continue; } - + DW_Format unit_format = DW_FormatFromSize(unit_length); U64 cu_info_off = 0; U64 cu_info_off_size = str8_deserial_read_dwarf_uint(unit_data, unit_cursor, unit_format, &cu_info_off); @@ -728,64 +977,64 @@ d2r_cu_contrib_map_from_aranges(Arena *arena, DW_Input *input, U64 image_base) continue; } unit_cursor += cu_info_off_size; - + U8 address_size = 0; U64 address_size_size = str8_deserial_read_struct(unit_data, unit_cursor, &address_size); if (address_size_size == 0) { continue; } unit_cursor += address_size_size; - + U8 segment_selector_size = 0; U64 segment_selector_size_size = str8_deserial_read_struct(unit_data, unit_cursor, &segment_selector_size); if (segment_selector_size_size == 0) { continue; } unit_cursor += segment_selector_size_size; - + U64 tuple_size = address_size * 2 + segment_selector_size; U64 bytes_too_far_past_boundary = unit_cursor % tuple_size; if (bytes_too_far_past_boundary > 0) { unit_cursor += tuple_size - bytes_too_far_past_boundary; } - - RDIM_Rng1U64List voff_ranges = {0}; + + RDIM_Rng1U64ChunkList voff_ranges = {0}; if (segment_selector_size == 0) { while (unit_cursor + address_size * 2 <= unit_data.size) { U64 address = 0; U64 length = 0; unit_cursor += str8_deserial_read(unit_data, unit_cursor, &address, address_size, address_size); unit_cursor += str8_deserial_read(unit_data, unit_cursor, &length, address_size, address_size); - + if (address == 0 && length == 0) { break; } - + // TODO: error handling AssertAlways(address >= image_base); - + U64 min = address - image_base; U64 max = min + length; - rdim_rng1u64_list_push(arena, &voff_ranges, (RDIM_Rng1U64){.min = min, .max = max}); + rdim_rng1u64_chunk_list_push(arena, &voff_ranges, 256, (RDIM_Rng1U64){.min = min, .max = max}); } } else { // TODO: segment relative addressing NotImplemented; } - + U64 map_idx = cm.count++; cm.info_off_arr[map_idx] = cu_info_off; cm.voff_range_arr[map_idx] = voff_ranges; } - + scratch_end(scratch); return cm; } -internal RDIM_Rng1U64List +internal RDIM_Rng1U64ChunkList d2r_voff_ranges_from_cu_info_off(D2R_CompUnitContribMap map, U64 info_off) { - RDIM_Rng1U64List voff_ranges = {0}; + RDIM_Rng1U64ChunkList voff_ranges = {0}; U64 voff_list_idx = u64_array_bsearch(map.info_off_arr, map.count, info_off); if (voff_list_idx < map.count) { voff_ranges = map.voff_range_arr[voff_list_idx]; @@ -798,117 +1047,107 @@ d2r_push_scope(Arena *arena, RDIM_ScopeChunkList *scopes, U64 scope_chunk_cap, D { // fill out scope RDIM_Scope *scope = rdim_scope_chunk_list_push(arena, scopes, scope_chunk_cap); - + // push ranges for (Rng1U64Node *i = ranges.first; i != 0; i = i->next) { rdim_scope_push_voff_range(arena, scopes, scope, (RDIM_Rng1U64){.min = i->v.min, i->v.max}); } - + // associate scope with tag tag_stack->scope = scope; - + // update scope hierarchy DW_TagKind parent_tag_kind = tag_stack->next->cur_node->tag.kind; if (parent_tag_kind == DW_Tag_SubProgram || parent_tag_kind == DW_Tag_InlinedSubroutine || parent_tag_kind == DW_Tag_LexicalBlock) { RDIM_Scope *parent = tag_stack->next->scope; - - scope->parent_scope = tag_stack->next->scope; - + + scope->parent_scope = parent; + scope->symbol = parent->symbol; + if (parent->last_child) { parent->last_child->next_sibling = scope; } - SLLQueuePush_N(parent->first_child, parent->last_child, scope, next_sibling); } - - // propagate scope symbol - if (tag_stack->cur_node->tag.kind == DW_Tag_LexicalBlock) { - scope->symbol = tag_stack->next->scope->symbol; - } - + return scope; } -internal RDIM_BakeParams * -d2r_convert(Arena *arena, D2R_User2Convert *in) +internal RDIM_BakeParams +d2r_convert(Arena *arena, ASYNC_Root *async_root, D2R_ConvertParams *params) { Temp scratch = scratch_begin(&arena, 1); - - B32 is_parse_relaxed = !(in->flags & D2R_ConvertFlag_StrictParse); - - RDIM_BinarySectionList binary_sections = {0}; + + //////////////////////////////// + + ProfBegin("compute exe hash"); + U64 exe_hash = rdi_hash(params->exe_data.str, params->exe_data.size); + ProfEnd(); + + //////////////////////////////// + Arch arch = Arch_Null; U64 image_base = 0; - U64 voff_max = 0; + RDIM_BinarySectionList binary_sections = {0}; DW_Input input = {0}; - DW_ListUnitInput lui = {0}; - if (pe_check_magic(in->input_exe_data)) { - PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, in->input_exe_data); - - // infer exe info - arch = pe.arch; - image_base = pe.image_base; - - // get COFF sections - String8 raw_sections = str8_substr(in->input_exe_data, rng_1u64(pe.section_array_off, pe.section_array_off+sizeof(COFF_SectionHeader)*pe.section_count)); - U64 section_count = raw_sections.size / sizeof(COFF_SectionHeader); - COFF_SectionHeader *section_array = (COFF_SectionHeader *)raw_sections.str; - - // loop over section headers and pick max virtual offset - for (U64 i = 0; i < section_count; ++i) { - U64 sec_voff_max = section_array[i].voff + section_array[i].vsize; - voff_max = Max(voff_max, sec_voff_max); - } - - ProfBegin("binary sections"); - for (U64 i = 0; i < section_count; ++i) { - COFF_SectionHeader *coff_sec = §ion_array[i]; - RDIM_BinarySection *sec = rdim_binary_section_list_push(arena, &binary_sections); - - sec->name = coff_name_from_section_header(in->input_exe_data, coff_sec, pe.string_table_off); - sec->flags = rdi_binary_section_flags_from_coff_section_flags(coff_sec->flags); - sec->voff_first = coff_sec->voff; - sec->voff_opl = coff_sec->voff + coff_sec->vsize; - sec->foff_first = coff_sec->foff; - sec->foff_opl = coff_sec->foff + coff_sec->fsize; - } - ProfEnd(); - - // find DWARF sections - input = dw_input_from_coff_section_table(scratch.arena, in->input_exe_data, pe.string_table_off, section_count, section_array); + + switch(params->exe_kind) + { + default:{}break; + case ExecutableImageKind_CoffPe: + { + PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, params->exe_data); + + // get image arch + arch = pe.arch; + + // get image base + image_base = pe.image_base; + + // get image sections + String8 raw_sections = str8_substr(params->exe_data, pe.section_table_range); + U64 section_count = raw_sections.size / sizeof(COFF_SectionHeader); + COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_sections.str; + + // convert sections + String8 string_table = str8_substr(params->exe_data, pe.string_table_range); + binary_sections = c2r_rdi_binary_sections_from_coff_sections(arena, params->exe_data, string_table, section_count, section_table); + + // make DWARF input + input = dw_input_from_coff_section_table(scratch.arena, params->exe_data, string_table, section_count, section_table); + }break; + case ExecutableImageKind_Elf32: + case ExecutableImageKind_Elf64: + { + ELF_BinInfo elf = elf_bin_from_data(params->dbg_data); + + // get image arch + arch = arch_from_elf_machine(elf.hdr.e_machine); + + // get image base + image_base = elf_base_addr_from_bin(&elf.hdr); + + // get image sections + ELF_Shdr64Array shdrs = elf_shdr64_array_from_bin(scratch.arena, params->dbg_data, &elf.hdr); + + // convert sections + binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, shdrs); + + // make DWARF input + input = dw_input_from_elf_section_table(scratch.arena, params->dbg_data, &elf); + }break; } - + //////////////////////////////// - - RDI_Arch arch_rdi = RDI_Arch_NULL; - switch (arch) { - case Arch_Null: arch_rdi = RDI_Arch_NULL; break; - case Arch_x64: arch_rdi = RDI_Arch_X64; break; - case Arch_x86: arch_rdi = RDI_Arch_X86; break; - default: NotImplemented; break; - } - - U64 arch_addr_size = rdi_addr_size_from_arch(arch_rdi); - + + RDIM_TopLevelInfo top_level_info = rdim_make_top_level_info(params->exe_name, arch, exe_hash, binary_sections); + //////////////////////////////// - - ProfBegin("compute exe hash"); - U64 exe_hash = rdi_hash(in->input_exe_data.str, in->input_exe_data.size); - ProfEnd(); - + + U64 arch_addr_size = rdi_addr_size_from_arch(arch); + //////////////////////////////// - - ProfBegin("top level info"); - RDIM_TopLevelInfo top_level_info = {0}; - top_level_info.arch = arch_rdi; - top_level_info.exe_name = str8_skip_last_slash(in->input_exe_name); - top_level_info.exe_hash = exe_hash; - top_level_info.voff_max = voff_max; - top_level_info.producer_name = str8_lit(BUILD_TITLE_STRING_LITERAL); - ProfEnd(); - - //////////////////////////////// - + static const U64 UNIT_CHUNK_CAP = 256; static const U64 UDT_CHUNK_CAP = 256; static const U64 TYPE_CHUNK_CAP = 256; @@ -919,10 +1158,10 @@ d2r_convert(Arena *arena, D2R_User2Convert *in) static const U64 INLINE_SITE_CHUNK_CAP = 256; static const U64 SRC_FILE_CAP = 256; static const U64 LINE_TABLE_CAP = 256; - + RDIM_UnitChunkList units = {0}; RDIM_UDTChunkList udts = {0}; - RDIM_TypeChunkList types = {0}; + RDIM_TypeChunkList types = rdim_init_type_chunk_list(arena, arch); RDIM_SymbolChunkList gvars = {0}; RDIM_SymbolChunkList tvars = {0}; RDIM_SymbolChunkList procs = {0}; @@ -930,9 +1169,13 @@ d2r_convert(Arena *arena, D2R_User2Convert *in) RDIM_InlineSiteChunkList inline_sites = {0}; RDIM_SrcFileChunkList src_files = {0}; RDIM_LineTableChunkList line_tables = {0}; - + //////////////////////////////// - + + RDIM_Scope *global_scope = rdim_scope_chunk_list_push(arena, &scopes, SCOPE_CHUNK_CAP); + + //////////////////////////////// + ProfBegin("Make Unit Contrib Map"); D2R_CompUnitContribMap cu_contrib_map = {0}; if (input.sec[DW_Section_ARanges].data.size > 0) { @@ -942,24 +1185,28 @@ d2r_convert(Arena *arena, D2R_User2Convert *in) NotImplemented; } ProfEnd(); - + ProfBegin("Parse Comop Unit Ranges"); DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, &input); Rng1U64List cu_range_list = dw_unit_ranges_from_data(scratch.arena, input.sec[DW_Section_Info].data); Rng1U64Array cu_ranges = rng1u64_array_from_list(scratch.arena, &cu_range_list); ProfEnd(); - + //////////////////////////////// - + ProfBegin("Parse Compile Unit Headers"); + // TODO(rjf): parse should always be relaxed. any verification checks we do + // should just be logged via log_info(...), and then the caller of this + // converter can collect those & display as necessary. + B32 is_parse_relaxed = 1; DW_CompUnit *cu_arr = push_array(scratch.arena, DW_CompUnit, cu_ranges.count); for (U64 cu_idx = 0; cu_idx < cu_ranges.count; ++cu_idx) { cu_arr[cu_idx] = dw_cu_from_info_off(scratch.arena, &input, lu_input, cu_ranges.v[cu_idx].min, is_parse_relaxed); } ProfEnd(); - + //////////////////////////////// - + ProfBegin("Parse Line Tables"); DW_LineTableParseResult *cu_line_tables = push_array(scratch.arena, DW_LineTableParseResult, cu_ranges.count); for (U64 cu_idx = 0; cu_idx < cu_ranges.count; ++cu_idx) { @@ -970,17 +1217,17 @@ d2r_convert(Arena *arena, D2R_User2Convert *in) cu_line_tables[cu_idx] = dw_parsed_line_table_from_data(scratch.arena, cu_stmt_list, &input, cu_dir, cu_name, cu->address_size, cu->str_offsets_lu); } ProfEnd(); - + //////////////////////////////// - + ProfBegin("Convert Line Tables"); - + HashTable *source_file_ht = hash_table_init(scratch.arena, 0x4000); RDIM_LineTable **cu_line_tables_rdi = push_array(scratch.arena, RDIM_LineTable *, cu_ranges.count); - + for (U64 cu_idx = 0; cu_idx < cu_ranges.count; ++cu_idx) { cu_line_tables_rdi[cu_idx] = rdim_line_table_chunk_list_push(arena, &line_tables, LINE_TABLE_CAP); - + DW_LineTableParseResult *line_table = &cu_line_tables[cu_idx]; DW_LineVMFileArray *dir_table = &line_table->vm_header.dir_table; DW_LineVMFileArray *file_table = &line_table->vm_header.file_table; @@ -1000,27 +1247,27 @@ d2r_convert(Arena *arena, D2R_User2Convert *in) } src_file_map[file_idx] = src_file; } - + for (DW_LineSeqNode *line_seq = line_table->first_seq; line_seq != 0; line_seq = line_seq->next) { if (line_seq->count == 0) { continue; } - + U64 *voffs = push_array(arena, U64, line_seq->count); U32 *line_nums = push_array(arena, U32, line_seq->count); U16 *col_nums = 0; U64 line_idx = 0; - + DW_LineNode *file_line_n = line_seq->first; U64 file_line_count = 0; - + for (DW_LineNode *line_n = file_line_n; line_n != 0; line_n = line_n->next) { if (file_line_n->v.file_index != line_n->v.file_index || line_n->next == 0) { U64 file_index = file_line_n->v.file_index; U64 *file_voffs = &voffs[line_idx]; U32 *file_line_nums = &line_nums[line_idx]; U16 *file_col_nums = 0; - + U64 lines_written = 0; U64 prev_ln = max_U64; DW_LineNode *sentinel = line_n->v.file_index != file_line_n->v.file_index ? line_n : 0; @@ -1028,82 +1275,82 @@ d2r_convert(Arena *arena, D2R_User2Convert *in) if (file_line_n->v.line != prev_ln) { // TODO: error handling AssertAlways(file_line_n->v.address >= image_base); - + voffs[line_idx] = file_line_n->v.address - image_base; line_nums[line_idx] = file_line_n->v.line; - + ++lines_written; ++line_idx; - + prev_ln = file_line_n->v.line; } } - + RDIM_SrcFile *src_file = src_file_map[file_index]; RDIM_LineSequence *line_seq = rdim_line_table_push_sequence(arena, &line_tables, cu_line_tables_rdi[cu_idx], src_file, file_voffs, file_line_nums, file_col_nums, lines_written); rdim_src_file_push_line_sequence(arena, &src_files, src_file, line_seq); - + file_line_count = 1; } else { ++file_line_count; } } - + // handle last line if (file_line_n) { U64 file_index = file_line_n->v.file_index; U64 *file_voffs = &voffs[line_idx]; U32 *file_line_nums = &line_nums[line_idx]; U16 *file_col_nums = 0; - + for (; file_line_n != 0; file_line_n = file_line_n->next, ++line_idx) { // TODO: error handling AssertAlways(file_line_n->v.address >= image_base); voffs[line_idx] = file_line_n->v.address - image_base; line_nums[line_idx] = file_line_n->v.line; } - + RDIM_SrcFile *src_file = src_file_map[file_index]; RDIM_LineSequence *line_seq = rdim_line_table_push_sequence(arena, &line_tables, cu_line_tables_rdi[cu_idx], src_file, file_voffs, file_line_nums, file_col_nums, file_line_count); rdim_src_file_push_line_sequence(arena, &src_files, src_file, line_seq); } - + //Assert(line_idx == line_seq->count); } } - + ProfEnd(); - + //////////////////////////////// ProfBegin("Convert Units"); - + for (U64 cu_idx = 0; cu_idx < cu_ranges.count; ++cu_idx) { Temp comp_temp = temp_begin(scratch.arena); - + DW_CompUnit *cu = &cu_arr[cu_idx]; - + // parse and build tag tree DW_TagTree tag_tree = dw_tag_tree_from_cu(comp_temp.arena, &input, cu); - + // build tag hash table for abstract origin resolution cu->tag_ht = dw_make_tag_hash_table(comp_temp.arena, tag_tree); - + String8 dwo_name = dw_string_from_attrib(&input, cu, cu->tag, DW_Attrib_DwoName); String8 gnu_dwo_name = dw_string_from_attrib(&input, cu, cu->tag, DW_Attrib_GNU_DwoName); if (dwo_name.size || gnu_dwo_name.size || cu->dwo_id) { // TODO: report that we dont support DWO continue; } - + // get unit's contribution ranges - RDIM_Rng1U64List cu_voff_ranges = d2r_voff_ranges_from_cu_info_off(cu_contrib_map, cu_ranges.v[cu_idx].min); - + RDIM_Rng1U64ChunkList cu_voff_ranges = d2r_voff_ranges_from_cu_info_off(cu_contrib_map, cu_ranges.v[cu_idx].min); + String8 cu_name = dw_string_from_attrib(&input, cu, cu->tag, DW_Attrib_Name); String8 cu_dir = dw_string_from_attrib(&input, cu, cu->tag, DW_Attrib_CompDir); String8 cu_prod = dw_string_from_attrib(&input, cu, cu->tag, DW_Attrib_Producer); DW_Language cu_lang = dw_const_u64_from_attrib(&input, cu, cu->tag, DW_Attrib_Language); - + RDIM_Unit *unit = rdim_unit_chunk_list_push(arena, &units, UNIT_CHUNK_CAP); unit->unit_name = cu_name; unit->compiler_name = cu_prod; @@ -1114,454 +1361,525 @@ d2r_convert(Arena *arena, D2R_User2Convert *in) unit->language = rdi_language_from_dw_language(cu_lang); unit->line_table = cu_line_tables_rdi[cu_idx]; unit->voff_ranges = cu_voff_ranges; - + D2R_TypeTable *type_table = push_array(comp_temp.arena, D2R_TypeTable, 1); type_table->ht = hash_table_init(comp_temp.arena, 0x4000); type_table->types = &types; type_table->type_chunk_cap = TYPE_CHUNK_CAP; - type_table->void_type = d2r_create_type(arena, type_table); - type_table->void_type->kind = RDI_TypeKind_Void; type_table->varg_type = d2r_create_type(arena, type_table); type_table->varg_type->kind = RDI_TypeKind_Variadic; - + D2R_TagNode *free_tags = push_array(comp_temp.arena, D2R_TagNode, 1); D2R_TagNode *tag_stack = push_array(comp_temp.arena, D2R_TagNode, 1); tag_stack->cur_node = tag_tree.root; - + while (tag_stack) { while (tag_stack->cur_node) { DW_TagNode *cur_node = tag_stack->cur_node; DW_Tag tag = cur_node->tag; B32 visit_children = 1; - + switch (tag.kind) { - case DW_Tag_Null: { - InvalidPath; - } break; - case DW_Tag_ClassType: { - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - - B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); - if (is_decl) { - type->kind = RDI_TypeKind_IncompleteClass; - - Assert(!cur_node->first_child); - visit_children = 0; - } else { - RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); - udt->self_type = type; - - type->kind = RDI_TypeKind_Class; - type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); - type->udt = udt; - type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - - tag_stack->type = type; - } - } break; - case DW_Tag_StructureType: { - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - - B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); - if (is_decl) { - type->kind = RDI_TypeKind_IncompleteStruct; - - // TODO: error handling - Assert(!cur_node->first_child); - visit_children = 0; - } else { - RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); - udt->self_type = type; - - type->kind = RDI_TypeKind_Struct; - type->udt = udt; - type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); + case DW_Tag_Null: { + InvalidPath; + } break; + case DW_Tag_ClassType: { + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - tag_stack->type = type; - } - } break; - case DW_Tag_UnionType: { - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - - B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); - if (is_decl) { - type->kind = RDI_TypeKind_IncompleteUnion; - - // TODO: error handling - Assert(!cur_node->first_child); - visit_children = 0; - } else { - RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); - udt->self_type = type; - - type->kind = RDI_TypeKind_Union; - type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); - type->udt = udt; - - tag_stack->type = type; - } - } break; - case DW_Tag_EnumerationType: { - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - - B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); - if (is_decl) { - type->kind = RDI_TypeKind_IncompleteEnum; - - // TODO: error handling - Assert(!cur_node->first_child); - visit_children = 0; - } else { - RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); - udt->self_type = type; - - type->kind = RDI_TypeKind_Enum; - type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); - type->udt = udt; - - tag_stack->type = type; - } - } break; - case DW_Tag_SubroutineType: { - // collect parameters - RDIM_TypeList param_list = {0}; - for (DW_TagNode *n = cur_node->first_child; n != 0; n = n->sibling) { - if (n->tag.kind == DW_Tag_FormalParameter) { - RDIM_Type *param_type = d2r_type_from_attrib(arena, type_table, &input, cu, n->tag, DW_Attrib_Type); - rdim_type_list_push(comp_temp.arena, ¶m_list, param_type); - } else if (n->tag.kind == DW_Tag_UnspecifiedParameters) { - rdim_type_list_push(comp_temp.arena, ¶m_list, type_table->varg_type); + B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); + if (is_decl) { + type->kind = RDI_TypeKind_IncompleteClass; + + Assert(!cur_node->first_child); + visit_children = 0; } else { + RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); + udt->self_type = type; + + type->kind = RDI_TypeKind_Class; + type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); + type->udt = udt; + type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + + tag_stack->type = type; + } + } break; + case DW_Tag_StructureType: { + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + + B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); + if (is_decl) { + type->kind = RDI_TypeKind_IncompleteStruct; + // TODO: error handling - AssertAlways(!"unexpected tag"); - } - } - - // init proceudre type - RDIM_Type *ret_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Function; - type->byte_size = arch_addr_size; - type->direct_type = ret_type; - type->count = param_list.count; - type->param_types = rdim_array_from_type_list(arena, param_list); - - visit_children = 0; - } break; - case DW_Tag_Typedef: { - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Alias; - type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - } break; - case DW_Tag_BaseType: { - DW_ATE encoding = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_Encoding); - U64 byte_size = dw_byte_size_from_tag(&input, cu, tag); - - // convert base type encoding to RDI version - RDI_TypeKind kind = RDI_TypeKind_NULL; - switch (encoding) { - case DW_ATE_Null: kind = RDI_TypeKind_NULL; break; - case DW_ATE_Address: kind = RDI_TypeKind_Void; break; - case DW_ATE_Boolean: kind = RDI_TypeKind_Bool; break; - case DW_ATE_ComplexFloat: { - switch (byte_size) { - case 4: kind = RDI_TypeKind_ComplexF32; break; - case 8: kind = RDI_TypeKind_ComplexF64; break; - case 10: kind = RDI_TypeKind_ComplexF80; break; - case 16: kind = RDI_TypeKind_ComplexF128; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling + Assert(!cur_node->first_child); + visit_children = 0; + } else { + RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); + udt->self_type = type; + + type->kind = RDI_TypeKind_Struct; + type->udt = udt; + type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); + + tag_stack->type = type; } } break; - case DW_ATE_Float: { - switch (byte_size) { - case 2: kind = RDI_TypeKind_F16; break; - case 4: kind = RDI_TypeKind_F32; break; - case 6: kind = RDI_TypeKind_F48; break; - case 8: kind = RDI_TypeKind_F64; break; - case 16: kind = RDI_TypeKind_F128; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling - } - } break; - case DW_ATE_Signed: { - switch (byte_size) { - case 1: kind = RDI_TypeKind_S8; break; - case 2: kind = RDI_TypeKind_S16; break; - case 4: kind = RDI_TypeKind_S32; break; - case 8: kind = RDI_TypeKind_S64; break; - case 16: kind = RDI_TypeKind_S128; break; - case 32: kind = RDI_TypeKind_S256; break; - case 64: kind = RDI_TypeKind_S512; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling - } - } break; - case DW_ATE_SignedChar: { - switch (byte_size) { - case 1: kind = RDI_TypeKind_Char8; break; - case 2: kind = RDI_TypeKind_Char16; break; - case 4: kind = RDI_TypeKind_Char32; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling - } - } break; - case DW_ATE_Unsigned: { - switch (byte_size) { - case 1: kind = RDI_TypeKind_U8; break; - case 2: kind = RDI_TypeKind_U16; break; - case 4: kind = RDI_TypeKind_U32; break; - case 8: kind = RDI_TypeKind_U64; break; - case 16: kind = RDI_TypeKind_U128; break; - case 32: kind = RDI_TypeKind_U256; break; - case 64: kind = RDI_TypeKind_U512; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling - } - } break; - case DW_ATE_UnsignedChar: { - switch (byte_size) { - case 1: kind = RDI_TypeKind_UChar8; break; - case 2: kind = RDI_TypeKind_UChar16; break; - case 4: kind = RDI_TypeKind_UChar32; break; - default: AssertAlways(!"unexpected size"); break; // TODO: error handling - } - } break; - case DW_ATE_ImaginaryFloat: { - NotImplemented; - } break; - case DW_ATE_PackedDecimal: { - NotImplemented; - } break; - case DW_ATE_NumericString: { - NotImplemented; - } break; - case DW_ATE_Edited: { - NotImplemented; - } break; - case DW_ATE_SignedFixed: { - NotImplemented; - } break; - case DW_ATE_UnsignedFixed: { - NotImplemented; - } break; - case DW_ATE_DecimalFloat: { - NotImplemented; - } break; - case DW_ATE_Utf: { - NotImplemented; - } break; - case DW_ATE_Ucs: { - NotImplemented; - } break; - case DW_ATE_Ascii: { - NotImplemented; - } break; - default: AssertAlways(!"unexpected base type encoding"); break; // TODO: error handling - } - - RDIM_Type *base_type = d2r_create_type(arena, type_table); - base_type->kind = kind; - base_type->byte_size = byte_size; - - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Alias; - type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - type->direct_type = base_type; - } break; - case DW_Tag_PointerType: { - RDIM_Type *direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - - // TODO: - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Allocated)); - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Associated)); - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Alignment)); - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_AddressClass)); - - U64 byte_size = arch_addr_size; - if (cu->version == DW_Version_5 || cu->relaxed) { - dw_try_byte_size_from_tag(&input, cu, tag, &byte_size); - } - - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Ptr; - type->byte_size = byte_size; - type->direct_type = direct_type; - } break; - case DW_Tag_RestrictType: { - // TODO: - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Alignment)); - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); - - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Modifier; - type->byte_size = arch_addr_size; - type->flags = RDI_TypeModifierFlag_Restrict; - type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - } break; - case DW_Tag_VolatileType: { - // TODO: - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); - - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Modifier; - type->byte_size = arch_addr_size; - type->flags = RDI_TypeModifierFlag_Volatile; - type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - } break; - case DW_Tag_ConstType: { - // TODO: - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); - Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Alignment)); - - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Modifier; - type->byte_size = arch_addr_size; - type->flags = RDI_TypeModifierFlag_Const; - type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - } break; - case DW_Tag_ArrayType: { - // * DWARF vs RDI Array Type Graph * - // - // For example lets take following decl: - // - // int (*foo[2])[3][4]; - // - // This compiles to in DWARF: - // - // foo -> DW_TAG_ArrayType -> (A0) DW_TAG_Subrange [2] - // \ - // -> (B0) DW_TAG_PointerType -> (A1) DW_TAG_ArrayType -> DW_TAG_Subrange [3] -> DW_Tag_Subrange [4] - // \ - // -> (B1) DW_TAG_BaseType (int) - // - // RDI expects: - // - // foo -> Array (2) -> Pointer -> Array (3) -> Array (4) -> int - // - // Note that DWARF forks the graph on DW_TAG_ArrayType to describe array ranges in branch A and - // in branch B describes array type which might be a struct, pointer, base type, or any other type tag. - // However, in RDI we have a simple list of type nodes and to convert we need to append type nodes from - // B to A. - - RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Array; - type->direct_type = 0; - - U64 subrange_count = 0; - RDIM_Type *t = type; - for (DW_TagNode *n = cur_node->first_child; n != 0; n = n->sibling) { - if (n->tag.kind != DW_Tag_SubrangeType) { + case DW_Tag_UnionType: { + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + + B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); + if (is_decl) { + type->kind = RDI_TypeKind_IncompleteUnion; + // TODO: error handling - AssertAlways(!"unexpected tag"); - continue; - } - - if (subrange_count > 0) { - // init array type node - RDIM_Type *s = d2r_create_type(arena, type_table); - s->kind = RDI_TypeKind_Array; - s->direct_type = 0; - - // append new array type node - t->direct_type = s; - t = s; - } - - // resolve array lower bound - U64 lower_bound = 0; - if (dw_tag_has_attrib(&input, cu, n->tag, DW_Attrib_LowerBound)) { - lower_bound = dw_u64_from_attrib(&input, cu, n->tag, DW_Attrib_LowerBound); + Assert(!cur_node->first_child); + visit_children = 0; } else { - lower_bound = dw_pick_default_lower_bound(cu_lang); + RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); + udt->self_type = type; + + type->kind = RDI_TypeKind_Union; + type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); + type->udt = udt; + + tag_stack->type = type; } - - // resolve array upper bound - U64 upper_bound = 0; - if (dw_tag_has_attrib(&input, cu, n->tag, DW_Attrib_Count)) { - U64 count = dw_u64_from_attrib(&input, cu, n->tag, DW_Attrib_Count); - upper_bound = lower_bound + count; - } else if (dw_tag_has_attrib(&input, cu, n->tag, DW_Attrib_UpperBound)) { - upper_bound = dw_u64_from_attrib(&input, cu, n->tag, DW_Attrib_UpperBound); - // turn upper bound into exclusive range - upper_bound += 1; + } break; + case DW_Tag_EnumerationType: { + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + + B32 is_decl = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_Declaration); + if (is_decl) { + type->kind = RDI_TypeKind_IncompleteEnum; + + // TODO: error handling + Assert(!cur_node->first_child); + visit_children = 0; } else { - // zero size array + RDIM_UDT *udt = rdim_udt_chunk_list_push(arena, &udts, UDT_CHUNK_CAP); + udt->self_type = type; + + type->kind = RDI_TypeKind_Enum; + type->byte_size = dw_byte_size_32_from_tag(&input, cu, tag); + type->udt = udt; + + tag_stack->type = type; } - - t->count = upper_bound - lower_bound; - ++subrange_count; - } - - Assert(t->direct_type == 0); - t->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - - visit_children = 0; - } break; - case DW_Tag_SubrangeType: { - // TODO: error handling - AssertAlways(!"unexpected tag"); - } break; - case DW_Tag_Inheritance: { - DW_TagNode *parent_node = tag_stack->next->cur_node; - if (parent_node->tag.kind != DW_Tag_StructureType && - parent_node->tag.kind != DW_Tag_ClassType) { + } break; + case DW_Tag_SubroutineType: { + // collect parameters + RDIM_TypeList param_list = {0}; + for (DW_TagNode *n = cur_node->first_child; n != 0; n = n->sibling) { + if (n->tag.kind == DW_Tag_FormalParameter) { + RDIM_Type *param_type = d2r_type_from_attrib(arena, type_table, &input, cu, n->tag, DW_Attrib_Type); + rdim_type_list_push(comp_temp.arena, ¶m_list, param_type); + } else if (n->tag.kind == DW_Tag_UnspecifiedParameters) { + rdim_type_list_push(comp_temp.arena, ¶m_list, type_table->varg_type); + } else { + // TODO: error handling + AssertAlways(!"unexpected tag"); + } + } + + // init proceudre type + RDIM_Type *ret_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Function; + type->byte_size = arch_addr_size; + type->direct_type = ret_type; + type->count = param_list.count; + type->param_types = rdim_array_from_type_list(arena, param_list); + + visit_children = 0; + } break; + case DW_Tag_Typedef: { + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Alias; + type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + } break; + case DW_Tag_BaseType: { + DW_ATE encoding = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_Encoding); + U64 byte_size = dw_byte_size_from_tag(&input, cu, tag); + + // convert base type encoding to RDI version + RDI_TypeKind kind = RDI_TypeKind_NULL; + switch (encoding) { + case DW_ATE_Null: kind = RDI_TypeKind_NULL; break; + case DW_ATE_Address: kind = RDI_TypeKind_Void; break; + case DW_ATE_Boolean: kind = RDI_TypeKind_Bool; break; + case DW_ATE_ComplexFloat: { + switch (byte_size) { + case 4: kind = RDI_TypeKind_ComplexF32; break; + case 8: kind = RDI_TypeKind_ComplexF64; break; + case 10: kind = RDI_TypeKind_ComplexF80; break; + case 16: kind = RDI_TypeKind_ComplexF128; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_Float: { + switch (byte_size) { + case 2: kind = RDI_TypeKind_F16; break; + case 4: kind = RDI_TypeKind_F32; break; + case 6: kind = RDI_TypeKind_F48; break; + case 8: kind = RDI_TypeKind_F64; break; + case 16: kind = RDI_TypeKind_F128; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_Signed: { + switch (byte_size) { + case 1: kind = RDI_TypeKind_S8; break; + case 2: kind = RDI_TypeKind_S16; break; + case 4: kind = RDI_TypeKind_S32; break; + case 8: kind = RDI_TypeKind_S64; break; + case 16: kind = RDI_TypeKind_S128; break; + case 32: kind = RDI_TypeKind_S256; break; + case 64: kind = RDI_TypeKind_S512; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_SignedChar: { + switch (byte_size) { + case 1: kind = RDI_TypeKind_Char8; break; + case 2: kind = RDI_TypeKind_Char16; break; + case 4: kind = RDI_TypeKind_Char32; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_Unsigned: { + switch (byte_size) { + case 1: kind = RDI_TypeKind_U8; break; + case 2: kind = RDI_TypeKind_U16; break; + case 4: kind = RDI_TypeKind_U32; break; + case 8: kind = RDI_TypeKind_U64; break; + case 16: kind = RDI_TypeKind_U128; break; + case 32: kind = RDI_TypeKind_U256; break; + case 64: kind = RDI_TypeKind_U512; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_UnsignedChar: { + switch (byte_size) { + case 1: kind = RDI_TypeKind_UChar8; break; + case 2: kind = RDI_TypeKind_UChar16; break; + case 4: kind = RDI_TypeKind_UChar32; break; + default: AssertAlways(!"unexpected size"); break; // TODO: error handling + } + } break; + case DW_ATE_ImaginaryFloat: { + NotImplemented; + } break; + case DW_ATE_PackedDecimal: { + NotImplemented; + } break; + case DW_ATE_NumericString: { + NotImplemented; + } break; + case DW_ATE_Edited: { + NotImplemented; + } break; + case DW_ATE_SignedFixed: { + NotImplemented; + } break; + case DW_ATE_UnsignedFixed: { + NotImplemented; + } break; + case DW_ATE_DecimalFloat: { + NotImplemented; + } break; + case DW_ATE_Utf: { + NotImplemented; + } break; + case DW_ATE_Ucs: { + NotImplemented; + } break; + case DW_ATE_Ascii: { + NotImplemented; + } break; + default: AssertAlways(!"unexpected base type encoding"); break; // TODO: error handling + } + + RDIM_Type *base_type = rdim_builtin_type_from_kind(types, kind); + base_type->kind = kind; + base_type->byte_size = byte_size; + + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Alias; + type->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + type->direct_type = base_type; + } break; + case DW_Tag_PointerType: { + RDIM_Type *direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + + // TODO: + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Allocated)); + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Associated)); + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Alignment)); + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_AddressClass)); + + U64 byte_size = arch_addr_size; + if (cu->version == DW_Version_5 || cu->relaxed) { + dw_try_byte_size_from_tag(&input, cu, tag, &byte_size); + } + + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Ptr; + type->byte_size = byte_size; + type->direct_type = direct_type; + } break; + case DW_Tag_RestrictType: { + // TODO: + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Alignment)); + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); + + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Modifier; + type->byte_size = arch_addr_size; + type->flags = RDI_TypeModifierFlag_Restrict; + type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + } break; + case DW_Tag_VolatileType: { + // TODO: + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); + + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Modifier; + type->byte_size = arch_addr_size; + type->flags = RDI_TypeModifierFlag_Volatile; + type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + } break; + case DW_Tag_ConstType: { + // TODO: + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Name)); + Assert(!dw_tag_has_attrib(&input, cu, tag, DW_Attrib_Alignment)); + + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Modifier; + type->byte_size = arch_addr_size; + type->flags = RDI_TypeModifierFlag_Const; + type->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + } break; + case DW_Tag_ArrayType: { + // * DWARF vs RDI Array Type Graph * + // + // For example lets take following decl: + // + // int (*foo[2])[3][4]; + // + // This compiles to in DWARF: + // + // foo -> DW_TAG_ArrayType -> (A0) DW_TAG_Subrange [2] + // \ + // -> (B0) DW_TAG_PointerType -> (A1) DW_TAG_ArrayType -> DW_TAG_Subrange [3] -> DW_Tag_Subrange [4] + // \ + // -> (B1) DW_TAG_BaseType (int) + // + // RDI expects: + // + // foo -> Array (2) -> Pointer -> Array (3) -> Array (4) -> int + // + // Note that DWARF forks the graph on DW_TAG_ArrayType to describe array ranges in branch A and + // in branch B describes array type which might be a struct, pointer, base type, or any other type tag. + // However, in RDI we have a simple list of type nodes and to convert we need to append type nodes from + // B to A. + + RDIM_Type *type = d2r_find_or_create_type_from_offset(arena, type_table, tag.info_off); + type->kind = RDI_TypeKind_Array; + type->direct_type = 0; + + U64 subrange_count = 0; + RDIM_Type *t = type; + for (DW_TagNode *n = cur_node->first_child; n != 0; n = n->sibling) { + if (n->tag.kind != DW_Tag_SubrangeType) { + // TODO: error handling + AssertAlways(!"unexpected tag"); + continue; + } + + if (subrange_count > 0) { + // init array type node + RDIM_Type *s = d2r_create_type(arena, type_table); + s->kind = RDI_TypeKind_Array; + s->direct_type = 0; + + // append new array type node + t->direct_type = s; + t = s; + } + + // resolve array lower bound + U64 lower_bound = 0; + if (dw_tag_has_attrib(&input, cu, n->tag, DW_Attrib_LowerBound)) { + lower_bound = dw_u64_from_attrib(&input, cu, n->tag, DW_Attrib_LowerBound); + } else { + lower_bound = dw_pick_default_lower_bound(cu_lang); + } + + // resolve array upper bound + U64 upper_bound = 0; + if (dw_tag_has_attrib(&input, cu, n->tag, DW_Attrib_Count)) { + U64 count = dw_u64_from_attrib(&input, cu, n->tag, DW_Attrib_Count); + upper_bound = lower_bound + count; + } else if (dw_tag_has_attrib(&input, cu, n->tag, DW_Attrib_UpperBound)) { + upper_bound = dw_u64_from_attrib(&input, cu, n->tag, DW_Attrib_UpperBound); + // turn upper bound into exclusive range + upper_bound += 1; + } else { + // zero size array + } + + t->count = upper_bound - lower_bound; + ++subrange_count; + } + + Assert(t->direct_type == 0); + t->direct_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + + visit_children = 0; + } break; + case DW_Tag_SubrangeType: { // TODO: error handling - AssertAlways(!"unexpected parent tag"); - } - - RDIM_Type *parent = tag_stack->next->type; - RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, parent->udt); - member->kind = RDI_MemberKind_Base; - member->type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - member->off = safe_cast_u32(dw_const_u32_from_attrib(&input, cu, tag, DW_Attrib_DataMemberLocation)); - } break; - case DW_Tag_Enumerator: { - DW_TagNode *parent_node = tag_stack->next->cur_node; - if (parent_node->tag.kind != DW_Tag_EnumerationType) { - // TODO: error handling - AssertAlways(!"unexpected parent tag"); - } - - RDIM_Type *type = tag_stack->next->type; - RDIM_UDTEnumVal *member = rdim_udt_push_enum_val(arena, &udts, type->udt); - member->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - member->val = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_ConstValue); - } break; - case DW_Tag_Member: { - DW_TagNode *parent_node = tag_stack->next->cur_node; - if (parent_node->tag.kind != DW_Tag_StructureType && - parent_node->tag.kind != DW_Tag_ClassType && - parent_node->tag.kind != DW_Tag_UnionType && - parent_node->tag.kind != DW_Tag_EnumerationType) { - // TODO: error handling - AssertAlways(!"unexpected parent tag"); - } - - DW_Attrib *data_member_location = dw_attrib_from_tag(&input, cu, tag, DW_Attrib_DataMemberLocation); - DW_AttribClass data_member_location_class = dw_value_class_from_attrib(cu, data_member_location); - if (data_member_location_class == DW_AttribClass_LocList) { - AssertAlways(!"UDT member with multiple locations are not supported"); - } - - RDIM_Type *type = tag_stack->next->type; - RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, type->udt); - member->kind = RDI_MemberKind_DataField; - member->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - member->type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - member->off = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_DataMemberLocation); - } break; - case DW_Tag_SubProgram: { - DW_InlKind inl = dw_u64_from_attrib(&input, cu, tag, DW_Attrib_Inline); - switch (inl) { - case DW_Inl_NotInlined: { + AssertAlways(!"unexpected tag"); + } break; + case DW_Tag_Inheritance: { + DW_TagNode *parent_node = tag_stack->next->cur_node; + if (parent_node->tag.kind != DW_Tag_StructureType && + parent_node->tag.kind != DW_Tag_ClassType) { + // TODO: error handling + AssertAlways(!"unexpected parent tag"); + } + + RDIM_Type *parent = tag_stack->next->type; + RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, parent->udt); + member->kind = RDI_MemberKind_Base; + member->type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + member->off = safe_cast_u32(dw_const_u32_from_attrib(&input, cu, tag, DW_Attrib_DataMemberLocation)); + } break; + case DW_Tag_Enumerator: { + DW_TagNode *parent_node = tag_stack->next->cur_node; + if (parent_node->tag.kind != DW_Tag_EnumerationType) { + // TODO: error handling + AssertAlways(!"unexpected parent tag"); + } + + RDIM_Type *type = tag_stack->next->type; + RDIM_UDTEnumVal *member = rdim_udt_push_enum_val(arena, &udts, type->udt); + member->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + member->val = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_ConstValue); + } break; + case DW_Tag_Member: { + DW_TagNode *parent_node = tag_stack->next->cur_node; + if (parent_node->tag.kind != DW_Tag_StructureType && + parent_node->tag.kind != DW_Tag_ClassType && + parent_node->tag.kind != DW_Tag_UnionType && + parent_node->tag.kind != DW_Tag_EnumerationType) { + // TODO: error handling + AssertAlways(!"unexpected parent tag"); + } + + DW_Attrib *data_member_location = dw_attrib_from_tag(&input, cu, tag, DW_Attrib_DataMemberLocation); + DW_AttribClass data_member_location_class = dw_value_class_from_attrib(cu, data_member_location); + if (data_member_location_class == DW_AttribClass_LocList) { + AssertAlways(!"UDT member with multiple locations are not supported"); + } + + RDIM_Type *type = tag_stack->next->type; + RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, type->udt); + member->kind = RDI_MemberKind_DataField; + member->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + member->type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + member->off = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_DataMemberLocation); + } break; + case DW_Tag_SubProgram: { + DW_InlKind inl = dw_u64_from_attrib(&input, cu, tag, DW_Attrib_Inline); + switch (inl) { + case DW_Inl_NotInlined: { + U64 param_count = 0; + RDIM_Type **params = d2r_collect_proc_params(arena, type_table, &input, cu, cur_node, ¶m_count); + + // get return type + RDIM_Type *ret_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + + // fill out proc type + RDIM_Type *proc_type = d2r_create_type(arena, type_table); + proc_type->kind = RDI_TypeKind_Function; + proc_type->byte_size = arch_addr_size; + proc_type->direct_type = ret_type; + proc_type->count = param_count; + proc_type->param_types = params; + + // get container type + RDIM_Type *container_type = 0; + if (dw_tag_has_attrib(&input, cu, tag, DW_Attrib_ContainingType)) { + container_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_ContainingType); + } + + // get frame base expression + String8 frame_base_expr = dw_exprloc_from_attrib(&input, cu, tag, DW_Attrib_FrameBase); + + // get proc container symbol + RDIM_Symbol *proc = rdim_symbol_chunk_list_push(arena, &procs, PROC_CHUNK_CAP ); + + // make scope + Rng1U64List ranges = d2r_range_list_from_tag(comp_temp.arena, &input, cu, image_base, tag); + RDIM_Scope *root_scope = d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, tag_stack, ranges); + root_scope->symbol = proc; + + // fill out proc + proc->is_extern = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_External); + proc->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + proc->link_name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_LinkageName); + proc->type = proc_type; + proc->container_symbol = 0; + proc->container_type = container_type; + proc->root_scope = root_scope; + proc->frame_base = d2r_locset_from_attrib(arena, &input, cu, &scopes, root_scope, image_base, arch, tag, DW_Attrib_FrameBase); + + // sub program with user-defined parent tag is a method + DW_TagKind parent_tag_kind = tag_stack->next->cur_node->tag.kind; + if (parent_tag_kind == DW_Tag_ClassType || parent_tag_kind == DW_Tag_StructureType) { + RDI_MemberKind member_kind = RDI_MemberKind_NULL; + DW_VirtualityKind virtuality = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_Virtuality); + switch (virtuality) { + case DW_VirtualityKind_None: member_kind = RDI_MemberKind_Method; break; + case DW_VirtualityKind_Virtual: member_kind = RDI_MemberKind_VirtualMethod; break; + case DW_VirtualityKind_PureVirtual: member_kind = RDI_MemberKind_VirtualMethod; break; // TODO: create kind for pure virutal + //default: InvalidPath; break; + } + + RDIM_Type *type = tag_stack->next->type; + RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, type->udt); + member->kind = member_kind; + member->type = type; + member->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + } else if (parent_tag_kind != DW_Tag_CompileUnit) { + //AssertAlways(!"unexpected tag"); + } + + tag_stack->scope = root_scope; + } break; + case DW_Inl_DeclaredNotInlined: + case DW_Inl_DeclaredInlined: + case DW_Inl_Inlined: { + visit_children = 0; + } break; + default: InvalidPath; break; + } + } break; + case DW_Tag_InlinedSubroutine: { U64 param_count = 0; - RDIM_Type **params = d2r_collect_proc_params(arena, type_table, &input, cu, cur_node, ¶m_count); - + RDIM_Type **params = d2r_collect_proc_params(arena, type_table, &input, cu, tag_stack->cur_node, ¶m_count); + // get return type RDIM_Type *ret_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - + // fill out proc type RDIM_Type *proc_type = d2r_create_type(arena, type_table); proc_type->kind = RDI_TypeKind_Function; @@ -1569,159 +1887,97 @@ d2r_convert(Arena *arena, D2R_User2Convert *in) proc_type->direct_type = ret_type; proc_type->count = param_count; proc_type->param_types = params; - + // get container type - RDIM_Type *container_type = 0; + RDIM_Type *owner = 0; if (dw_tag_has_attrib(&input, cu, tag, DW_Attrib_ContainingType)) { - container_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_ContainingType); + owner = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_ContainingType); } - - // get frame base expression - String8 frame_base_expr = dw_exprloc_from_attrib(&input, cu, tag, DW_Attrib_FrameBase); - - // get proc container symbol - RDIM_Symbol *proc = rdim_symbol_chunk_list_push(arena, &procs, PROC_CHUNK_CAP ); - + + // fill out inline site + RDIM_InlineSite *inline_site = rdim_inline_site_chunk_list_push(arena, &inline_sites, INLINE_SITE_CHUNK_CAP); + inline_site->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + inline_site->type = proc_type; + inline_site->owner = owner; + inline_site->line_table = 0; + // make scope Rng1U64List ranges = d2r_range_list_from_tag(comp_temp.arena, &input, cu, image_base, tag); RDIM_Scope *root_scope = d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, tag_stack, ranges); - root_scope->symbol = proc; - - // fill out proc - proc->is_extern = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_External); - proc->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - proc->link_name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_LinkageName); - proc->type = proc_type; - proc->container_symbol = 0; - proc->container_type = container_type; - proc->root_scope = root_scope; - proc->frame_base = d2r_locset_from_attrib(arena, &input, cu, &scopes, root_scope, image_base, cu->address_size, arch_rdi, cu->addr_lu, tag, DW_Attrib_FrameBase); - - // sub program with user-defined parent tag is a method + root_scope->inline_site = inline_site; + } break; + case DW_Tag_Variable: { + String8 name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + RDIM_Type *type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + DW_TagKind parent_tag_kind = tag_stack->next->cur_node->tag.kind; - if (parent_tag_kind == DW_Tag_ClassType || parent_tag_kind == DW_Tag_StructureType) { - RDI_MemberKind member_kind = RDI_MemberKind_NULL; - DW_VirtualityKind virtuality = dw_const_u64_from_attrib(&input, cu, tag, DW_Attrib_Virtuality); - switch (virtuality) { - case DW_VirtualityKind_None: member_kind = RDI_MemberKind_Method; break; - case DW_VirtualityKind_Virtual: member_kind = RDI_MemberKind_VirtualMethod; break; - case DW_VirtualityKind_PureVirtual: member_kind = RDI_MemberKind_VirtualMethod; break; // TODO: create kind for pure virutal - default: InvalidPath; break; + if (parent_tag_kind == DW_Tag_SubProgram || + parent_tag_kind == DW_Tag_InlinedSubroutine || + parent_tag_kind == DW_Tag_LexicalBlock) { + RDIM_Scope *scope = tag_stack->next->scope; + RDIM_Local *local = rdim_scope_push_local(arena, &scopes, tag_stack->next->scope); + local->kind = RDI_LocalKind_Variable; + local->name = name; + local->type = type; + local->locset = d2r_var_locset_from_tag(arena, &input, cu, &scopes, scope, image_base, arch, tag); + } else { + + // NOTE: due to a bug in clang in stb_sprint.h local variables + // are declared in global scope without a name + if (name.size == 0) { + break; } - - RDIM_Type *type = tag_stack->next->type; - RDIM_UDTMember *member = rdim_udt_push_member(arena, &udts, type->udt); - member->kind = member_kind; - member->type = type; - member->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - } else if (parent_tag_kind != DW_Tag_CompileUnit) { - AssertAlways(!"unexpected tag"); + + RDIM_Symbol *gvar = rdim_symbol_chunk_list_push(arena, &gvars, GVAR_CHUNK_CAP); + gvar->is_extern = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_External); + gvar->name = name; + gvar->link_name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_LinkageName); + gvar->type = type; + //gvar->locset = d2r_locset_from_attrib(arena, &input, cu, &scopes, global_scope, image_base, arch, tag, DW_Attrib_Location); + gvar->container_symbol = 0; + gvar->container_type = 0; // TODO: NotImplemented; } - - tag_stack->scope = root_scope; } break; - case DW_Inl_DeclaredNotInlined: - case DW_Inl_DeclaredInlined: - case DW_Inl_Inlined: { - visit_children = 0; - } break; - default: InvalidPath; break; - } - } break; - case DW_Tag_InlinedSubroutine: { - U64 param_count = 0; - RDIM_Type **params = d2r_collect_proc_params(arena, type_table, &input, cu, tag_stack->cur_node, ¶m_count); - - // get return type - RDIM_Type *ret_type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - - // fill out proc type - RDIM_Type *proc_type = d2r_create_type(arena, type_table); - proc_type->kind = RDI_TypeKind_Function; - proc_type->byte_size = arch_addr_size; - proc_type->direct_type = ret_type; - proc_type->count = param_count; - proc_type->param_types = params; - - // get container type - RDIM_Type *owner = 0; - if (dw_tag_has_attrib(&input, cu, tag, DW_Attrib_ContainingType)) { - owner = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_ContainingType); - } - - // fill out inline site - RDIM_InlineSite *inline_site = rdim_inline_site_chunk_list_push(arena, &inline_sites, INLINE_SITE_CHUNK_CAP); - inline_site->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - inline_site->type = proc_type; - inline_site->owner = owner; - inline_site->line_table = 0; - - // make scope - Rng1U64List ranges = d2r_range_list_from_tag(comp_temp.arena, &input, cu, image_base, tag); - RDIM_Scope *root_scope = d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, tag_stack, ranges); - root_scope->inline_site = inline_site; - } break; - case DW_Tag_Variable: { - String8 name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - RDIM_Type *type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - - DW_TagKind parent_tag_kind = tag_stack->next->cur_node->tag.kind; - if (parent_tag_kind == DW_Tag_SubProgram || - parent_tag_kind == DW_Tag_InlinedSubroutine || - parent_tag_kind == DW_Tag_LexicalBlock) { - RDIM_Scope *scope = tag_stack->next->scope; - RDIM_Local *local = rdim_scope_push_local(arena, &scopes, tag_stack->next->scope); - local->kind = RDI_LocalKind_Variable; - local->name = name; - local->type = type; - local->locset = d2r_locset_from_attrib(arena, &input, cu, &scopes, scope, image_base, cu->address_size, arch_rdi, cu->addr_lu, tag, DW_Attrib_Location); - } else { - - // NOTE: due to a bug in clang in stb_sprint.h local variables - // are declared in global scope without a name - if (name.size == 0) { - break; + case DW_Tag_FormalParameter: { + DW_TagKind parent_tag_kind = tag_stack->next->cur_node->tag.kind; + if (parent_tag_kind == DW_Tag_SubProgram || parent_tag_kind == DW_Tag_InlinedSubroutine) { + RDIM_Scope *scope = tag_stack->next->scope; + RDIM_Local *param = rdim_scope_push_local(arena, &scopes, scope); + param->kind = RDI_LocalKind_Parameter; + param->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); + param->type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); + param->locset = d2r_var_locset_from_tag(arena, &input, cu, &scopes, scope, image_base, arch, tag); + } else { + // TODO: error handling + AssertAlways(!"this is a local variable"); } - - RDIM_Symbol *gvar = rdim_symbol_chunk_list_push(arena, &gvars, GVAR_CHUNK_CAP); - gvar->is_extern = dw_flag_from_attrib(&input, cu, tag, DW_Attrib_External); - gvar->name = name; - gvar->link_name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_LinkageName); - gvar->type = type; - gvar->offset = 0; // TODO: NotImplemented; - gvar->container_symbol = 0; - gvar->container_type = 0; // TODO: NotImplemented; - } - } break; - case DW_Tag_FormalParameter: { - DW_TagKind parent_tag_kind = tag_stack->next->cur_node->tag.kind; - if (parent_tag_kind == DW_Tag_SubProgram || parent_tag_kind == DW_Tag_InlinedSubroutine) { - RDIM_Scope *scope = tag_stack->next->scope; - RDIM_Local *param = rdim_scope_push_local(arena, &scopes, scope); - param->kind = RDI_LocalKind_Parameter; - param->name = dw_string_from_attrib(&input, cu, tag, DW_Attrib_Name); - param->type = d2r_type_from_attrib(arena, type_table, &input, cu, tag, DW_Attrib_Type); - param->locset = d2r_locset_from_attrib(arena, &input, cu, &scopes, scope, image_base, cu->address_size, arch_rdi, cu->addr_lu, tag, DW_Attrib_Location); - } else { - // TODO: error handling - AssertAlways(!"this is a local variable"); - } - } break; - case DW_Tag_LexicalBlock: { - if (tag_stack->next->cur_node->tag.kind == DW_Tag_SubProgram || - tag_stack->next->cur_node->tag.kind == DW_Tag_InlinedSubroutine || - tag_stack->next->cur_node->tag.kind == DW_Tag_LexicalBlock) { - Rng1U64List ranges = d2r_range_list_from_tag(comp_temp.arena, &input, cu, image_base, tag); - d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, tag_stack, ranges); - } - } break; - case DW_Tag_Label: - case DW_Tag_CompileUnit: - case DW_Tag_UnspecifiedParameters: - break; - default: NotImplemented; break; + } break; + case DW_Tag_LexicalBlock: { + if (tag_stack->next->cur_node->tag.kind == DW_Tag_SubProgram || + tag_stack->next->cur_node->tag.kind == DW_Tag_InlinedSubroutine || + tag_stack->next->cur_node->tag.kind == DW_Tag_LexicalBlock) { + Rng1U64List ranges = d2r_range_list_from_tag(comp_temp.arena, &input, cu, image_base, tag); + d2r_push_scope(arena, &scopes, SCOPE_CHUNK_CAP, tag_stack, ranges); + } + } break; + case DW_Tag_CallSite: { + // TODO + } break; + case DW_Tag_CallSiteParameter: { + // TODO + } break; + case DW_Tag_Label: + case DW_Tag_CompileUnit: + case DW_Tag_UnspecifiedParameters: + break; + case DW_Tag_Namespace: break; + case DW_Tag_ImportedDeclaration: break; + case DW_Tag_PtrToMemberType: break; + case DW_Tag_TemplateTypeParameter: break; + case DW_Tag_ReferenceType: break; + default: NotImplemented; break; } - + if (tag_stack->cur_node->first_child && visit_children) { D2R_TagNode *frame = free_tags; if (frame) { @@ -1736,22 +1992,22 @@ d2r_convert(Arena *arena, D2R_User2Convert *in) tag_stack->cur_node = tag_stack->cur_node->sibling; } } - + // recycle free frame D2R_TagNode *frame = tag_stack; SLLStackPop(tag_stack); SLLStackPush(free_tags, frame); - + if (tag_stack) { tag_stack->cur_node = tag_stack->cur_node->sibling; } } - + temp_end(comp_temp); } - + ProfEnd(); - + { for (RDIM_TypeChunkNode *chunk_n = types.first; chunk_n != 0; chunk_n = chunk_n->next) { for (U64 i = 0; i < chunk_n->count; ++i) { @@ -1767,18 +2023,18 @@ d2r_convert(Arena *arena, D2R_User2Convert *in) } } } - + { RDIM_TypeNode *type_stack = 0; RDIM_TypeNode *free_types = 0; - + for (RDIM_TypeChunkNode *chunk_n = types.first; chunk_n != 0; chunk_n = chunk_n->next) { for (U64 i = 0; i < chunk_n->count; ++i) { RDIM_Type *type = &chunk_n->v[i]; if (type->kind == RDI_TypeKind_Array) { if (type->byte_size != 0) continue; - + RDIM_Type *t; for (t = type; t != 0 && t->kind == RDI_TypeKind_Array; t = t->direct_type) { RDIM_TypeNode *f = free_types; @@ -1790,12 +2046,12 @@ d2r_convert(Arena *arena, D2R_User2Convert *in) f->v = t; SLLStackPush(type_stack, f); } - + U64 base_type_size = 0; if (t) { base_type_size = t->byte_size; } - + U64 array_size = base_type_size; while (type_stack) { if (type_stack->v->count) { @@ -1805,10 +2061,10 @@ d2r_convert(Arena *arena, D2R_User2Convert *in) } SLLStackPop(type_stack); } - + type->count = 0; type->byte_size = array_size; - + // recycle frames free_types = type_stack; type_stack = 0; @@ -1816,126 +2072,49 @@ d2r_convert(Arena *arena, D2R_User2Convert *in) } } } - + //////////////////////////////// - - RDIM_BakeParams *bake_params = push_array(arena, RDIM_BakeParams, 1); - bake_params->top_level_info = top_level_info; - bake_params->binary_sections = binary_sections; - bake_params->units = units; - bake_params->types = types; - bake_params->udts = udts; - bake_params->src_files = src_files; - bake_params->line_tables = line_tables; - bake_params->global_variables = gvars; - bake_params->thread_variables = tvars; - bake_params->procedures = procs; - bake_params->scopes = scopes; - bake_params->inline_sites = inline_sites; - + + RDIM_BakeParams bake_params = {0}; + bake_params.top_level_info = top_level_info; + bake_params.binary_sections = binary_sections; + bake_params.units = units; + bake_params.types = types; + bake_params.udts = udts; + bake_params.src_files = src_files; + bake_params.line_tables = line_tables; + bake_params.global_variables = gvars; + bake_params.thread_variables = tvars; + bake_params.procedures = procs; + bake_params.scopes = scopes; + bake_params.inline_sites = inline_sites; + scratch_end(scratch); return bake_params; } -RDI_PROC void -rdim_assign_type_index(RDIM_Type *type, U64 *type_indices, U64 *curr_type_idx) -{ - RDI_U64 type_pos = rdim_idx_from_type(type); - - if(type->kind == RDI_TypeKind_NULL) - { - type_indices[type_pos] = 0; - return; - } - - if(type_indices[type_pos] == 0) - { - if(type->param_types) - { - for(RDI_U64 param_idx = 0; param_idx < type->count; param_idx += 1) - { - rdim_assign_type_index(type->param_types[param_idx], type_indices, curr_type_idx); - } - } - - if(type->direct_type) - { - rdim_assign_type_index(type->direct_type, type_indices, curr_type_idx); - } - - type_indices[type_pos] = *curr_type_idx; - *curr_type_idx += 1; - } -} - -RDI_PROC RDI_U64 * -rdim_make_type_indices(RDIM_Arena *arena, RDIM_TypeChunkList *types) -{ - ProfBeginFunction(); - - RDI_U64 *type_indices = rdim_push_array(arena, RDI_U64, types->total_count + 1); - RDI_U64 type_indices_count = 1; - - for(RDIM_TypeChunkNode *chunk = types->first; chunk != 0; chunk = chunk->next) - { - for(RDI_U64 i = 0; i < chunk->count; i += 1) - { - rdim_assign_type_index(&chunk->v[i], type_indices, &type_indices_count); - } - } - - ProfEnd(); - return type_indices; -} - -internal RDIM_BakeResults -d2r_bake(RDIM_LocalState *state, RDIM_BakeParams *in_params) -{ - //////////////////////////////// - // resolve incomplete types - - rdim_local_resolve_incomplete_types(&in_params->types, &in_params->udts); - - //////////////////////////////// - // compute type indices - - RDI_U64 *type_indices = rdim_make_type_indices(scratch.arena, &in_params->types); - - // using type indices create a correct type array layout - NotImplemented; - - return rdim_bake(state, in_params); -} - -internal RDIM_SerializedSectionBundle -d2r_compress(Arena *arena, RDIM_SerializedSectionBundle in) -{ - RDIM_SerializedSectionBundle result = {0}; - return result; -} - internal RDI_Language rdi_language_from_dw_language(DW_Language v) { RDI_Language result = RDI_Language_NULL; switch (v) { - case DW_Language_Null: result = RDI_Language_NULL; break; - - case DW_Language_C89: - case DW_Language_C99: - case DW_Language_C11: - case DW_Language_C: + case DW_Language_Null: result = RDI_Language_NULL; break; + + case DW_Language_C89: + case DW_Language_C99: + case DW_Language_C11: + case DW_Language_C: result = RDI_Language_C; break; - - case DW_Language_CPlusPlus03: - case DW_Language_CPlusPlus11: - case DW_Language_CPlusPlus14: - case DW_Language_CPlusPlus: + + case DW_Language_CPlusPlus03: + case DW_Language_CPlusPlus11: + case DW_Language_CPlusPlus14: + case DW_Language_CPlusPlus: result = RDI_Language_CPlusPlus; break; - - default: NotImplemented; break; + + default: NotImplemented; break; } return result; } @@ -1948,7 +2127,7 @@ rdi_reg_from_dw_reg_x86(DW_RegX86 v) #define X(reg_dw, val_dw, reg_rdi, ...) case DW_RegX86_##reg_dw: result = RDI_RegCodeX86_##reg_rdi; break; DW_Regs_X86_XList(X) #undef X - default: NotImplemented; break; + default: NotImplemented; break; } return result; } @@ -1961,7 +2140,7 @@ rdi_reg_from_dw_reg_x64(DW_RegX64 v, RDI_RegCodeX64 *code_out, U64 *off_out, U64 #define X(reg_dw, val_dw, reg_rdi, off, size) case DW_RegX64_##reg_dw: result = RDI_RegCodeX64_##reg_rdi; *off_out = off; *size_out = size; break; DW_Regs_X64_XList(X) #undef X - default: NotImplemented; break; + default: NotImplemented; break; } return result; } @@ -1971,11 +2150,10 @@ rdi_reg_from_dw_reg(Arch arch, DW_Reg v, RDI_RegCode *code_out, U64 *off_out, U6 { RDI_RegCode result = RDI_RegCode_nil; switch (arch) { - case Arch_Null: break; - case Arch_x86: ; break; - case Arch_x64: return rdi_reg_from_dw_reg_x64(v, code_out, off_out, size_out); - default: NotImplemented; break; + case Arch_Null: break; + case Arch_x86: ; break; + case Arch_x64: return rdi_reg_from_dw_reg_x64(v, code_out, off_out, size_out); + default: NotImplemented; break; } return 0; } - diff --git a/src/rdi_from_dwarf/rdi_from_dwarf.h b/src/rdi_from_dwarf/rdi_from_dwarf.h index 4f59fb27..1831367c 100644 --- a/src/rdi_from_dwarf/rdi_from_dwarf.h +++ b/src/rdi_from_dwarf/rdi_from_dwarf.h @@ -1,34 +1,25 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once -typedef U64 D2R_ConvertFlags; -enum +typedef struct D2R_ConvertParams D2R_ConvertParams; +struct D2R_ConvertParams { -#define X(t,n,k) D2R_ConvertFlag_##t = (1ull << RDI_SectionKind_##t), - RDI_SectionKind_XList -#undef X - D2R_ConvertFlag_StrictParse, + String8 dbg_name; + String8 dbg_data; + String8 exe_name; + String8 exe_data; + ExecutableImageKind exe_kind; + RDIM_SubsetFlags subset_flags; + B32 deterministic; }; -typedef struct D2R_User2Convert -{ - String8 input_exe_name; - String8 input_exe_data; - String8 input_debug_name; - String8 input_debug_data; - String8 output_name; - D2R_ConvertFlags flags; - String8List errors; -} D2R_User2Convert; - typedef struct D2R_TypeTable { HashTable *ht; RDIM_TypeChunkList *types; U64 type_chunk_cap; - RDIM_Type *void_type; RDIM_Type *varg_type; } D2R_TypeTable; @@ -42,28 +33,18 @@ typedef struct D2R_TagNode typedef struct D2R_CompUnitContribMap { - U64 count; - U64 *info_off_arr; - RDIM_Rng1U64List *voff_range_arr; + U64 count; + U64 *info_off_arr; + RDIM_Rng1U64ChunkList *voff_range_arr; } D2R_CompUnitContribMap; //////////////////////////////// -// Command Line -> Conversion Inputs -internal D2R_User2Convert * d2r_user2convert_from_cmdln(Arena *arena, CmdLine *cmdline); +internal RDIM_BakeParams d2r_convert(Arena *arena, ASYNC_Root *async_root, D2R_ConvertParams *params); //////////////////////////////// -// Top-Level Conversion Entry Point - -internal RDIM_BakeParams * d2r_convert (Arena *arena, D2R_User2Convert *in); -internal RDIM_BakeResults d2r_bake (RDIM_LocalState *state, RDIM_BakeParams *in); -internal RDIM_SerializedSectionBundle d2r_compress(Arena *arena, RDIM_SerializedSectionBundle in); - -//////////////////////////////// -// Enum Conversion internal RDI_Language rdi_language_from_dw_language(DW_Language v); internal RDI_RegCodeX86 rdi_reg_from_dw_reg_x86(DW_RegX86 v); internal B32 rdi_reg_from_dw_reg_x64(DW_RegX64 v, RDI_RegCodeX64 *code_out, U64 *off_out, U64 *size_out); internal B32 rdi_reg_from_dw_reg(Arch arch, DW_Reg v, RDI_RegCode *code_out, U64 *off_out, U64 *size_out); - diff --git a/src/rdi_from_dwarf/rdi_from_dwarf_main.c b/src/rdi_from_dwarf/rdi_from_dwarf_main.c deleted file mode 100644 index a74e3b15..00000000 --- a/src/rdi_from_dwarf/rdi_from_dwarf_main.c +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -#define BUILD_TITLE "Epic Games Tools (R) DWARF Converter" -#define BUILD_CONSOLE_INTERFACE 1 - -//////////////////////////////// - -#include "third_party/rad_lzb_simple/rad_lzb_simple.h" -#include "third_party/rad_lzb_simple/rad_lzb_simple.c" -#include "third_party/xxHash/xxhash.c" -#include "third_party/xxHash/xxhash.h" -#include "third_party/radsort/radsort.h" - -//////////////////////////////// - -#include "lib_rdi_format/rdi_format.h" -#include "lib_rdi_format/rdi_format.c" -#include "lib_rdi_format/rdi_format_parse.h" -#include "lib_rdi_format/rdi_format_parse.c" - -//////////////////////////////// - -#include "base/base_inc.h" -#include "os/os_inc.h" -#include "async/async.h" -#include "rdi_make/rdi_make_local.h" -#include "linker/path_ext/path.h" -#include "linker/hash_table.h" -#include "coff/coff.h" -#include "coff/coff_parse.h" -#include "dwarf/dwarf.h" -#include "dwarf/dwarf_parse.h" -#include "dwarf/dwarf_coff.h" -#include "pe/pe.h" -#include "linker/rdi/rdi_coff.h" -#include "rdi_from_dwarf/rdi_from_dwarf.h" - -#include "base/base_inc.c" -#include "os/os_inc.c" -#include "async/async.c" -#include "coff/coff.c" -#include "coff/coff_parse.c" -#include "pe/pe.c" -#include "rdi_make/rdi_make_local.c" -#include "linker/rdi/rdi_coff.c" -#include "linker/path_ext/path.c" -#include "linker/hash_table.c" -#include "dwarf/dwarf.c" -#include "dwarf/dwarf_parse.c" -#include "dwarf/dwarf_coff.c" -#include "rdi_from_dwarf/rdi_from_dwarf.c" - -//////////////////////////////// -// Entry Point - -internal void -entry_point(CmdLine *cmdline) -{ - // initialize state and unpack command line - Arena *arena = arena_alloc(); - B32 do_help = (cmd_line_has_flag(cmdline, str8_lit("help")) || - cmd_line_has_flag(cmdline, str8_lit("h")) || - cmd_line_has_flag(cmdline, str8_lit("?"))); - - D2R_User2Convert *user2convert = d2r_user2convert_from_cmdln(arena, cmdline); - - // display help - if (do_help) { - fprintf(stderr, "--- rdi_from_dwarf ------------------------------------------------------------\n\n"); - - fprintf(stderr, "This utility converts debug information from DWARF into the RAD Debug Info\n"); - fprintf(stderr, "format. The following arguments are accepted:\n\n"); - - fprintf(stderr, "--exe: [optional] Specifies the path of the executable filefor which the\n"); - fprintf(stderr, " debug info was generated.\n"); - fprintf(stderr, "--debug: Specifies the path of the .DEBUG debug info file to\n"); - fprintf(stderr, " convert.\n"); - fprintf(stderr, "--out: Specifies the path at which the output will be written.\n\n"); - - if (!do_help) { - for (String8Node *n = user2convert->errors.first; n != 0; n = n->next) { - fprintf(stderr, "error(input): %.*s\n", str8_varg(n->string)); - } - } - - os_abort(0); - } - - RDIM_LocalState *rdim_local_state = rdim_local_init(); - - ProfBegin("convert"); - RDIM_BakeParams *convert2bake = d2r_convert(arena, user2convert); - ProfEnd(); - - ProfBegin("bake"); - RDIM_BakeResults bake2srlz = d2r_bake(rdim_local_state, convert2bake); - ProfEnd(); - - ProfBegin("serialize bake"); - RDIM_SerializedSectionBundle srlz2file = rdim_serialized_section_bundle_from_bake_results(&bake2srlz); - ProfEnd(); - - RDIM_SerializedSectionBundle srlz2file_compressed = srlz2file; - if (cmd_line_has_flag(cmdline, str8_lit("compress"))) { - ProfBegin("compress"); - srlz2file_compressed = d2r_compress(arena, srlz2file); - ProfEnd(); - } - - ProfBegin("serialize blobs"); - String8List blobs = rdim_file_blobs_from_section_bundle(arena, &srlz2file_compressed); - ProfEnd(); - - ProfBegin("write"); - if (!os_write_data_list_to_file_path(user2convert->output_name, blobs)) { - fprintf(stderr, "error(ouptut): unable to write to %.*s\n", str8_varg(user2convert->output_name)); - } - ProfEnd(); -} - diff --git a/src/rdi_from_elf/rdi_from_elf.c b/src/rdi_from_elf/rdi_from_elf.c new file mode 100644 index 00000000..ccbb1351 --- /dev/null +++ b/src/rdi_from_elf/rdi_from_elf.c @@ -0,0 +1,9 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +internal RDIM_BinarySectionList +e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, ELF_Shdr64Array shdrs) +{ + RDIM_BinarySectionList result = {0}; + return result; +} diff --git a/src/rdi_from_elf/rdi_from_elf.h b/src/rdi_from_elf/rdi_from_elf.h new file mode 100644 index 00000000..3d979c8f --- /dev/null +++ b/src/rdi_from_elf/rdi_from_elf.h @@ -0,0 +1,9 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef RDI_FROM_ELF_H +#define RDI_FROM_ELF_H + +internal RDIM_BinarySectionList e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, ELF_Shdr64Array shdrs); + +#endif // RDI_FROM_ELF_H diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index a15b21cb..66b15cba 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) // TODO(rjf): eliminate redundant null checks, just always allocate @@ -40,11 +40,12 @@ p2r_hash_from_voff(U64 voff) //////////////////////////////// //~ rjf: Command Line -> Conversion Inputs - -internal P2R_User2Convert * + +#if 0 +internal P2R_ConvertParams * p2r_user2convert_from_cmdln(Arena *arena, CmdLine *cmdline) { - P2R_User2Convert *result = push_array(arena, P2R_User2Convert, 1); + P2R_ConvertParams *result = push_array(arena, P2R_ConvertParams, 1); //- rjf: get input pdb { @@ -152,7 +153,8 @@ Case("source_path_name_map",NormalSourcePathNameMap)\ #undef FlagNameMapXList return result; -} +} +#endif //////////////////////////////// //~ rjf: COFF <-> RDI Canonical Conversions @@ -503,7 +505,7 @@ p2r_location_over_lvar_addr_range(Arena *arena, RDIM_ScopeChunkList *scopes, RDI ASYNC_WORK_DEF(p2r_exe_hash_work) { ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(p2r_async_root); P2R_EXEHashIn *in = (P2R_EXEHashIn *)input; U64 *out = push_array(arena, U64, 1); ProfScope("hash exe") *out = rdi_hash(in->exe_data.str, in->exe_data.size); @@ -514,7 +516,7 @@ ASYNC_WORK_DEF(p2r_exe_hash_work) ASYNC_WORK_DEF(p2r_tpi_hash_parse_work) { ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(p2r_async_root); P2R_TPIHashParseIn *in = (P2R_TPIHashParseIn *)input; void *out = 0; ProfScope("parse tpi hash") out = pdb_tpi_hash_from_data(arena, in->strtbl, in->tpi, in->hash_data, in->aux_data); @@ -525,7 +527,7 @@ ASYNC_WORK_DEF(p2r_tpi_hash_parse_work) ASYNC_WORK_DEF(p2r_tpi_leaf_parse_work) { ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(p2r_async_root); P2R_TPILeafParseIn *in = (P2R_TPILeafParseIn *)input; void *out = 0; ProfScope("parse tpi leaf") out = cv_leaf_from_data(arena, in->leaf_data, in->itype_first); @@ -536,7 +538,7 @@ ASYNC_WORK_DEF(p2r_tpi_leaf_parse_work) ASYNC_WORK_DEF(p2r_symbol_stream_parse_work) { ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(p2r_async_root); P2R_SymbolStreamParseIn *in = (P2R_SymbolStreamParseIn *)input; void *out = 0; ProfScope("parse symbol stream") out = cv_sym_from_data(arena, in->data, 4); @@ -547,7 +549,7 @@ ASYNC_WORK_DEF(p2r_symbol_stream_parse_work) ASYNC_WORK_DEF(p2r_c13_stream_parse_work) { ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(p2r_async_root); P2R_C13StreamParseIn *in = (P2R_C13StreamParseIn *)input; void *out = 0; ProfScope("parse c13 stream") out = cv_c13_parsed_from_data(arena, in->data, in->strtbl, in->coff_sections); @@ -558,7 +560,7 @@ ASYNC_WORK_DEF(p2r_c13_stream_parse_work) ASYNC_WORK_DEF(p2r_comp_unit_parse_work) { ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(p2r_async_root); P2R_CompUnitParseIn *in = (P2R_CompUnitParseIn *)input; void *out = 0; ProfScope("parse comp units") out = pdb_comp_unit_array_from_data(arena, in->data); @@ -569,177 +571,121 @@ ASYNC_WORK_DEF(p2r_comp_unit_parse_work) ASYNC_WORK_DEF(p2r_comp_unit_contributions_parse_work) { ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(p2r_async_root); P2R_CompUnitContributionsParseIn *in = (P2R_CompUnitContributionsParseIn *)input; void *out = 0; ProfScope("parse comp unit contributions") out = pdb_comp_unit_contribution_array_from_data(arena, in->data, in->coff_sections); ProfEnd(); return out; -} +} + +ASYNC_WORK_DEF(p2r_comp_unit_contributions_bucket_work) +{ + ProfBeginFunction(); + Arena *arena = async_root_thread_arena(p2r_async_root); + P2R_CompUnitContributionsBucketIn *in = (P2R_CompUnitContributionsBucketIn *)input; + P2R_CompUnitContributionsBucketOut *out = push_array(arena, P2R_CompUnitContributionsBucketOut, 1); + { + out->unit_ranges = push_array(arena, RDIM_Rng1U64ChunkList, in->comp_unit_count); + for(U64 idx = 0; idx < in->contributions.count; idx += 1) + { + PDB_CompUnitContribution *contribution = &in->contributions.contributions[idx]; + if(contribution->mod < in->comp_unit_count) + { + RDIM_Rng1U64 r = {contribution->voff_first, contribution->voff_opl}; + rdim_rng1u64_chunk_list_push(arena, &out->unit_ranges[contribution->mod], 256, r); + } + } + } + ProfEnd(); + return out; +} //////////////////////////////// -//~ rjf: Unit Conversion Tasks +//~ rjf: Unit Source File Gathering Tasks -ASYNC_WORK_DEF(p2r_units_convert_work) +ASYNC_WORK_DEF(p2r_gather_unit_src_file_work) { ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(p2r_async_root); Temp scratch = scratch_begin(&arena, 1); - P2R_UnitConvertIn *in = (P2R_UnitConvertIn *)input; - P2R_UnitConvertOut *out = push_array(arena, P2R_UnitConvertOut, 1); - ProfScope("build units, initial src file map, & collect unit source files") - if(in->comp_units != 0) + P2R_GatherUnitSrcFilesIn *in = (P2R_GatherUnitSrcFilesIn *)input; + P2R_GatherUnitSrcFilesOut *out = push_array(arena, P2R_GatherUnitSrcFilesOut, 1); + PDB_CompUnit *pdb_unit = in->comp_unit; + CV_SymParsed *pdb_unit_sym = in->comp_unit_syms; + CV_C13Parsed *pdb_unit_c13 = in->comp_unit_c13s; + CV_RecRange *rec_ranges_first = pdb_unit_sym->sym_ranges.ranges; + CV_RecRange *rec_ranges_opl = rec_ranges_first+pdb_unit_sym->sym_ranges.count; + String8List src_file_paths = {0}; { - U64 units_chunk_cap = in->comp_units->count; - P2R_SrcFileMap src_file_map = {0}; - src_file_map.slots_count = 65536; - src_file_map.slots = push_array(scratch.arena, P2R_SrcFileNode *, src_file_map.slots_count); + //- rjf: build local hash table to dedup files within this unit + U64 hit_path_slots_count = 4096; + String8Node **hit_path_slots = push_array(scratch.arena, String8Node *, hit_path_slots_count); - //////////////////////////// - //- rjf: pass 1: build per-unit info & per-unit line tables - // - ProfScope("pass 1: build per-unit info & per-unit line tables") - for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) + //- rjf: produce obj name/path + String8 obj_name = pdb_unit->obj_name; + if(str8_match(obj_name, str8_lit("* Linker *"), 0) || + str8_match(obj_name, str8_lit("Import:"), StringMatchFlag_RightSideSloppy)) { - PDB_CompUnit *pdb_unit = in->comp_units->units[comp_unit_idx]; - CV_SymParsed *pdb_unit_sym = in->comp_unit_syms[comp_unit_idx]; - CV_C13Parsed *pdb_unit_c13 = in->comp_unit_c13s[comp_unit_idx]; - - //- rjf: produce unit name - String8 unit_name = pdb_unit->obj_name; - if(unit_name.size != 0) - { - String8 unit_name_past_last_slash = str8_skip_last_slash(unit_name); - if(unit_name_past_last_slash.size != 0) - { - unit_name = unit_name_past_last_slash; - } - } - - //- rjf: produce obj name/path - String8 obj_name = pdb_unit->obj_name; - if(str8_match(obj_name, str8_lit("* Linker *"), 0) || - str8_match(obj_name, str8_lit("Import:"), StringMatchFlag_RightSideSloppy)) - { - MemoryZeroStruct(&obj_name); - } - String8 obj_folder_path = lower_from_str8(scratch.arena, str8_chop_last_slash(obj_name)); - - //- rjf: build this unit's line table, fill out primary line info (inline info added after) - RDIM_LineTable *line_table = 0; + MemoryZeroStruct(&obj_name); + } + String8 obj_folder_path = lower_from_str8(scratch.arena, str8_chop_last_slash(obj_name)); + + //- rjf: find all files in this unit's (non-inline) line info + ProfScope("find all files in this unit's (non-inline) line info") for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; node != 0; node = node->next) + { + if(node->kind == CV_C13SubSectionKind_Lines) { - if(node->kind == CV_C13SubSectionKind_Lines) + for(CV_C13LinesParsedNode *lines_n = node->lines_first; + lines_n != 0; + lines_n = lines_n->next) { - for(CV_C13LinesParsedNode *lines_n = node->lines_first; - lines_n != 0; - lines_n = lines_n->next) + // rjf: file name -> normalized file path + String8 file_path = lines_n->v.file_name; + String8 file_path_normalized = lower_from_str8(scratch.arena, str8_skip_chop_whitespace(file_path)); { - CV_C13LinesParsed *lines = &lines_n->v; - - // rjf: file name -> normalized file path - String8 file_path = lines->file_name; - String8 file_path_normalized = lower_from_str8(scratch.arena, str8_skip_chop_whitespace(file_path)); + PathStyle file_path_normalized_style = path_style_from_str8(file_path_normalized); + String8List file_path_normalized_parts = str8_split_path(scratch.arena, file_path_normalized); + if(file_path_normalized_style == PathStyle_Relative) { - PathStyle file_path_normalized_style = path_style_from_str8(file_path_normalized); - String8List file_path_normalized_parts = str8_split_path(scratch.arena, file_path_normalized); - if(file_path_normalized_style == PathStyle_Relative) - { - String8List obj_folder_path_parts = str8_split_path(scratch.arena, obj_folder_path); - str8_list_concat_in_place(&obj_folder_path_parts, &file_path_normalized_parts); - file_path_normalized_parts = obj_folder_path_parts; - file_path_normalized_style = path_style_from_str8(obj_folder_path); - } - str8_path_list_resolve_dots_in_place(&file_path_normalized_parts, file_path_normalized_style); - file_path_normalized = str8_path_list_join_by_style(scratch.arena, &file_path_normalized_parts, file_path_normalized_style); + String8List obj_folder_path_parts = str8_split_path(scratch.arena, obj_folder_path); + str8_list_concat_in_place(&obj_folder_path_parts, &file_path_normalized_parts); + file_path_normalized_parts = obj_folder_path_parts; + file_path_normalized_style = path_style_from_str8(obj_folder_path); } - - // rjf: normalized file path -> source file node - U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); - U64 src_file_slot = file_path_normalized_hash%src_file_map.slots_count; - P2R_SrcFileNode *src_file_node = 0; - for(P2R_SrcFileNode *n = src_file_map.slots[src_file_slot]; n != 0; n = n->next) + str8_path_list_resolve_dots_in_place(&file_path_normalized_parts, file_path_normalized_style); + file_path_normalized = str8_path_list_join_by_style(scratch.arena, &file_path_normalized_parts, file_path_normalized_style); + } + + // rjf: normalized file path -> source file node + U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); + U64 hit_path_slot = file_path_normalized_hash%hit_path_slots_count; + String8Node *hit_path_node = 0; + for(String8Node *n = hit_path_slots[hit_path_slot]; n != 0; n = n->next) + { + if(str8_match(n->string, file_path_normalized, 0)) { - if(str8_match(n->src_file->normal_full_path, file_path_normalized, 0)) - { - src_file_node = n; - break; - } - } - if(src_file_node == 0) - { - src_file_node = push_array(scratch.arena, P2R_SrcFileNode, 1); - SLLStackPush(src_file_map.slots[src_file_slot], src_file_node); - src_file_node->src_file = rdim_src_file_chunk_list_push(arena, &out->src_files, 4096); - src_file_node->src_file->normal_full_path = push_str8_copy(arena, file_path_normalized); - } - - // rjf: push sequence into both line table & source file's line map - if(lines->line_count != 0) - { - if(line_table == 0) - { - line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 256); - } - RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, lines->voffs, lines->line_nums, lines->col_nums, lines->line_count); - rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); + hit_path_node = n; + break; } } + if(hit_path_node == 0) + { + hit_path_node = push_array(scratch.arena, String8Node, 1); + SLLStackPush(hit_path_slots[hit_path_slot], hit_path_node); + hit_path_node->string = file_path_normalized; + str8_list_push(scratch.arena, &src_file_paths, push_str8_copy(arena, file_path_normalized)); + } } } - - //- rjf: build unit - RDIM_Unit *dst_unit = rdim_unit_chunk_list_push(arena, &out->units, units_chunk_cap); - dst_unit->unit_name = unit_name; - dst_unit->compiler_name = pdb_unit_sym->info.compiler_name; - dst_unit->object_file = obj_name; - dst_unit->archive_file = pdb_unit->group_name; - dst_unit->language = p2r_rdi_language_from_cv_language(pdb_unit_sym->info.language); - dst_unit->line_table = line_table; } - //////////////////////////// - //- rjf: pass 2: build per-unit voff ranges from comp unit contributions table - // - PDB_CompUnitContribution *contrib_ptr = in->comp_unit_contributions->contributions; - PDB_CompUnitContribution *contrib_opl = contrib_ptr + in->comp_unit_contributions->count; - ProfScope("pass 2: build per-unit voff ranges from comp unit contributions table") - for(;contrib_ptr < contrib_opl; contrib_ptr += 1) + //- rjf: find all files in unit's inline line info + ProfScope("find all files in unit's inline line info") { - if(contrib_ptr->mod < in->comp_units->count) - { - RDIM_Unit *unit = &out->units.first->v[contrib_ptr->mod]; - RDIM_Rng1U64 range = {contrib_ptr->voff_first, contrib_ptr->voff_opl}; - rdim_rng1u64_list_push(arena, &unit->voff_ranges, range); - } - } - - //////////////////////////// - //- rjf: pass 3: parse all inlinee line tables - // - out->units_first_inline_site_line_tables = push_array(arena, RDIM_LineTable *, in->comp_units->count); - ProfScope("pass 3: parse all inlinee line tables") - for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) - { - //- rjf: unpack unit - PDB_CompUnit *pdb_unit = in->comp_units->units[comp_unit_idx]; - CV_SymParsed *unit_sym = in->comp_unit_syms[comp_unit_idx]; - CV_C13Parsed *unit_c13 = in->comp_unit_c13s[comp_unit_idx]; - CV_RecRange *rec_ranges_first = unit_sym->sym_ranges.ranges; - CV_RecRange *rec_ranges_opl = rec_ranges_first+unit_sym->sym_ranges.count; - - //- rjf: produce obj name/path - String8 obj_name = pdb_unit->obj_name; - if(str8_match(obj_name, str8_lit("* Linker *"), 0) || - str8_match(obj_name, str8_lit("Import:"), StringMatchFlag_RightSideSloppy)) - { - MemoryZeroStruct(&obj_name); - } - String8 obj_folder_path = lower_from_str8(scratch.arena, str8_chop_last_slash(obj_name)); - - //- rjf: parse inlinee line tables U64 base_voff = 0; for(CV_RecRange *rec_range = rec_ranges_first; rec_range < rec_ranges_opl; @@ -750,7 +696,7 @@ ASYNC_WORK_DEF(p2r_units_convert_work) U64 sym_off_opl = rec_range->off + rec_range->hdr.size; //- rjf: skip invalid ranges - if(sym_off_opl > unit_sym->data.size || sym_off_first > unit_sym->data.size || sym_off_first > sym_off_opl) + if(sym_off_opl > pdb_unit_sym->data.size || sym_off_first > pdb_unit_sym->data.size || sym_off_first > sym_off_opl) { continue; } @@ -758,8 +704,8 @@ ASYNC_WORK_DEF(p2r_units_convert_work) //- rjf: unpack symbol info CV_SymKind kind = rec_range->hdr.kind; U64 sym_header_struct_size = cv_header_struct_size_from_sym_kind(kind); - void *sym_header_struct_base = unit_sym->data.str + sym_off_first; - void *sym_data_opl = unit_sym->data.str + sym_off_opl; + void *sym_header_struct_base = pdb_unit_sym->data.str + sym_off_first; + void *sym_data_opl = pdb_unit_sym->data.str + sym_off_opl; //- rjf: skip bad sizes if(sym_off_first + sym_header_struct_size > sym_off_opl) @@ -795,8 +741,8 @@ ASYNC_WORK_DEF(p2r_units_convert_work) CV_C13InlineeLinesParsed *inlinee_lines_parsed = 0; { U64 hash = cv_hash_from_item_id(sym->inlinee); - U64 slot_idx = hash%unit_c13->inlinee_lines_parsed_slots_count; - for(CV_C13InlineeLinesParsedNode *n = unit_c13->inlinee_lines_parsed_slots[slot_idx]; n != 0; n = n->hash_next) + U64 slot_idx = hash%pdb_unit_c13->inlinee_lines_parsed_slots_count; + for(CV_C13InlineeLinesParsedNode *n = pdb_unit_c13->inlinee_lines_parsed_slots[slot_idx]; n != 0; n = n->hash_next) { if(n->v.inlinee == sym->inlinee) { @@ -807,52 +753,38 @@ ASYNC_WORK_DEF(p2r_units_convert_work) } // rjf: build line table, fill with parsed binary annotations - if(inlinee_lines_parsed != 0) { // rjf: grab checksums sub-section - CV_C13SubSectionNode *file_chksms = unit_c13->file_chksms_sub_section; + CV_C13SubSectionNode *file_chksms = pdb_unit_c13->file_chksms_sub_section; // rjf: gathered lines - typedef struct LineChunk LineChunk; - struct LineChunk - { - LineChunk *next; - U64 cap; - U64 count; - U64 *voffs; // [line_count + 1] (sorted) - U32 *line_nums; // [line_count] - U16 *col_nums; // [2*line_count] - }; - LineChunk *first_line_chunk = 0; - LineChunk *last_line_chunk = 0; - U64 total_line_chunk_line_count = 0; - U32 last_file_off = max_U32; - U32 curr_file_off = max_U32; - RDIM_LineTable* line_table = 0; - + U32 last_file_off = max_U32; + U32 curr_file_off = max_U32; + U64 line_count = 0; CV_C13InlineSiteDecoder decoder = cv_c13_inline_site_decoder_init(inlinee_lines_parsed->file_off, inlinee_lines_parsed->first_source_ln, base_voff); for(;;) { + // rjf: step & update CV_C13InlineSiteDecoderStep step = cv_c13_inline_site_decoder_step(&decoder, binary_annots); - if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitFile) { last_file_off = curr_file_off; curr_file_off = step.file_off; } - if(step.flags == 0 && total_line_chunk_line_count > 0) + if(step.flags == 0 && line_count > 0) { last_file_off = curr_file_off; curr_file_off = max_U32; } - if((last_file_off != max_U32 && last_file_off != curr_file_off)) + + // rjf: file updated -> gather new file name + if(last_file_off != max_U32 && last_file_off != curr_file_off) { String8 seq_file_name = {0}; - if(last_file_off + sizeof(CV_C13Checksum) <= file_chksms->size) { - CV_C13Checksum *checksum = (CV_C13Checksum*)(unit_c13->data.str + file_chksms->off + last_file_off); + CV_C13Checksum *checksum = (CV_C13Checksum*)(pdb_unit_c13->data.str + file_chksms->off + last_file_off); U32 name_off = checksum->name_off; seq_file_name = pdb_strtbl_string_from_off(in->pdb_strtbl, name_off); } @@ -875,77 +807,34 @@ ASYNC_WORK_DEF(p2r_units_convert_work) } // rjf: normalized file path -> source file node - U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); - U64 src_file_slot = file_path_normalized_hash%src_file_map.slots_count; - P2R_SrcFileNode *src_file_node = 0; - for(P2R_SrcFileNode *n = src_file_map.slots[src_file_slot]; n != 0; n = n->next) + U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); + U64 hit_path_slot = file_path_normalized_hash%hit_path_slots_count; + String8Node *hit_path_node = 0; + for(String8Node *n = hit_path_slots[hit_path_slot]; n != 0; n = n->next) { - if(str8_match(n->src_file->normal_full_path, file_path_normalized, 0)) + if(str8_match(n->string, file_path_normalized, 0)) { - src_file_node = n; + hit_path_node = n; break; } } - if(src_file_node == 0) + if(hit_path_node == 0) { - src_file_node = push_array(scratch.arena, P2R_SrcFileNode, 1); - SLLStackPush(src_file_map.slots[src_file_slot], src_file_node); - src_file_node->src_file = rdim_src_file_chunk_list_push(arena, &out->src_files, 4096); - src_file_node->src_file->normal_full_path = push_str8_copy(arena, file_path_normalized); + hit_path_node = push_array(scratch.arena, String8Node, 1); + SLLStackPush(hit_path_slots[hit_path_slot], hit_path_node); + hit_path_node->string = file_path_normalized; + str8_list_push(scratch.arena, &src_file_paths, push_str8_copy(arena, file_path_normalized)); } - - // rjf: gather all lines - RDI_U64 *voffs = push_array_no_zero(arena, RDI_U64, total_line_chunk_line_count+1); - RDI_U32 *line_nums = push_array_no_zero(arena, RDI_U32, total_line_chunk_line_count); - RDI_U64 line_count = total_line_chunk_line_count; - { - U64 dst_idx = 0; - for(LineChunk *chunk = first_line_chunk; chunk != 0; chunk = chunk->next) - { - MemoryCopy(voffs+dst_idx, chunk->voffs, sizeof(U64)*(chunk->count+1)); - MemoryCopy(line_nums+dst_idx, chunk->line_nums, sizeof(U32)*chunk->count); - dst_idx += chunk->count; - } - } - - // rjf: push - if(line_count != 0) - { - if(line_table == 0) - { - line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 256); - if(out->units_first_inline_site_line_tables[comp_unit_idx] == 0) - { - out->units_first_inline_site_line_tables[comp_unit_idx] = line_table; - } - } - RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, voffs, line_nums, 0, line_count); - rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); - } - - // rjf: clear line chunks for subsequent sequences - first_line_chunk = last_line_chunk = 0; - total_line_chunk_line_count = 0; + line_count = 0; } + // rjf: count lines if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitLine) { - LineChunk *chunk = last_line_chunk; - if(chunk == 0 || chunk->count+1 >= chunk->cap) - { - chunk = push_array(scratch.arena, LineChunk, 1); - SLLQueuePush(first_line_chunk, last_line_chunk, chunk); - chunk->cap = 256; - chunk->voffs = push_array_no_zero(scratch.arena, U64, chunk->cap); - chunk->line_nums = push_array_no_zero(scratch.arena, U32, chunk->cap); - } - chunk->voffs[chunk->count] = step.line_voff; - chunk->voffs[chunk->count+1] = step.line_voff_end; - chunk->line_nums[chunk->count] = step.ln; - chunk->count += 1; - total_line_chunk_line_count += 1; + line_count += 1; } + // rjf: no more flags -> done if(step.flags == 0) { break; @@ -957,18 +846,394 @@ ASYNC_WORK_DEF(p2r_units_convert_work) } } } + out->src_file_paths = str8_array_from_list(arena, &src_file_paths); scratch_end(scratch); ProfEnd(); return out; } +//////////////////////////////// +//~ rjf: Unit Conversion Tasks + +ASYNC_WORK_DEF(p2r_unit_convert_work) +{ + ProfBeginFunction(); + Arena *arena = async_root_thread_arena(p2r_async_root); + Temp scratch = scratch_begin(&arena, 1); + P2R_UnitConvertIn *in = (P2R_UnitConvertIn *)input; + P2R_UnitConvertOut *out = push_array(arena, P2R_UnitConvertOut, 1); + + //////////////////////////// + //- rjf: pass 1: build per-unit info & per-unit line table + // + ProfScope("pass 1: build per-unit info & per-unit line table") + { + PDB_CompUnit *pdb_unit = in->comp_unit; + CV_SymParsed *pdb_unit_sym = in->comp_unit_syms; + CV_C13Parsed *pdb_unit_c13 = in->comp_unit_c13s; + + //- rjf: produce unit name + String8 unit_name = pdb_unit->obj_name; + if(unit_name.size != 0) + { + String8 unit_name_past_last_slash = str8_skip_last_slash(unit_name); + if(unit_name_past_last_slash.size != 0) + { + unit_name = unit_name_past_last_slash; + } + } + + //- rjf: produce obj name/path + String8 obj_name = pdb_unit->obj_name; + if(str8_match(obj_name, str8_lit("* Linker *"), 0) || + str8_match(obj_name, str8_lit("Import:"), StringMatchFlag_RightSideSloppy)) + { + MemoryZeroStruct(&obj_name); + } + String8 obj_folder_path = lower_from_str8(scratch.arena, str8_chop_last_slash(obj_name)); + + //- rjf: build this unit's line table, fill out primary line info (inline info added after) + RDIM_LineTable *line_table = 0; + for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; + node != 0; + node = node->next) + { + if(node->kind == CV_C13SubSectionKind_Lines) + { + for(CV_C13LinesParsedNode *lines_n = node->lines_first; + lines_n != 0; + lines_n = lines_n->next) + { + CV_C13LinesParsed *lines = &lines_n->v; + + // rjf: file name -> normalized file path + String8 file_path = lines->file_name; + String8 file_path_normalized = lower_from_str8(scratch.arena, str8_skip_chop_whitespace(file_path)); + { + PathStyle file_path_normalized_style = path_style_from_str8(file_path_normalized); + String8List file_path_normalized_parts = str8_split_path(scratch.arena, file_path_normalized); + if(file_path_normalized_style == PathStyle_Relative) + { + String8List obj_folder_path_parts = str8_split_path(scratch.arena, obj_folder_path); + str8_list_concat_in_place(&obj_folder_path_parts, &file_path_normalized_parts); + file_path_normalized_parts = obj_folder_path_parts; + file_path_normalized_style = path_style_from_str8(obj_folder_path); + } + str8_path_list_resolve_dots_in_place(&file_path_normalized_parts, file_path_normalized_style); + file_path_normalized = str8_path_list_join_by_style(scratch.arena, &file_path_normalized_parts, file_path_normalized_style); + } + + // rjf: normalized file path -> source file node + U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); + U64 src_file_slot = file_path_normalized_hash%in->src_file_map->slots_count; + P2R_SrcFileNode *src_file_node = 0; + if(lines->line_count != 0) + { + for(P2R_SrcFileNode *n = in->src_file_map->slots[src_file_slot]; n != 0; n = n->next) + { + if(str8_match(n->src_file->normal_full_path, file_path_normalized, 0)) + { + src_file_node = n; + break; + } + } + } + + // rjf: push sequence into both line table & source file's line map + if(src_file_node != 0) + { + if(line_table == 0) + { + line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 256); + } + RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, lines->voffs, lines->line_nums, lines->col_nums, lines->line_count); + } + } + } + } + + //- rjf: build unit + RDIM_Unit *dst_unit = rdim_unit_chunk_list_push(arena, &out->units, 1); + dst_unit->unit_name = unit_name; + dst_unit->compiler_name = pdb_unit_sym->info.compiler_name; + dst_unit->object_file = obj_name; + dst_unit->archive_file = pdb_unit->group_name; + dst_unit->language = p2r_rdi_language_from_cv_language(pdb_unit_sym->info.language); + dst_unit->line_table = line_table; + dst_unit->voff_ranges = in->comp_unit_ranges; + } + + //////////////////////////// + //- rjf: pass 2: parse all inlinee line tables + // + ProfScope("pass 2: parse all inlinee line tables") + { + //- rjf: unpack unit + PDB_CompUnit *pdb_unit = in->comp_unit; + CV_SymParsed *pdb_unit_sym = in->comp_unit_syms; + CV_C13Parsed *pdb_unit_c13 = in->comp_unit_c13s; + CV_RecRange *rec_ranges_first = pdb_unit_sym->sym_ranges.ranges; + CV_RecRange *rec_ranges_opl = rec_ranges_first+pdb_unit_sym->sym_ranges.count; + + //- rjf: produce obj name/path + String8 obj_name = pdb_unit->obj_name; + if(str8_match(obj_name, str8_lit("* Linker *"), 0) || + str8_match(obj_name, str8_lit("Import:"), StringMatchFlag_RightSideSloppy)) + { + MemoryZeroStruct(&obj_name); + } + String8 obj_folder_path = lower_from_str8(scratch.arena, str8_chop_last_slash(obj_name)); + + //- rjf: parse inlinee line tables + U64 base_voff = 0; + for(CV_RecRange *rec_range = rec_ranges_first; + rec_range < rec_ranges_opl; + rec_range += 1) + { + //- rjf: rec range -> symbol info range + U64 sym_off_first = rec_range->off + 2; + U64 sym_off_opl = rec_range->off + rec_range->hdr.size; + + //- rjf: skip invalid ranges + if(sym_off_opl > pdb_unit_sym->data.size || sym_off_first > pdb_unit_sym->data.size || sym_off_first > sym_off_opl) + { + continue; + } + + //- rjf: unpack symbol info + CV_SymKind kind = rec_range->hdr.kind; + U64 sym_header_struct_size = cv_header_struct_size_from_sym_kind(kind); + void *sym_header_struct_base = pdb_unit_sym->data.str + sym_off_first; + void *sym_data_opl = pdb_unit_sym->data.str + sym_off_opl; + + //- rjf: skip bad sizes + if(sym_off_first + sym_header_struct_size > sym_off_opl) + { + continue; + } + + //- rjf: process symbol + switch(kind) + { + default:{}break; + + //- rjf: LPROC32/GPROC32 (gather base address) + case CV_SymKind_LPROC32: + case CV_SymKind_GPROC32: + { + CV_SymProc32 *proc32 = (CV_SymProc32 *)sym_header_struct_base; + COFF_SectionHeader *section = (0 < proc32->sec && proc32->sec <= in->coff_sections.count) ? &in->coff_sections.v[proc32->sec-1] : 0; + if(section != 0) + { + base_voff = section->voff + proc32->off; + } + }break; + + //- rjf: INLINESITE + case CV_SymKind_INLINESITE: + { + // rjf: unpack sym + CV_SymInlineSite *sym = (CV_SymInlineSite *)sym_header_struct_base; + String8 binary_annots = str8((U8 *)(sym+1), rec_range->hdr.size - sizeof(rec_range->hdr.kind) - sizeof(*sym)); + + // rjf: map inlinee -> parsed cv c13 inlinee line info + CV_C13InlineeLinesParsed *inlinee_lines_parsed = 0; + { + U64 hash = cv_hash_from_item_id(sym->inlinee); + U64 slot_idx = hash%pdb_unit_c13->inlinee_lines_parsed_slots_count; + for(CV_C13InlineeLinesParsedNode *n = pdb_unit_c13->inlinee_lines_parsed_slots[slot_idx]; n != 0; n = n->hash_next) + { + if(n->v.inlinee == sym->inlinee) + { + inlinee_lines_parsed = &n->v; + break; + } + } + } + + // rjf: build line table, fill with parsed binary annotations + if(inlinee_lines_parsed != 0) + { + // rjf: grab checksums sub-section + CV_C13SubSectionNode *file_chksms = pdb_unit_c13->file_chksms_sub_section; + + // rjf: gathered lines + typedef struct LineChunk LineChunk; + struct LineChunk + { + LineChunk *next; + U64 cap; + U64 count; + U64 *voffs; // [line_count + 1] (sorted) + U32 *line_nums; // [line_count] + U16 *col_nums; // [2*line_count] + }; + LineChunk *first_line_chunk = 0; + LineChunk *last_line_chunk = 0; + U64 total_line_chunk_line_count = 0; + U32 last_file_off = max_U32; + U32 curr_file_off = max_U32; + RDIM_LineTable* line_table = 0; + + CV_C13InlineSiteDecoder decoder = cv_c13_inline_site_decoder_init(inlinee_lines_parsed->file_off, inlinee_lines_parsed->first_source_ln, base_voff); + for(;;) + { + // rjf: step & update + CV_C13InlineSiteDecoderStep step = cv_c13_inline_site_decoder_step(&decoder, binary_annots); + if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitFile) + { + last_file_off = curr_file_off; + curr_file_off = step.file_off; + } + if(step.flags == 0 && total_line_chunk_line_count > 0) + { + last_file_off = curr_file_off; + curr_file_off = max_U32; + } + + // rjf: file updated -> push line chunks gathered for this file + if(last_file_off != max_U32 && last_file_off != curr_file_off) + { + String8 seq_file_name = {0}; + if(last_file_off + sizeof(CV_C13Checksum) <= file_chksms->size) + { + CV_C13Checksum *checksum = (CV_C13Checksum*)(pdb_unit_c13->data.str + file_chksms->off + last_file_off); + U32 name_off = checksum->name_off; + seq_file_name = pdb_strtbl_string_from_off(in->pdb_strtbl, name_off); + } + + // rjf: file name -> normalized file path + String8 file_path = seq_file_name; + String8 file_path_normalized = lower_from_str8(scratch.arena, str8_skip_chop_whitespace(file_path)); + { + PathStyle file_path_normalized_style = path_style_from_str8(file_path_normalized); + String8List file_path_normalized_parts = str8_split_path(scratch.arena, file_path_normalized); + if(file_path_normalized_style == PathStyle_Relative) + { + String8List obj_folder_path_parts = str8_split_path(scratch.arena, obj_folder_path); + str8_list_concat_in_place(&obj_folder_path_parts, &file_path_normalized_parts); + file_path_normalized_parts = obj_folder_path_parts; + file_path_normalized_style = path_style_from_str8(obj_folder_path); + } + str8_path_list_resolve_dots_in_place(&file_path_normalized_parts, file_path_normalized_style); + file_path_normalized = str8_path_list_join_by_style(scratch.arena, &file_path_normalized_parts, file_path_normalized_style); + } + + // rjf: normalized file path -> source file node + U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); + U64 src_file_slot = file_path_normalized_hash%in->src_file_map->slots_count; + P2R_SrcFileNode *src_file_node = 0; + for(P2R_SrcFileNode *n = in->src_file_map->slots[src_file_slot]; n != 0; n = n->next) + { + if(str8_match(n->src_file->normal_full_path, file_path_normalized, 0)) + { + src_file_node = n; + break; + } + } + + // rjf: gather all lines + RDI_U64 *voffs = 0; + RDI_U32 *line_nums = 0; + RDI_U64 line_count = 0; + if(src_file_node != 0) + { + voffs = push_array_no_zero(arena, RDI_U64, total_line_chunk_line_count+1); + line_nums = push_array_no_zero(arena, RDI_U32, total_line_chunk_line_count); + line_count = total_line_chunk_line_count; + U64 dst_idx = 0; + for(LineChunk *chunk = first_line_chunk; chunk != 0; chunk = chunk->next) + { + MemoryCopy(voffs+dst_idx, chunk->voffs, sizeof(U64)*(chunk->count+1)); + MemoryCopy(line_nums+dst_idx, chunk->line_nums, sizeof(U32)*chunk->count); + dst_idx += chunk->count; + } + } + + // rjf: push + if(line_count != 0) + { + if(line_table == 0) + { + line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 256); + if(out->unit_first_inline_site_line_table == 0) + { + out->unit_first_inline_site_line_table = line_table; + } + } + rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, voffs, line_nums, 0, line_count); + } + + // rjf: clear line chunks for subsequent sequences + first_line_chunk = last_line_chunk = 0; + total_line_chunk_line_count = 0; + } + + // rjf: new line -> emit to chunk + if(step.flags & CV_C13InlineSiteDecoderStepFlag_EmitLine) + { + LineChunk *chunk = last_line_chunk; + if(chunk == 0 || chunk->count+1 >= chunk->cap) + { + chunk = push_array(scratch.arena, LineChunk, 1); + SLLQueuePush(first_line_chunk, last_line_chunk, chunk); + chunk->cap = 8; + chunk->voffs = push_array_no_zero(scratch.arena, U64, chunk->cap); + chunk->line_nums = push_array_no_zero(scratch.arena, U32, chunk->cap); + } + chunk->voffs[chunk->count] = step.line_voff; + chunk->voffs[chunk->count+1] = step.line_voff_end; + chunk->line_nums[chunk->count] = step.ln; + chunk->count += 1; + total_line_chunk_line_count += 1; + } + + // rjf: no more flags -> done + if(step.flags == 0) + { + break; + } + } + } + }break; + } + } + } + scratch_end(scratch); + ProfEnd(); + return out; +} + +//////////////////////////////// +//~ rjf: Source File Sequence Equipping Task + +ASYNC_WORK_DEF(p2r_src_file_seq_equip_work) +{ + ProfBeginFunction(); + Arena *arena = async_root_thread_arena(p2r_async_root); + P2R_SrcFileSeqEquipIn *in = (P2R_SrcFileSeqEquipIn *)input; + for(RDIM_LineTableChunkNode *line_table_chunk_n = in->line_tables.first; line_table_chunk_n != 0; line_table_chunk_n = line_table_chunk_n->next) + { + for EachIndex(chunk_line_table_idx, line_table_chunk_n->count) + { + RDIM_LineTable *line_table = &line_table_chunk_n->v[chunk_line_table_idx]; + for(RDIM_LineSequenceNode *s = line_table->first_seq; s != 0; s = s->next) + { + rdim_src_file_push_line_sequence(arena, &in->src_files, s->v.src_file, &s->v); + } + } + } + ProfEnd(); + return 0; +} + //////////////////////////////// //~ rjf: Link Name Map Building Tasks ASYNC_WORK_DEF(p2r_link_name_map_build_work) { ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(p2r_async_root); P2R_LinkNameMapBuildIn *in = (P2R_LinkNameMapBuildIn *)input; CV_RecRange *rec_ranges_first = in->sym->sym_ranges.ranges; CV_RecRange *rec_ranges_opl = rec_ranges_first + in->sym->sym_ranges.count; @@ -1026,7 +1291,7 @@ ASYNC_WORK_DEF(p2r_link_name_map_build_work) ASYNC_WORK_DEF(p2r_itype_fwd_map_fill_work) { ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(p2r_async_root); P2R_ITypeFwdMapFillIn *in = (P2R_ITypeFwdMapFillIn *)input; ProfScope("fill itype fwd map") for(CV_TypeId itype = in->itype_first; itype < in->itype_opl; itype += 1) { @@ -1156,7 +1421,7 @@ ASYNC_WORK_DEF(p2r_itype_fwd_map_fill_work) ASYNC_WORK_DEF(p2r_itype_chain_build_work) { ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(p2r_async_root); Temp scratch = scratch_begin(&arena, 1); P2R_ITypeChainBuildIn *in = (P2R_ITypeChainBuildIn *)input; ProfScope("dependency itype chain build") @@ -1459,7 +1724,7 @@ ASYNC_WORK_DEF(p2r_itype_chain_build_work) ASYNC_WORK_DEF(p2r_udt_convert_work) { ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(p2r_async_root); P2R_UDTConvertIn *in = (P2R_UDTConvertIn *)input; #define p2r_type_ptr_from_itype(itype) ((in->itype_type_ptrs && (itype) < in->tpi_leaf->itype_opl) ? (in->itype_type_ptrs[(in->itype_fwd_map[(itype)] ? in->itype_fwd_map[(itype)] : (itype))]) : 0) RDIM_UDTChunkList *udts = push_array(arena, RDIM_UDTChunkList, 1); @@ -2096,7 +2361,7 @@ ASYNC_WORK_DEF(p2r_udt_convert_work) ASYNC_WORK_DEF(p2r_symbol_stream_convert_work) { ProfBeginFunction(); - Arena *arena = p2r_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(p2r_async_root); Temp scratch = scratch_begin(&arena, 1); P2R_SymbolStreamConvertIn *in = (P2R_SymbolStreamConvertIn *)input; #define p2r_type_ptr_from_itype(itype) ((in->itype_type_ptrs && (itype) < in->tpi_leaf->itype_opl) ? (in->itype_type_ptrs[(in->itype_fwd_map[(itype)] ? in->itype_fwd_map[(itype)] : (itype))]) : 0) @@ -2107,11 +2372,13 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work) U64 sym_procedures_chunk_cap = 1024; U64 sym_global_variables_chunk_cap = 1024; U64 sym_thread_variables_chunk_cap = 1024; + U64 sym_constants_chunk_cap = 1024; U64 sym_scopes_chunk_cap = 1024; U64 sym_inline_sites_chunk_cap = 1024; RDIM_SymbolChunkList sym_procedures = {0}; RDIM_SymbolChunkList sym_global_variables = {0}; RDIM_SymbolChunkList sym_thread_variables = {0}; + RDIM_SymbolChunkList sym_constants = {0}; RDIM_ScopeChunkList sym_scopes = {0}; RDIM_InlineSiteChunkList sym_inline_sites = {0}; RDIM_TypeChunkList typedefs = {0}; @@ -2338,21 +2605,19 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work) } }break; + //- rjf: UDT (typedefs) case CV_SymKind_UDT: + if(in->parsing_global_stream && top_scope_node == 0) { - if(in->parsing_global_stream && top_scope_node == 0) + CV_SymUDT *udt = (CV_SymUDT *)sym_header_struct_base; + String8 name = str8_cstring_capped(udt+1, sym_data_opl); + RDIM_Type *type = rdim_type_chunk_list_push(arena, &typedefs, 4096); + type->kind = RDI_TypeKind_Alias; + type->name = name; + type->direct_type = p2r_type_ptr_from_itype(udt->itype); + if(type->direct_type != 0) { - CV_SymUDT *udt = (CV_SymUDT *)sym_header_struct_base; - String8 name = str8_cstring_capped(udt+1, sym_data_opl); - - RDIM_Type *type = rdim_type_chunk_list_push(arena, &typedefs, 4096); - type->kind = RDI_TypeKind_Alias; - type->name = name; - type->direct_type = p2r_type_ptr_from_itype(udt->itype); - if(type->direct_type != 0) - { - type->byte_size = type->direct_type->byte_size; - } + type->byte_size = type->direct_type->byte_size; } }break; @@ -2950,6 +3215,39 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work) defrange_target = 0; defrange_target_is_param = 0; }break; + + //- rjf: CONSTANT + case CV_SymKind_CONSTANT: + { + // rjf: unpack + CV_SymConstant *sym = (CV_SymConstant *)sym_header_struct_base; + RDIM_Type *type = p2r_type_ptr_from_itype(sym->itype); + U8 *val_ptr = (U8 *)(sym+1); + CV_NumericParsed val = cv_numeric_from_data_range(val_ptr, sym_data_opl); + U64 val64 = cv_u64_from_numeric(&val); + U8 *name_ptr = val_ptr + val.encoded_size; + String8 name = str8_cstring_capped(name_ptr, sym_data_opl); + String8 val_data = str8_struct(&val64); + U64 container_name_opl = 0; + if(type != 0) + { + container_name_opl = p2r_end_of_cplusplus_container_name(type->name); + } + String8 name_qualified = name; + if(container_name_opl != 0) + { + name_qualified = push_str8f(arena, "%S%S", str8_prefix(type->name, container_name_opl), name); + } + + // rjf: build constant symbol + if(name_qualified.size != 0) + { + RDIM_Symbol *cnst = rdim_symbol_chunk_list_push(arena, &sym_constants, sym_constants_chunk_cap); + cnst->name = name_qualified; + cnst->type = type; + rdim_symbol_push_value_data(arena, &sym_constants, cnst, val_data); + } + }break; } } } @@ -2962,6 +3260,7 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work) out->procedures = sym_procedures; out->global_variables = sym_global_variables; out->thread_variables = sym_thread_variables; + out->constants = sym_constants; out->scopes = sym_scopes; out->inline_sites = sym_inline_sites; out->typedefs = typedefs; @@ -2976,11 +3275,12 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work) //////////////////////////////// //~ rjf: Top-Level Conversion Entry Point -internal P2R_Convert2Bake * -p2r_convert(Arena *arena, P2R_User2Convert *in) +internal RDIM_BakeParams +p2r_convert(Arena *arena, ASYNC_Root *async_root, P2R_ConvertParams *in) { Temp scratch = scratch_begin(&arena, 1); - + p2r_async_root = async_root; + ////////////////////////////////////////////////////////////// //- rjf: parse MSF structure // @@ -3150,27 +3450,41 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) ASYNC_Task *sym_parse_task = !dbi ? 0 : async_task_launch(scratch.arena, p2r_symbol_stream_parse_work, .input = &sym_parse_in); ////////////////////////////////////////////////////////////// - //- rjf: kickoff compilation unit parses - // - P2R_CompUnitParseIn comp_unit_parse_in = {dbi ? pdb_data_from_dbi_range(dbi, PDB_DbiRange_ModuleInfo) : str8_zero()}; - P2R_CompUnitContributionsParseIn comp_unit_contributions_parse_in = {dbi ? pdb_data_from_dbi_range(dbi, PDB_DbiRange_SecCon) : str8_zero(), coff_sections}; - ASYNC_Task *comp_unit_parse_task = !dbi ? 0 : async_task_launch(scratch.arena, p2r_comp_unit_parse_work, .input = &comp_unit_parse_in); - ASYNC_Task *comp_unit_contributions_parse_task = !dbi ? 0 : async_task_launch(scratch.arena, p2r_comp_unit_contributions_parse_work, .input = &comp_unit_contributions_parse_in); - - ////////////////////////////////////////////////////////////// - //- rjf: join compilation unit parses - // + //- rjf: do compilation unit parse + // PDB_CompUnitArray *comp_units = 0; - U64 comp_unit_count = 0; + U64 comp_unit_count = 0; + { + P2R_CompUnitParseIn comp_unit_parse_in = {dbi ? pdb_data_from_dbi_range(dbi, PDB_DbiRange_ModuleInfo) : str8_zero()}; + ASYNC_Task *comp_unit_parse_task = !dbi ? 0 : async_task_launch(scratch.arena, p2r_comp_unit_parse_work, .input = &comp_unit_parse_in); + comp_units = async_task_join_struct(comp_unit_parse_task, PDB_CompUnitArray); + comp_unit_count = comp_units ? comp_units->count : 0; + } + + ////////////////////////////////////////////////////////////// + //- rjf: do compilation unit contributions parse + // PDB_CompUnitContributionArray *comp_unit_contributions = 0; - U64 comp_unit_contribution_count = 0; - { - comp_units = async_task_join_struct(comp_unit_parse_task, PDB_CompUnitArray); + U64 comp_unit_contribution_count = 0; + { + P2R_CompUnitContributionsParseIn comp_unit_contributions_parse_in = {dbi ? pdb_data_from_dbi_range(dbi, PDB_DbiRange_SecCon) : str8_zero(), coff_sections}; + ASYNC_Task *comp_unit_contributions_parse_task = !dbi ? 0 : async_task_launch(scratch.arena, p2r_comp_unit_contributions_parse_work, .input = &comp_unit_contributions_parse_in); comp_unit_contributions = async_task_join_struct(comp_unit_contributions_parse_task, PDB_CompUnitContributionArray); - comp_unit_count = comp_units ? comp_units->count : 0; - comp_unit_contribution_count = comp_unit_contributions ? comp_unit_contributions->count : 0; - } - + comp_unit_contribution_count = comp_unit_contributions ? comp_unit_contributions->count : 0; + } + + ////////////////////////////////////////////////////////////// + //- rjf: do compilation unit contributions bucket + // + RDIM_Rng1U64ChunkList *unit_ranges = 0; + if(comp_unit_contributions) + { + P2R_CompUnitContributionsBucketIn in = {comp_unit_count, *comp_unit_contributions}; + ASYNC_Task *task = async_task_launch(scratch.arena, p2r_comp_unit_contributions_bucket_work, .input = &in); + P2R_CompUnitContributionsBucketOut *out = async_task_join_struct(task, P2R_CompUnitContributionsBucketOut); + unit_ranges = out->unit_ranges; + } + ////////////////////////////////////////////////////////////// //- rjf: parse syms & line info for each compilation unit // @@ -3262,7 +3576,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) top_level_info.exe_name = str8_skip_last_slash(in->input_exe_name); top_level_info.exe_hash = exe_hash; top_level_info.voff_max = exe_voff_max; - if(!(in->flags & P2R_ConvertFlag_Deterministic)) + if(in->deterministic) { top_level_info.producer_name = str8_lit(BUILD_TITLE_STRING_LITERAL); } @@ -3291,10 +3605,79 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) } ////////////////////////////////////////////////////////////// - //- rjf: kick off unit conversion & source file collection + //- rjf: gather all source file paths; build nodes // - P2R_UnitConvertIn unit_convert_in = {strtbl, coff_sections, comp_units, comp_unit_contributions, sym_for_unit, c13_for_unit}; - ASYNC_Task *unit_convert_task = async_task_launch(scratch.arena, p2r_units_convert_work, .input = &unit_convert_in); + RDIM_SrcFileChunkList all_src_files__sequenceless = {0}; + P2R_SrcFileMap src_file_map = {0}; + ProfScope("gather all source file paths; build nodes") + { + U64 tasks_count = comp_unit_count; + P2R_GatherUnitSrcFilesIn *tasks_inputs = push_array(scratch.arena, P2R_GatherUnitSrcFilesIn, tasks_count); + P2R_GatherUnitSrcFilesOut *tasks_outputs = push_array(scratch.arena, P2R_GatherUnitSrcFilesOut, tasks_count); + ASYNC_Task **tasks = push_array(scratch.arena, ASYNC_Task *, tasks_count); + for EachIndex(idx, tasks_count) + { + tasks_inputs[idx].pdb_strtbl = strtbl; + tasks_inputs[idx].coff_sections = coff_sections; + tasks_inputs[idx].comp_unit = comp_units->units[idx]; + tasks_inputs[idx].comp_unit_syms = sym_for_unit[idx]; + tasks_inputs[idx].comp_unit_c13s = c13_for_unit[idx]; + tasks[idx] = async_task_launch(scratch.arena, p2r_gather_unit_src_file_work, .input = &tasks_inputs[idx]); + } + U64 total_path_count = 0; + for EachIndex(idx, tasks_count) + { + tasks_outputs[idx] = *async_task_join_struct(tasks[idx], P2R_GatherUnitSrcFilesOut); + total_path_count += tasks_outputs[idx].src_file_paths.count; + } + src_file_map.slots_count = total_path_count + total_path_count/2 + 1; + src_file_map.slots = push_array(scratch.arena, P2R_SrcFileNode *, src_file_map.slots_count); + for EachIndex(idx, tasks_count) + { + for EachIndex(path_idx, tasks_outputs[idx].src_file_paths.count) + { + String8 file_path_normalized = tasks_outputs[idx].src_file_paths.v[path_idx]; + U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); + U64 src_file_slot = file_path_normalized_hash%src_file_map.slots_count; + P2R_SrcFileNode *src_file_node = 0; + for(P2R_SrcFileNode *n = src_file_map.slots[src_file_slot]; n != 0; n = n->next) + { + if(str8_match(n->src_file->normal_full_path, file_path_normalized, 0)) + { + src_file_node = n; + break; + } + } + if(src_file_node == 0) + { + src_file_node = push_array(scratch.arena, P2R_SrcFileNode, 1); + SLLStackPush(src_file_map.slots[src_file_slot], src_file_node); + src_file_node->src_file = rdim_src_file_chunk_list_push(arena, &all_src_files__sequenceless, total_path_count); + src_file_node->src_file->normal_full_path = push_str8_copy(arena, file_path_normalized); + } + } + } + } + + ////////////////////////////////////////////////////////////// + //- rjf: kick off unit conversion tasks + // + U64 unit_convert_tasks_count = comp_unit_count; + P2R_UnitConvertIn *unit_convert_tasks_ins = push_array(scratch.arena, P2R_UnitConvertIn, unit_convert_tasks_count); + ASYNC_Task **unit_convert_tasks = push_array(scratch.arena, ASYNC_Task *, unit_convert_tasks_count); + for EachIndex(idx, unit_convert_tasks_count) + { + P2R_UnitConvertIn *in = &unit_convert_tasks_ins[idx]; + in->comp_unit_idx = idx; + in->pdb_strtbl = strtbl; + in->coff_sections = coff_sections; + in->comp_unit = comp_units->units[idx]; + in->comp_unit_ranges = unit_ranges[idx]; + in->comp_unit_syms = sym_for_unit[idx]; + in->comp_unit_c13s = c13_for_unit[idx]; + in->src_file_map = &src_file_map; + unit_convert_tasks[idx] = async_task_launch(scratch.arena, p2r_unit_convert_work, .input = in); + } ////////////////////////////////////////////////////////////// //- rjf: join global sym stream parse @@ -3366,7 +3749,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) CV_TypeId *itype_fwd_map = 0; CV_TypeId itype_first = 0; CV_TypeId itype_opl = 0; - if(tpi_leaf != 0 && in->flags & P2R_ConvertFlag_Types) ProfScope("types pass 1: produce type forward resolution map") + if(tpi_leaf != 0 && in->subset_flags & RDIM_SubsetFlag_Types) ProfScope("types pass 1: produce type forward resolution map") { //- rjf: allocate forward resolution map itype_first = tpi_leaf->itype_first; @@ -3407,7 +3790,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) // as such, always show up *earlier* in the actually built types. // P2R_TypeIdChain **itype_chains = 0; - if(tpi_leaf != 0 && in->flags & P2R_ConvertFlag_Types) ProfScope("types pass 2: produce per-itype itype chain (for producing dependent types first)") + if(tpi_leaf != 0 && in->subset_flags & RDIM_SubsetFlag_Types) ProfScope("types pass 2: produce per-itype itype chain (for producing dependent types first)") { //- rjf: allocate itype chain table itype_chains = push_array(arena, P2R_TypeIdChain *, (U64)itype_opl); @@ -3445,7 +3828,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) RDIM_Type **itype_type_ptrs = 0; RDIM_TypeChunkList all_types = rdim_init_type_chunk_list(arena, top_level_info.arch); #define p2r_type_ptr_from_itype(itype) ((itype_type_ptrs && (itype) < itype_opl) ? (itype_type_ptrs[(itype_fwd_map[(itype)] ? itype_fwd_map[(itype)] : (itype))]) : 0) - if(in->flags & P2R_ConvertFlag_Types) ProfScope("types pass 3: construct all root/stub types from TPI") + if(in->subset_flags & RDIM_SubsetFlag_Types) ProfScope("types pass 3: construct all root/stub types from TPI") { itype_type_ptrs = push_array(arena, RDIM_Type *, (U64)(itype_opl)); @@ -3965,7 +4348,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) U64 udt_tasks_count = ((U64)itype_opl+(udt_task_size_itypes-1))/udt_task_size_itypes; P2R_UDTConvertIn *udt_tasks_inputs = push_array(scratch.arena, P2R_UDTConvertIn, udt_tasks_count); ASYNC_Task **udt_tasks = push_array(scratch.arena, ASYNC_Task *, udt_tasks_count); - if(in->flags & P2R_ConvertFlag_UDTs) ProfScope("types pass 4: kick off UDT build") + if(in->subset_flags & RDIM_SubsetFlag_UDTs) ProfScope("types pass 4: kick off UDT build") { for(U64 idx = 0; idx < udt_tasks_count; idx += 1) { @@ -3990,19 +4373,31 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) } ////////////////////////////////////////////////////////////// - //- rjf: join unit conversion & src file & line table tasks + //- rjf: join unit conversion tasks // RDIM_UnitChunkList all_units = {0}; - RDIM_SrcFileChunkList all_src_files = {0}; RDIM_LineTableChunkList all_line_tables = {0}; - RDIM_LineTable **units_first_inline_site_line_tables = 0; + RDIM_LineTable **units_first_inline_site_line_tables = push_array(arena, RDIM_LineTable *, unit_convert_tasks_count); ProfScope("join unit conversion & src file tasks") { - P2R_UnitConvertOut *out = async_task_join_struct(unit_convert_task, P2R_UnitConvertOut); - all_units = out->units; - all_src_files = out->src_files; - all_line_tables = out->line_tables; - units_first_inline_site_line_tables = out->units_first_inline_site_line_tables; + for EachIndex(idx, unit_convert_tasks_count) + { + P2R_UnitConvertOut *out = async_task_join_struct(unit_convert_tasks[idx], P2R_UnitConvertOut); + rdim_unit_chunk_list_concat_in_place(&all_units, &out->units); + rdim_line_table_chunk_list_concat_in_place(&all_line_tables, &out->line_tables); + units_first_inline_site_line_tables[idx] = out->unit_first_inline_site_line_table; + } + } + + ////////////////////////////////////////////////////////////// + //- rjf: kick off source file line sequence equipping task + // + RDIM_SrcFileChunkList all_src_files = {0}; + { + P2R_SrcFileSeqEquipIn in = {all_src_files__sequenceless, all_line_tables}; + ASYNC_Task *task = async_task_launch(scratch.arena, p2r_src_file_seq_equip_work, .input = &in); + async_task_join(task); + all_src_files = in.src_files; } ////////////////////////////////////////////////////////////// @@ -4011,6 +4406,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) RDIM_SymbolChunkList all_procedures = {0}; RDIM_SymbolChunkList all_global_variables = {0}; RDIM_SymbolChunkList all_thread_variables = {0}; + RDIM_SymbolChunkList all_constants = {0}; RDIM_ScopeChunkList all_scopes = {0}; RDIM_InlineSiteChunkList all_inline_sites = {0}; ProfScope("produce symbols from all streams") @@ -4065,6 +4461,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) rdim_symbol_chunk_list_concat_in_place(&all_procedures, &out->procedures); rdim_symbol_chunk_list_concat_in_place(&all_global_variables, &out->global_variables); rdim_symbol_chunk_list_concat_in_place(&all_thread_variables, &out->thread_variables); + rdim_symbol_chunk_list_concat_in_place(&all_constants, &out->constants); rdim_scope_chunk_list_concat_in_place(&all_scopes, &out->scopes); rdim_inline_site_chunk_list_concat_in_place(&all_inline_sites,&out->inline_sites); rdim_type_chunk_list_concat_in_place(&all_types, &out->typedefs); @@ -4085,70 +4482,27 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) ////////////////////////////////////////////////////////////// //- rjf: fill output // - P2R_Convert2Bake *out = push_array(arena, P2R_Convert2Bake, 1); + RDIM_BakeParams out = {0}; { - out->bake_params.top_level_info = top_level_info; - out->bake_params.binary_sections = binary_sections; - out->bake_params.units = all_units; - out->bake_params.types = all_types; - out->bake_params.udts = all_udts; - out->bake_params.src_files = all_src_files; - out->bake_params.line_tables = all_line_tables; - out->bake_params.global_variables = all_global_variables; - out->bake_params.thread_variables = all_thread_variables; - out->bake_params.procedures = all_procedures; - out->bake_params.scopes = all_scopes; - out->bake_params.inline_sites = all_inline_sites; + out.top_level_info = top_level_info; + out.binary_sections = binary_sections; + out.units = all_units; + out.types = all_types; + out.udts = all_udts; + out.src_files = all_src_files; + out.line_tables = all_line_tables; + out.global_variables = all_global_variables; + out.thread_variables = all_thread_variables; + out.constants = all_constants; + out.procedures = all_procedures; + out.scopes = all_scopes; + out.inline_sites = all_inline_sites; } scratch_end(scratch); return out; } -//////////////////////////////// -//~ rjf: Top-Level Initialization - -internal void -p2r_init(void) -{ - Arena *arena = arena_alloc(); - p2r_state = push_array(arena, P2R_State, 1); - p2r_state->arena = arena; - p2r_state->work_thread_arenas_count = async_thread_count(); - p2r_state->work_thread_arenas = push_array(arena, Arena *, p2r_state->work_thread_arenas_count); - for EachIndex(idx, p2r_state->work_thread_arenas_count) - { - p2r_state->work_thread_arenas[idx] = arena_alloc(); - } -} - -//////////////////////////////// -//~ rjf: Top-Level Baking Entry Point - -internal P2R_Bake2Serialize * -p2r_bake(Arena *arena, P2R_Convert2Bake *in) -{ - RDIM_LocalState local_state = {0}; - local_state.arena = p2r_state->arena; - local_state.work_thread_arenas_count = p2r_state->work_thread_arenas_count; - local_state.work_thread_arenas = p2r_state->work_thread_arenas; - - P2R_Bake2Serialize *result = push_array(arena, P2R_Bake2Serialize, 1); - result->bake_results = rdim_bake(&local_state, &in->bake_params); - return result; -} - -//////////////////////////////// -//~ rjf: Top-Level Compression Entry Point - -internal P2R_Serialize2File * -p2r_compress(Arena *arena, P2R_Serialize2File *in) -{ - P2R_Serialize2File *out = push_array(arena, P2R_Serialize2File, 1); - out->bundle = rdim_compress(arena, &in->bundle); - return out; -} - //////////////////////////////// internal B32 diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index e8642256..c9b2dcd5 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -1,68 +1,21 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RDI_FROM_PDB_H #define RDI_FROM_PDB_H -//////////////////////////////// -//~ rjf: Export Artifact Flags - -typedef U32 P2R_ConvertFlags; -enum -{ - P2R_ConvertFlag_Strings = (1<<0), - P2R_ConvertFlag_IndexRuns = (1<<1), - P2R_ConvertFlag_BinarySections = (1<<2), - P2R_ConvertFlag_Units = (1<<3), - P2R_ConvertFlag_Procedures = (1<<4), - P2R_ConvertFlag_GlobalVariables = (1<<5), - P2R_ConvertFlag_ThreadVariables = (1<<6), - P2R_ConvertFlag_Scopes = (1<<7), - P2R_ConvertFlag_Locals = (1<<8), - P2R_ConvertFlag_Types = (1<<9), - P2R_ConvertFlag_UDTs = (1<<10), - P2R_ConvertFlag_LineInfo = (1<<11), - P2R_ConvertFlag_GlobalVariableNameMap = (1<<12), - P2R_ConvertFlag_ThreadVariableNameMap = (1<<13), - P2R_ConvertFlag_ProcedureNameMap = (1<<14), - P2R_ConvertFlag_TypeNameMap = (1<<15), - P2R_ConvertFlag_LinkNameProcedureNameMap= (1<<16), - P2R_ConvertFlag_NormalSourcePathNameMap = (1<<17), - P2R_ConvertFlag_Deterministic = (1<<18), - P2R_ConvertFlag_All = 0xffffffff, -}; - //////////////////////////////// //~ rjf: Conversion Stage Inputs/Outputs -typedef struct P2R_User2Convert P2R_User2Convert; -struct P2R_User2Convert +typedef struct P2R_ConvertParams P2R_ConvertParams; +struct P2R_ConvertParams { String8 input_pdb_name; String8 input_pdb_data; String8 input_exe_name; String8 input_exe_data; - String8 output_name; - P2R_ConvertFlags flags; - String8List errors; -}; - -typedef struct P2R_Convert2Bake P2R_Convert2Bake; -struct P2R_Convert2Bake -{ - RDIM_BakeParams bake_params; -}; - -typedef struct P2R_Bake2Serialize P2R_Bake2Serialize; -struct P2R_Bake2Serialize -{ - RDIM_BakeResults bake_results; -}; - -typedef struct P2R_Serialize2File P2R_Serialize2File; -struct P2R_Serialize2File -{ - RDIM_SerializedSectionBundle bundle; + RDIM_SubsetFlags subset_flags; + B32 deterministic; }; //////////////////////////////// @@ -131,6 +84,21 @@ struct P2R_CompUnitContributionsParseIn COFF_SectionHeaderArray coff_sections; }; +//- rjf: comp unit contribution table bucketing by unit + +typedef struct P2R_CompUnitContributionsBucketIn P2R_CompUnitContributionsBucketIn; +struct P2R_CompUnitContributionsBucketIn +{ + U64 comp_unit_count; + PDB_CompUnitContributionArray contributions; +}; + +typedef struct P2R_CompUnitContributionsBucketOut P2R_CompUnitContributionsBucketOut; +struct P2R_CompUnitContributionsBucketOut +{ + RDIM_Rng1U64ChunkList *unit_ranges; +}; + //////////////////////////////// //~ rjf: Conversion Data Structure & Task Types @@ -169,26 +137,54 @@ struct P2R_SrcFileMap U64 slots_count; }; +//- rjf: per-unit source files conversion tasks + +typedef struct P2R_GatherUnitSrcFilesIn P2R_GatherUnitSrcFilesIn; +struct P2R_GatherUnitSrcFilesIn +{ + PDB_Strtbl *pdb_strtbl; + COFF_SectionHeaderArray coff_sections; + PDB_CompUnit *comp_unit; + CV_SymParsed *comp_unit_syms; + CV_C13Parsed *comp_unit_c13s; +}; + +typedef struct P2R_GatherUnitSrcFilesOut P2R_GatherUnitSrcFilesOut; +struct P2R_GatherUnitSrcFilesOut +{ + String8Array src_file_paths; +}; + //- rjf: unit conversion tasks typedef struct P2R_UnitConvertIn P2R_UnitConvertIn; struct P2R_UnitConvertIn { + U64 comp_unit_idx; PDB_Strtbl *pdb_strtbl; COFF_SectionHeaderArray coff_sections; - PDB_CompUnitArray *comp_units; - PDB_CompUnitContributionArray *comp_unit_contributions; - CV_SymParsed **comp_unit_syms; - CV_C13Parsed **comp_unit_c13s; + PDB_CompUnit *comp_unit; + RDIM_Rng1U64ChunkList comp_unit_ranges; + CV_SymParsed *comp_unit_syms; + CV_C13Parsed *comp_unit_c13s; + P2R_SrcFileMap *src_file_map; }; typedef struct P2R_UnitConvertOut P2R_UnitConvertOut; struct P2R_UnitConvertOut { RDIM_UnitChunkList units; + RDIM_LineTableChunkList line_tables; + RDIM_LineTable *unit_first_inline_site_line_table; +}; + +//- rjf: src file sequence equipping task + +typedef struct P2R_SrcFileSeqEquipIn P2R_SrcFileSeqEquipIn; +struct P2R_SrcFileSeqEquipIn +{ RDIM_SrcFileChunkList src_files; RDIM_LineTableChunkList line_tables; - RDIM_LineTable **units_first_inline_site_line_tables; }; //- rjf: link name map building tasks @@ -270,26 +266,16 @@ struct P2R_SymbolStreamConvertOut RDIM_SymbolChunkList procedures; RDIM_SymbolChunkList global_variables; RDIM_SymbolChunkList thread_variables; + RDIM_SymbolChunkList constants; RDIM_ScopeChunkList scopes; RDIM_InlineSiteChunkList inline_sites; RDIM_TypeChunkList typedefs; }; -//////////////////////////////// -//~ rjf: Top-Level State - -typedef struct P2R_State P2R_State; -struct P2R_State -{ - Arena *arena; - U64 work_thread_arenas_count; - Arena **work_thread_arenas; -}; - //////////////////////////////// //~ rjf: Globals -global P2R_State *p2r_state = 0; +global ASYNC_Root *p2r_async_root = 0; //////////////////////////////// //~ rjf: Basic Helpers @@ -300,7 +286,9 @@ internal U64 p2r_hash_from_voff(U64 voff); //////////////////////////////// //~ rjf: Command Line -> Conversion Inputs -internal P2R_User2Convert *p2r_user2convert_from_cmdln(Arena *arena, CmdLine *cmdline); +#if 0 +internal P2R_ConvertParams *p2r_user2convert_from_cmdln(Arena *arena, CmdLine *cmdline); +#endif //////////////////////////////// //~ rjf: COFF => RDI Canonical Conversions @@ -332,11 +320,22 @@ ASYNC_WORK_DEF(p2r_symbol_stream_parse_work); ASYNC_WORK_DEF(p2r_c13_stream_parse_work); ASYNC_WORK_DEF(p2r_comp_unit_parse_work); ASYNC_WORK_DEF(p2r_comp_unit_contributions_parse_work); +ASYNC_WORK_DEF(p2r_comp_unit_contributions_bucket_work); + +//////////////////////////////// +//~ rjf: Unit Source File Gathering Tasks + +ASYNC_WORK_DEF(p2r_gather_unit_src_file_work); //////////////////////////////// //~ rjf: Unit Conversion Tasks -ASYNC_WORK_DEF(p2r_units_convert_work); +ASYNC_WORK_DEF(p2r_unit_convert_work); + +//////////////////////////////// +//~ rjf: Source File Sequence Equipping Task + +ASYNC_WORK_DEF(p2r_src_file_seq_equip_work); //////////////////////////////// //~ rjf: Link Name Map Building Tasks @@ -362,22 +361,7 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work); //////////////////////////////// //~ rjf: Top-Level Conversion Entry Point -internal P2R_Convert2Bake *p2r_convert(Arena *arena, P2R_User2Convert *in); - -//////////////////////////////// -//~ rjf: Top-Level Initialization - -internal void p2r_init(void); - -//////////////////////////////// -//~ rjf: Top-Level Baking Entry Point - -internal P2R_Bake2Serialize *p2r_bake(Arena *arena, P2R_Convert2Bake *in); - -//////////////////////////////// -//~ rjf: Top-Level Compression Entry Point - -internal P2R_Serialize2File *p2r_compress(Arena *arena, P2R_Serialize2File *in); +internal RDIM_BakeParams p2r_convert(Arena *arena, ASYNC_Root *async_root, P2R_ConvertParams *in); //////////////////////////////// diff --git a/src/rdi_from_pdb/rdi_from_pdb_main.c b/src/rdi_from_pdb/rdi_from_pdb_main.c deleted file mode 100644 index a0d02a7d..00000000 --- a/src/rdi_from_pdb/rdi_from_pdb_main.c +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ rjf: Build Options - -#define BUILD_TITLE "rdi_from_pdb" -#define BUILD_CONSOLE_INTERFACE 1 - -//////////////////////////////// -//~ rjf: Includes - -//- rjf: [lib] -#include "lib_rdi_format/rdi_format.h" -#include "lib_rdi_format/rdi_format.c" -#include "third_party/rad_lzb_simple/rad_lzb_simple.h" -#include "third_party/rad_lzb_simple/rad_lzb_simple.c" - -//- rjf: [h] -#include "base/base_inc.h" -#include "os/os_inc.h" -#include "path/path.h" -#include "async/async.h" -#include "rdi_make/rdi_make_local.h" -#include "coff/coff.h" -#include "coff/coff_parse.h" -#include "codeview/codeview.h" -#include "codeview/codeview_parse.h" -#include "msf/msf.h" -#include "msf/msf_parse.h" -#include "pdb/pdb.h" -#include "pdb/pdb_parse.h" -#include "pdb/pdb_stringize.h" -#include "rdi_from_pdb.h" - -//- rjf: [c] -#include "base/base_inc.c" -#include "os/os_inc.c" -#include "path/path.c" -#include "async/async.c" -#include "rdi_make/rdi_make_local.c" -#include "coff/coff.c" -#include "coff/coff_parse.c" -#include "codeview/codeview.c" -#include "codeview/codeview_parse.c" -#include "msf/msf.c" -#include "msf/msf_parse.c" -#include "pdb/pdb.c" -#include "pdb/pdb_parse.c" -#include "pdb/pdb_stringize.c" -#include "rdi_from_pdb.c" - -//////////////////////////////// -//~ rjf: Entry Point - -internal void -entry_point(CmdLine *cmdline) -{ - //- rjf: initialize state, unpack command line - Arena *arena = arena_alloc(); - B32 do_help = (cmd_line_has_flag(cmdline, str8_lit("help")) || - cmd_line_has_flag(cmdline, str8_lit("h")) || - cmd_line_has_flag(cmdline, str8_lit("?"))); - P2R_User2Convert *user2convert = p2r_user2convert_from_cmdln(arena, cmdline); - - //- rjf: display help - if(do_help || user2convert->errors.node_count != 0) - { - fprintf(stderr, "--- rdi_from_pdb --------------------------------------------------------------\n\n"); - - fprintf(stderr, "This utility converts debug information from PDBs into the RAD Debug Info\n"); - fprintf(stderr, "format. The following arguments are accepted:\n\n"); - - fprintf(stderr, "--exe: [optional] Specifies the path of the executable file for which the\n"); - fprintf(stderr, " debug info was generated.\n"); - fprintf(stderr, "--pdb: Specifies the path of the PDB debug info file to\n"); - fprintf(stderr, " convert.\n"); - fprintf(stderr, "--out: Specifies the path at which the output Breakpad debug\n"); - fprintf(stderr, " info will be written.\n\n"); - - if(!do_help) - { - for(String8Node *n = user2convert->errors.first; n != 0; n = n->next) - { - fprintf(stderr, "error(input): %.*s\n", str8_varg(n->string)); - } - } - os_abort(0); - } - - //- rjf: convert - P2R_Convert2Bake *convert2bake = 0; - ProfScope("convert") - { - convert2bake = p2r_convert(arena, user2convert); - } - - //- rjf: bake - P2R_Bake2Serialize *bake2srlz = 0; - ProfScope("bake") - { - bake2srlz = p2r_bake(arena, convert2bake); - } - - //- rjf: serialize - P2R_Serialize2File *srlz2file = 0; - ProfScope("serialize") - { - srlz2file = push_array(arena, P2R_Serialize2File, 1); - srlz2file->bundle = rdim_serialized_section_bundle_from_bake_results(&bake2srlz->bake_results); - } - - //- rjf: compress - P2R_Serialize2File *srlz2file_compressed = srlz2file; - if(cmd_line_has_flag(cmdline, str8_lit("compress"))) ProfScope("compress") - { - srlz2file_compressed = push_array(arena, P2R_Serialize2File, 1); - srlz2file_compressed = p2r_compress(arena, srlz2file); - } - - //- rjf: serialize - String8List blobs = rdim_file_blobs_from_section_bundle(arena, &srlz2file_compressed->bundle); - - //- rjf: write - ProfScope("write") - { - OS_Handle output_file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Write, user2convert->output_name); - U64 off = 0; - for(String8Node *n = blobs.first; n != 0; n = n->next) - { - os_file_write(output_file, r1u64(off, off+n->string.size), n->string.str); - off += n->string.size; - } - os_file_close(output_file); - } -} diff --git a/src/rdi_make/rdi_make_help.c b/src/rdi_make/rdi_make_help.c deleted file mode 100644 index 35ff0d9b..00000000 --- a/src/rdi_make/rdi_make_help.c +++ /dev/null @@ -1,925 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ rjf: Baking Stage Tasks - -//- rjf: bake string map building - -#define rdim_make_string_map_if_needed() do {if(in->maps[thread_idx] == 0) ProfScope("make map") {in->maps[thread_idx] = rdim_bake_string_map_loose_make(arena, in->top);}} while(0) - -ASYNC_WORK_DEF(rdim_bake_src_files_strings_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeSrcFilesStringsIn *in = (RDIM_BakeSrcFilesStringsIn *)input; - rdim_make_string_map_if_needed(); - ProfScope("bake src file strings") rdim_bake_string_map_loose_push_src_files(arena, in->top, in->maps[thread_idx], in->list); - ProfEnd(); - return 0; -} - -ASYNC_WORK_DEF(rdim_bake_units_strings_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeUnitsStringsIn *in = (RDIM_BakeUnitsStringsIn *)input; - rdim_make_string_map_if_needed(); - ProfScope("bake unit strings") rdim_bake_string_map_loose_push_units(arena, in->top, in->maps[thread_idx], in->list); - ProfEnd(); - return 0; -} - -ASYNC_WORK_DEF(rdim_bake_types_strings_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeTypesStringsIn *in = (RDIM_BakeTypesStringsIn *)input; - rdim_make_string_map_if_needed(); - ProfScope("bake type strings") - { - for(RDIM_BakeTypesStringsInNode *n = in->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_push_type_slice(arena, in->top, in->maps[thread_idx], n->v, n->count); - } - } - ProfEnd(); - return 0; -} - -ASYNC_WORK_DEF(rdim_bake_udts_strings_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeUDTsStringsIn *in = (RDIM_BakeUDTsStringsIn *)input; - rdim_make_string_map_if_needed(); - ProfScope("bake udt strings") - { - for(RDIM_BakeUDTsStringsInNode *n = in->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_push_udt_slice(arena, in->top, in->maps[thread_idx], n->v, n->count); - } - } - ProfEnd(); - return 0; -} - -ASYNC_WORK_DEF(rdim_bake_symbols_strings_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeSymbolsStringsIn *in = (RDIM_BakeSymbolsStringsIn *)input; - rdim_make_string_map_if_needed(); - ProfScope("bake symbol strings") - { - for(RDIM_BakeSymbolsStringsInNode *n = in->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_push_symbol_slice(arena, in->top, in->maps[thread_idx], n->v, n->count); - } - } - ProfEnd(); - return 0; -} - -ASYNC_WORK_DEF(rdim_bake_inline_site_strings_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeInlineSiteStringsIn *in = input; - rdim_make_string_map_if_needed(); - ProfScope("bake inline site strings") - { - for(RDIM_BakeInlineSiteStringsInNode *n = in->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_push_inline_site_slice(arena, in->top, in->maps[thread_idx], n->v, n->count); - } - } - ProfEnd(); - return 0; -} - -ASYNC_WORK_DEF(rdim_bake_scopes_strings_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeScopesStringsIn *in = (RDIM_BakeScopesStringsIn *)input; - rdim_make_string_map_if_needed(); - ProfScope("bake scope strings") - { - for(RDIM_BakeScopesStringsInNode *n = in->first; n != 0; n = n->next) - { - rdim_bake_string_map_loose_push_scope_slice(arena, in->top, in->maps[thread_idx], n->v, n->count); - } - } - ProfEnd(); - return 0; -} - -ASYNC_WORK_DEF(rdim_bake_line_tables_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeLineTablesIn *in = (RDIM_BakeLineTablesIn *)input; - RDIM_LineTableBakeResult *out = push_array(arena, RDIM_LineTableBakeResult, 1); - ProfScope("bake line tables") *out = rdim_bake_line_tables(arena, in->line_tables); - ProfEnd(); - return out; -} - -#undef rdim_make_string_map_if_needed - -//- rjf: bake string map joining - -ASYNC_WORK_DEF(rdim_bake_string_map_join_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_JoinBakeStringMapSlotsIn *in = (RDIM_JoinBakeStringMapSlotsIn *)input; - ProfScope("join bake string maps") - { - for(U64 src_map_idx = 0; src_map_idx < in->src_maps_count; src_map_idx += 1) - { - for(U64 slot_idx = in->slot_idx_range.min; slot_idx < in->slot_idx_range.max; slot_idx += 1) - { - B32 src_slots_good = (in->src_maps[src_map_idx] != 0 && in->src_maps[src_map_idx]->slots != 0); - B32 dst_slot_is_zero = (in->dst_map->slots[slot_idx] == 0); - if(src_slots_good && dst_slot_is_zero) - { - in->dst_map->slots[slot_idx] = in->src_maps[src_map_idx]->slots[slot_idx]; - } - else if(src_slots_good && in->src_maps[src_map_idx]->slots[slot_idx] != 0) - { - rdim_bake_string_chunk_list_concat_in_place(in->dst_map->slots[slot_idx], in->src_maps[src_map_idx]->slots[slot_idx]); - } - } - } - } - ProfEnd(); - return 0; -} - -//- rjf: bake string map sorting - -ASYNC_WORK_DEF(rdim_bake_string_map_sort_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_SortBakeStringMapSlotsIn *in = (RDIM_SortBakeStringMapSlotsIn *)input; - ProfScope("sort bake string chunk list map range") - { - for(U64 slot_idx = in->slot_idx; - slot_idx < in->slot_idx+in->slot_count; - slot_idx += 1) - { - if(in->src_map->slots[slot_idx] != 0) - { - if(in->src_map->slots[slot_idx]->total_count > 1) - { - in->dst_map->slots[slot_idx] = push_array(arena, RDIM_BakeStringChunkList, 1); - *in->dst_map->slots[slot_idx] = rdim_bake_string_chunk_list_sorted_from_unsorted(arena, in->src_map->slots[slot_idx]); - } - else - { - in->dst_map->slots[slot_idx] = in->src_map->slots[slot_idx]; - } - } - } - } - ProfEnd(); - return 0; -} - -//- rjf: pass 1: interner/deduper map builds - -ASYNC_WORK_DEF(rdim_build_bake_name_map_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BuildBakeNameMapIn *in = (RDIM_BuildBakeNameMapIn *)input; - RDIM_BakeNameMap *name_map = 0; - ProfScope("build name map %i", in->k) name_map = rdim_bake_name_map_from_kind_params(arena, in->k, in->type_indices, in->params); - ProfEnd(); - return name_map; -} - -//- rjf: pass 2: string-map-dependent debug info stream builds - -ASYNC_WORK_DEF(rdim_bake_units_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeUnitsIn *in = (RDIM_BakeUnitsIn *)input; - RDIM_UnitBakeResult *out = push_array(arena, RDIM_UnitBakeResult, 1); - ProfScope("bake units") *out = rdim_bake_units(arena, in->strings, in->path_tree, in->units); - ProfEnd(); - return out; -} - -ASYNC_WORK_DEF(rdim_bake_unit_vmap_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeUnitVMapIn *in = (RDIM_BakeUnitVMapIn *)input; - RDIM_UnitVMapBakeResult *out = push_array(arena, RDIM_UnitVMapBakeResult, 1); - ProfScope("bake unit vmap") *out = rdim_bake_unit_vmap(arena, in->units); - ProfEnd(); - return out; -} - -ASYNC_WORK_DEF(rdim_bake_src_files_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeSrcFilesIn *in = (RDIM_BakeSrcFilesIn *)input; - RDIM_SrcFileBakeResult *out = push_array(arena, RDIM_SrcFileBakeResult, 1); - ProfScope("bake src files") *out = rdim_bake_src_files(arena, in->strings, in->path_tree, in->src_files); - ProfEnd(); - return out; -} - -ASYNC_WORK_DEF(rdim_bake_udts_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeUDTsIn *in = (RDIM_BakeUDTsIn *)input; - RDIM_UDTBakeResult *out = push_array(arena, RDIM_UDTBakeResult, 1); - ProfScope("bake udts") *out = rdim_bake_udts(arena, in->strings, in->type_indices, in->udts); - ProfEnd(); - return out; -} - -ASYNC_WORK_DEF(rdim_bake_global_variables_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeGlobalVariablesIn *in = (RDIM_BakeGlobalVariablesIn *)input; - RDIM_GlobalVariableBakeResult *out = push_array(arena, RDIM_GlobalVariableBakeResult, 1); - ProfScope("bake global variables") *out = rdim_bake_global_variables(arena, in->strings, in->type_indices, in->global_variables); - ProfEnd(); - return out; -} - -ASYNC_WORK_DEF(rdim_bake_global_vmap_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeGlobalVMapIn *in = (RDIM_BakeGlobalVMapIn *)input; - RDIM_GlobalVMapBakeResult *out = push_array(arena, RDIM_GlobalVMapBakeResult, 1); - ProfScope("bake global vmap") *out = rdim_bake_global_vmap(arena, in->global_variables); - ProfEnd(); - return out; -} - -ASYNC_WORK_DEF(rdim_bake_thread_variables_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeThreadVariablesIn *in = (RDIM_BakeThreadVariablesIn *)input; - RDIM_ThreadVariableBakeResult *out = push_array(arena, RDIM_ThreadVariableBakeResult, 1); - ProfScope("bake thread variables") *out = rdim_bake_thread_variables(arena, in->strings, in->type_indices, in->thread_variables); - ProfEnd(); - return out; -} - -ASYNC_WORK_DEF(rdim_bake_procedures_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeProceduresIn *in = (RDIM_BakeProceduresIn *)input; - RDIM_ProcedureBakeResult *out = push_array(arena, RDIM_ProcedureBakeResult, 1); - ProfScope("bake procedures") *out = rdim_bake_procedures(arena, in->strings, in->type_indices, in->location_blocks, in->location_data_blobs, in->procedures); - ProfEnd(); - return out; -} - -ASYNC_WORK_DEF(rdim_bake_scopes_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeScopesIn *in = (RDIM_BakeScopesIn *)input; - RDIM_ScopeBakeResult *out = push_array(arena, RDIM_ScopeBakeResult, 1); - ProfScope("bake scopes") *out = rdim_bake_scopes(arena, in->strings, in->type_indices, in->location_blocks, in->location_data_blobs, in->scopes); - ProfEnd(); - return out; -} - -ASYNC_WORK_DEF(rdim_bake_scope_vmap_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeScopeVMapIn *in = (RDIM_BakeScopeVMapIn *)input; - RDIM_ScopeVMapBakeResult *out = push_array(arena, RDIM_ScopeVMapBakeResult, 1); - ProfScope("bake scope vmap") *out = rdim_bake_scope_vmap(arena, in->scopes); - ProfEnd(); - return out; -} - -ASYNC_WORK_DEF(rdim_bake_inline_sites_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeInlineSitesIn *in = (RDIM_BakeInlineSitesIn *)input; - RDIM_InlineSiteBakeResult *out = push_array(arena, RDIM_InlineSiteBakeResult, 1); - ProfScope("bake inline sites") *out = rdim_bake_inline_sites(arena, in->strings, in->type_indices, in->inline_sites); - ProfEnd(); - return out; -} - -ASYNC_WORK_DEF(rdim_bake_file_paths_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeFilePathsIn *in = (RDIM_BakeFilePathsIn *)input; - RDIM_FilePathBakeResult *out = push_array(arena, RDIM_FilePathBakeResult, 1); - ProfScope("bake file paths") *out = rdim_bake_file_paths(arena, in->strings, in->path_tree); - ProfEnd(); - return out; -} - -ASYNC_WORK_DEF(rdim_bake_strings_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeStringsIn *in = (RDIM_BakeStringsIn *)input; - RDIM_StringBakeResult *out = push_array(arena, RDIM_StringBakeResult, 1); - ProfScope("bake strings") *out = rdim_bake_strings(arena, in->strings); - ProfEnd(); - return out; -} - -//- rjf: pass 3: idx-run-map-dependent debug info stream builds - -ASYNC_WORK_DEF(rdim_bake_type_nodes_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeTypeNodesIn *in = (RDIM_BakeTypeNodesIn *)input; - RDIM_TypeNodeBakeResult *out = push_array(arena, RDIM_TypeNodeBakeResult, 1); - ProfScope("bake type nodes") *out = rdim_bake_types(arena, in->strings, in->idx_runs, in->type_indices, in->types); - ProfEnd(); - return out; -} - -ASYNC_WORK_DEF(rdim_bake_name_map_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeNameMapIn *in = (RDIM_BakeNameMapIn *)input; - RDIM_NameMapBakeResult *out = push_array(arena, RDIM_NameMapBakeResult, 1); - ProfScope("bake name map %i", in->kind) *out = rdim_bake_name_map(arena, in->strings, in->idx_runs, in->map); - ProfEnd(); - return out; -} - -ASYNC_WORK_DEF(rdim_bake_idx_runs_work) -{ - ProfBeginFunction(); - Arena *arena = rdim_help_state->work_thread_arenas[thread_idx]; - RDIM_BakeIdxRunsIn *in = (RDIM_BakeIdxRunsIn *)input; - RDIM_IndexRunBakeResult *out = push_array(arena, RDIM_IndexRunBakeResult, 1); - ProfScope("bake idx runs") *out = rdim_bake_index_runs(arena, in->idx_runs); - ProfEnd(); - return out; -} - -internal RDIM_HelpState * -rdim_help_init(void) -{ - Arena *arena = arena_alloc(); - RDIM_HelpState *state = push_array(arena, RDIM_HelpState, 1); - state->arena = arena; - state->work_thread_arenas_count = async_thread_count(); - state->work_thread_arenas = push_array(arena, Arena *, state->work_thread_arenas_count); - for EachIndex(idx, state->work_thread_arenas_count) - { - state->work_thread_arenas[idx] = arena_alloc(); - } - return state; -} - -internal RDIM_BakeResults -rdim_bake(RDIM_HelpState *state, RDIM_BakeParams *in_params) -{ - Temp scratch = scratch_begin(0,0); - RDIM_BakeResults out = {0}; - - rdim_help_state = state; - - //////////////////////////////// - // compute type indices - - RDI_U64 *type_indices = rdim_make_type_indices(scratch.arena, &in_params->types); - - ////////////////////////////// - //- rjf: kick off line tables baking - // - ASYNC_Task *bake_line_tables_task = 0; - { - RDIM_BakeLineTablesIn *in = push_array(scratch.arena, RDIM_BakeLineTablesIn, 1); - in->line_tables = &in_params->line_tables; - bake_line_tables_task = async_task_launch(scratch.arena, rdim_bake_line_tables_work, .input = in); - } - - ////////////////////////////// - //- rjf: build interned path tree - // - RDIM_BakePathTree *path_tree = 0; - ProfScope("build interned path tree") - { - path_tree = rdim_bake_path_tree_from_params(state->arena, in_params); - } - - ////////////////////////////// - //- rjf: kick off string map building tasks - // - RDIM_BakeStringMapTopology bake_string_map_topology = {(64 + - in_params->procedures.total_count*1 + - in_params->global_variables.total_count*1 + - in_params->thread_variables.total_count*1 + - in_params->types.total_count/2)}; - RDIM_BakeStringMapLoose **bake_string_maps__in_progress = push_array(scratch.arena, RDIM_BakeStringMapLoose *, async_thread_count()); - ASYNC_TaskList bake_string_map_build_tasks = {0}; - { - // rjf: src files - ProfScope("kick off src files string map build task") - { - RDIM_BakeSrcFilesStringsIn *in = push_array(scratch.arena, RDIM_BakeSrcFilesStringsIn, 1); - in->top = &bake_string_map_topology; - in->maps = bake_string_maps__in_progress; - in->list = &in_params->src_files; - async_task_list_push(scratch.arena, &bake_string_map_build_tasks, async_task_launch(scratch.arena, rdim_bake_src_files_strings_work, .input = in)); - } - - // rjf: units - ProfScope("kick off units string map build task") - { - RDIM_BakeUnitsStringsIn *in = push_array(scratch.arena, RDIM_BakeUnitsStringsIn, 1); - in->top = &bake_string_map_topology; - in->maps = bake_string_maps__in_progress; - in->list = &in_params->units; - async_task_list_push(scratch.arena, &bake_string_map_build_tasks, async_task_launch(scratch.arena, rdim_bake_units_strings_work, .input = in)); - } - - // rjf: types - ProfScope("kick off types string map build tasks") - { - U64 items_per_task = 4096; - U64 num_tasks = (in_params->types.total_count+items_per_task-1)/items_per_task; - RDIM_TypeChunkNode *chunk = in_params->types.first; - U64 chunk_off = 0; - for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) - { - RDIM_BakeTypesStringsIn *in = push_array(scratch.arena, RDIM_BakeTypesStringsIn, 1); - in->top = &bake_string_map_topology; - in->maps = bake_string_maps__in_progress; - U64 items_left = items_per_task; - for(;chunk != 0 && items_left > 0;) - { - U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); - RDIM_BakeTypesStringsInNode *n = push_array(scratch.arena, RDIM_BakeTypesStringsInNode, 1); - SLLQueuePush(in->first, in->last, n); - n->v = chunk->v + chunk_off; - n->count = items_in_this_chunk; - chunk_off += items_in_this_chunk; - items_left -= items_in_this_chunk; - if(chunk_off >= chunk->count) - { - chunk = chunk->next; - chunk_off = 0; - } - } - async_task_list_push(scratch.arena, &bake_string_map_build_tasks, async_task_launch(scratch.arena, rdim_bake_types_strings_work, .input = in)); - } - } - - // rjf: UDTs - ProfScope("kick off udts string map build tasks") - { - U64 items_per_task = 4096; - U64 num_tasks = (in_params->udts.total_count+items_per_task-1)/items_per_task; - RDIM_UDTChunkNode *chunk = in_params->udts.first; - U64 chunk_off = 0; - for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) - { - RDIM_BakeUDTsStringsIn *in = push_array(scratch.arena, RDIM_BakeUDTsStringsIn, 1); - in->top = &bake_string_map_topology; - in->maps = bake_string_maps__in_progress; - U64 items_left = items_per_task; - for(;chunk != 0 && items_left > 0;) - { - U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); - RDIM_BakeUDTsStringsInNode *n = push_array(scratch.arena, RDIM_BakeUDTsStringsInNode, 1); - SLLQueuePush(in->first, in->last, n); - n->v = chunk->v + chunk_off; - n->count = items_in_this_chunk; - chunk_off += items_in_this_chunk; - items_left -= items_in_this_chunk; - if(chunk_off >= chunk->count) - { - chunk = chunk->next; - chunk_off = 0; - } - } - async_task_list_push(scratch.arena, &bake_string_map_build_tasks, async_task_launch(scratch.arena, rdim_bake_udts_strings_work, .input = in)); - } - } - - // rjf: symbols - ProfScope("kick off symbols string map build tasks") - { - RDIM_SymbolChunkList *symbol_lists[] = - { - &in_params->global_variables, - &in_params->thread_variables, - &in_params->procedures, - }; - for(U64 list_idx = 0; list_idx < ArrayCount(symbol_lists); list_idx += 1) - { - U64 items_per_task = 4096; - U64 num_tasks = (symbol_lists[list_idx]->total_count+items_per_task-1)/items_per_task; - RDIM_SymbolChunkNode *chunk = symbol_lists[list_idx]->first; - U64 chunk_off = 0; - for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) - { - RDIM_BakeSymbolsStringsIn *in = push_array(scratch.arena, RDIM_BakeSymbolsStringsIn, 1); - in->top = &bake_string_map_topology; - in->maps = bake_string_maps__in_progress; - U64 items_left = items_per_task; - for(;chunk != 0 && items_left > 0;) - { - U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); - RDIM_BakeSymbolsStringsInNode *n = push_array(scratch.arena, RDIM_BakeSymbolsStringsInNode, 1); - SLLQueuePush(in->first, in->last, n); - n->v = chunk->v + chunk_off; - n->count = items_in_this_chunk; - chunk_off += items_in_this_chunk; - items_left -= items_in_this_chunk; - if(chunk_off >= chunk->count) - { - chunk = chunk->next; - chunk_off = 0; - } - } - async_task_list_push(scratch.arena, &bake_string_map_build_tasks, async_task_launch(scratch.arena, rdim_bake_symbols_strings_work, .input = in)); - } - } - } - - ProfScope("kick off inline site string map build task") - { - U64 items_per_task = 4096; - U64 num_tasks = CeilIntegerDiv(in_params->inline_sites.total_count, items_per_task); - RDIM_InlineSiteChunkNode *chunk = in_params->inline_sites.first; - U64 chunk_off = 0; - for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) - { - RDIM_BakeInlineSiteStringsIn *in = push_array(scratch.arena, RDIM_BakeInlineSiteStringsIn, 1); - in->top = &bake_string_map_topology; - in->maps = bake_string_maps__in_progress; - U64 items_left = items_per_task; - for(;chunk != 0 && items_left > 0;) - { - U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); - RDIM_BakeInlineSiteStringsInNode *n = push_array(scratch.arena, RDIM_BakeInlineSiteStringsInNode, 1); - SLLQueuePush(in->first, in->last, n); - n->v = chunk->v + chunk_off; - n->count = items_in_this_chunk; - chunk_off += items_in_this_chunk; - items_left -= items_in_this_chunk; - if(chunk_off >= chunk->count) - { - chunk = chunk->next; - chunk_off = 0; - } - } - async_task_list_push(scratch.arena, &bake_string_map_build_tasks, async_task_launch(scratch.arena, rdim_bake_inline_site_strings_work, .input = in)); - } - } - - // rjf: scope chunks - ProfScope("kick off scope chunks string map build tasks") - { - U64 items_per_task = 4096; - U64 num_tasks = (in_params->scopes.total_count+items_per_task-1)/items_per_task; - RDIM_ScopeChunkNode *chunk = in_params->scopes.first; - U64 chunk_off = 0; - for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) - { - RDIM_BakeScopesStringsIn *in = push_array(scratch.arena, RDIM_BakeScopesStringsIn, 1); - in->top = &bake_string_map_topology; - in->maps = bake_string_maps__in_progress; - U64 items_left = items_per_task; - for(;chunk != 0 && items_left > 0;) - { - U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); - RDIM_BakeScopesStringsInNode *n = push_array(scratch.arena, RDIM_BakeScopesStringsInNode, 1); - SLLQueuePush(in->first, in->last, n); - n->v = chunk->v + chunk_off; - n->count = items_in_this_chunk; - chunk_off += items_in_this_chunk; - items_left -= items_in_this_chunk; - if(chunk_off >= chunk->count) - { - chunk = chunk->next; - chunk_off = 0; - } - } - async_task_list_push(scratch.arena, &bake_string_map_build_tasks, async_task_launch(scratch.arena, rdim_bake_scopes_strings_work, .input = in)); - } - } - } - - ////////////////////////////// - //- rjf: kick off name map building tasks - // - RDIM_BuildBakeNameMapIn build_bake_name_map_in[RDI_NameMapKind_COUNT] = {0}; - ASYNC_Task *build_bake_name_map_task[RDI_NameMapKind_COUNT] = {0}; - for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); - k < RDI_NameMapKind_COUNT; - k = (RDI_NameMapKind)(k+1)) - { - build_bake_name_map_in[k].k = k; - build_bake_name_map_in[k].type_indices = type_indices; - build_bake_name_map_in[k].params = in_params; - build_bake_name_map_task[k] = async_task_launch(scratch.arena, rdim_build_bake_name_map_work, .input = &build_bake_name_map_in[k]); - } - - ////////////////////////////// - //- rjf: join string map building tasks - // - ProfScope("join string map building tasks") - { - for(ASYNC_TaskNode *n = bake_string_map_build_tasks.first; n != 0; n = n->next) - { - async_task_join(n->v); - } - } - - ////////////////////////////// - //- rjf: produce joined string map - // - RDIM_BakeStringMapLoose *unsorted_bake_string_map = rdim_bake_string_map_loose_make(state->arena, &bake_string_map_topology); - ProfScope("produce joined string map") - { - U64 slots_per_task = 16384; - U64 num_tasks = (bake_string_map_topology.slots_count+slots_per_task-1)/slots_per_task; - ASYNC_Task **tasks = push_array(scratch.arena, ASYNC_Task *, num_tasks); - - // rjf: kickoff tasks - for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) - { - RDIM_JoinBakeStringMapSlotsIn *in = push_array(scratch.arena, RDIM_JoinBakeStringMapSlotsIn, 1); - in->top = &bake_string_map_topology; - in->src_maps = bake_string_maps__in_progress; - in->src_maps_count = async_thread_count(); - in->dst_map = unsorted_bake_string_map; - in->slot_idx_range = r1u64(task_idx*slots_per_task, task_idx*slots_per_task + slots_per_task); - in->slot_idx_range.max = Min(in->slot_idx_range.max, in->top->slots_count); - tasks[task_idx] = async_task_launch(scratch.arena, rdim_bake_string_map_join_work, .input = in); - } - - // rjf: join tasks - for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) - { - async_task_join(tasks[task_idx]); - } - - // rjf: insert small top-level stuff - rdim_bake_string_map_loose_push_top_level_info(state->arena, &bake_string_map_topology, unsorted_bake_string_map, &in_params->top_level_info); - rdim_bake_string_map_loose_push_binary_sections(state->arena, &bake_string_map_topology, unsorted_bake_string_map, &in_params->binary_sections); - rdim_bake_string_map_loose_push_path_tree(state->arena, &bake_string_map_topology, unsorted_bake_string_map, path_tree); - } - - ////////////////////////////// - //- rjf: kick off string map sorting tasks - // - ASYNC_TaskList sort_bake_string_map_tasks = {0}; - RDIM_BakeStringMapLoose *sorted_bake_string_map__in_progress = rdim_bake_string_map_loose_make(state->arena, &bake_string_map_topology); - { - U64 slots_per_task = 4096; - U64 num_tasks = (bake_string_map_topology.slots_count+slots_per_task-1)/slots_per_task; - for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) - { - RDIM_SortBakeStringMapSlotsIn *in = push_array(scratch.arena, RDIM_SortBakeStringMapSlotsIn, 1); - { - in->top = &bake_string_map_topology; - in->src_map = unsorted_bake_string_map; - in->dst_map = sorted_bake_string_map__in_progress; - in->slot_idx = task_idx*slots_per_task; - in->slot_count = slots_per_task; - if(in->slot_idx+in->slot_count > bake_string_map_topology.slots_count) - { - in->slot_count = bake_string_map_topology.slots_count - in->slot_idx; - } - } - async_task_list_push(scratch.arena, &sort_bake_string_map_tasks, async_task_launch(scratch.arena, rdim_bake_string_map_sort_work, .input = in)); - } - } - - ////////////////////////////// - //- rjf: join string map sorting tasks - // - ProfScope("join string map sorting tasks") - { - for(ASYNC_TaskNode *n = sort_bake_string_map_tasks.first; n != 0; n = n->next) - { - async_task_join(n->v); - } - } - RDIM_BakeStringMapLoose *sorted_bake_string_map = sorted_bake_string_map__in_progress; - - ////////////////////////////// - //- rjf: build finalized string map - // - ProfBegin("build finalized string map base indices"); - RDIM_BakeStringMapBaseIndices bake_string_map_base_idxes = rdim_bake_string_map_base_indices_from_map_loose(state->arena, &bake_string_map_topology, sorted_bake_string_map); - ProfEnd(); - ProfBegin("build finalized string map"); - RDIM_BakeStringMapTight bake_strings = rdim_bake_string_map_tight_from_loose(state->arena, &bake_string_map_topology, &bake_string_map_base_idxes, sorted_bake_string_map); - ProfEnd(); - - ////////////////////////////// - //- rjf: kick off pass 2 tasks - // - RDIM_BakeUnitsIn bake_units_top_level_in = {&bake_strings, path_tree, &in_params->units}; - ASYNC_Task *bake_units_task = async_task_launch(scratch.arena, rdim_bake_units_work, .input = &bake_units_top_level_in); - RDIM_BakeUnitVMapIn bake_unit_vmap_in = {&in_params->units}; - ASYNC_Task *bake_unit_vmap_task = async_task_launch(scratch.arena, rdim_bake_unit_vmap_work, .input = &bake_unit_vmap_in); - RDIM_BakeSrcFilesIn bake_src_files_in = {&bake_strings, path_tree, &in_params->src_files}; - ASYNC_Task *bake_src_files_task = async_task_launch(scratch.arena, rdim_bake_src_files_work, .input = &bake_src_files_in); - RDIM_BakeUDTsIn bake_udts_in = {&bake_strings, &in_params->udts, type_indices}; - ASYNC_Task *bake_udts_task = async_task_launch(scratch.arena, rdim_bake_udts_work, .input = &bake_udts_in); - RDIM_BakeGlobalVMapIn bake_global_vmap_in = {&in_params->global_variables}; - ASYNC_Task *bake_global_vmap_task = async_task_launch(scratch.arena, rdim_bake_global_vmap_work, .input = &bake_global_vmap_in); - RDIM_BakeScopeVMapIn bake_scope_vmap_in = {&in_params->scopes}; - ASYNC_Task *bake_scope_vmap_task = async_task_launch(scratch.arena, rdim_bake_scope_vmap_work, .input = &bake_scope_vmap_in); - RDIM_BakeInlineSitesIn bake_inline_sites_in = {&bake_strings, &in_params->inline_sites, type_indices}; - ASYNC_Task *bake_inline_sites_task = async_task_launch(scratch.arena, rdim_bake_inline_sites_work, .input = &bake_inline_sites_in); - RDIM_BakeFilePathsIn bake_file_paths_in = {&bake_strings, path_tree}; - ASYNC_Task *bake_file_paths_task = async_task_launch(scratch.arena, rdim_bake_file_paths_work, .input = &bake_file_paths_in); - RDIM_BakeStringsIn bake_strings_in = {&bake_strings}; - ASYNC_Task *bake_strings_task = async_task_launch(scratch.arena, rdim_bake_strings_work, .input = &bake_strings_in); - - RDIM_String8List location_blocks = {0}; - RDIM_String8List location_data_blobs = {0}; - - // reserve null location block for opl - rdim_location_block_chunk_list_push_array(state->arena, &location_blocks, 1); - - // TODO: export location instead of VOFF - RDIM_BakeThreadVariablesIn bake_thread_variables_in = {&bake_strings, &in_params->thread_variables, type_indices}; - ASYNC_Task *bake_thread_variables_task = async_task_launch(scratch.arena, rdim_bake_thread_variables_work, .input = &bake_thread_variables_in); - ProfScope("thread variables") out.thread_variables = *async_task_join_struct(bake_thread_variables_task, RDIM_ThreadVariableBakeResult); - - // TODO: export location instead of VOFF - RDIM_BakeGlobalVariablesIn bake_global_variables_in = {&bake_strings, &in_params->global_variables, type_indices}; - ASYNC_Task *bake_global_variables_task = async_task_launch(scratch.arena, rdim_bake_global_variables_work, .input = &bake_global_variables_in); - ProfScope("global variables") out.global_variables = *async_task_join_struct(bake_global_variables_task, RDIM_GlobalVariableBakeResult); - - RDIM_BakeScopesIn bake_scopes_in = {&bake_strings, &in_params->scopes, type_indices, &location_blocks, &location_data_blobs}; - ASYNC_Task *bake_scopes_task = async_task_launch(scratch.arena, rdim_bake_scopes_work, .input = &bake_scopes_in); - ProfScope("scopes") out.scopes = *async_task_join_struct(bake_scopes_task, RDIM_ScopeBakeResult); - - RDIM_BakeProceduresIn bake_procedures_in = {&bake_strings, &in_params->procedures, type_indices, &location_blocks, &location_data_blobs}; - ASYNC_Task *bake_procedures_task = async_task_launch(scratch.arena, rdim_bake_procedures_work, .input = &bake_procedures_in); - ProfScope("procedures") out.procedures = *async_task_join_struct(bake_procedures_task, RDIM_ProcedureBakeResult); - - ////////////////////////////// - //- rjf: join name map building tasks - // - RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT] = {0}; - ProfScope("join name map building tasks") - { - for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); - k < RDI_NameMapKind_COUNT; - k = (RDI_NameMapKind)(k+1)) - { - name_maps[k] = async_task_join_struct(build_bake_name_map_task[k], RDIM_BakeNameMap); - } - } - - ////////////////////////////// - //- rjf: build interned idx run map - // - RDIM_BakeIdxRunMap *idx_runs = 0; - ProfScope("build interned idx run map") - { - idx_runs = rdim_bake_idx_run_map_from_params(state->arena, name_maps, type_indices, in_params); - } - - ////////////////////////////// - //- rjf: do small top-level bakes - // - ProfScope("top level info") out.top_level_info = rdim_bake_top_level_info(state->arena, &bake_strings, &in_params->top_level_info); - ProfScope("binary sections") out.binary_sections = rdim_bake_binary_sections(state->arena, &bake_strings, &in_params->binary_sections); - ProfScope("top level name maps section") out.top_level_name_maps = rdim_bake_name_maps_top_level(state->arena, &bake_strings, idx_runs, name_maps); - - ////////////////////////////// - //- rjf: kick off pass 3 tasks - // - RDIM_BakeTypeNodesIn bake_type_nodes_in = {&bake_strings, idx_runs, &in_params->types, type_indices}; - ASYNC_Task *bake_type_nodes_task = async_task_launch(scratch.arena, rdim_bake_type_nodes_work, .input = &bake_type_nodes_in); - ASYNC_Task *bake_name_maps_tasks[RDI_NameMapKind_COUNT] = {0}; - { - for EachNonZeroEnumVal(RDI_NameMapKind, k) - { - if(name_maps[k] == 0 || name_maps[k]->name_count == 0) - { - continue; - } - RDIM_BakeNameMapIn *in = push_array(scratch.arena, RDIM_BakeNameMapIn, 1); - in->strings = &bake_strings; - in->idx_runs = idx_runs; - in->map = name_maps[k]; - in->kind = k; - bake_name_maps_tasks[k] = async_task_launch(scratch.arena, rdim_bake_name_map_work, .input = in); - } - } - RDIM_BakeIdxRunsIn bake_idx_runs_in = {idx_runs}; - ASYNC_Task *bake_idx_runs_task = async_task_launch(scratch.arena, rdim_bake_idx_runs_work, .input = &bake_idx_runs_in); - - ////////////////////////////// - //- rjf: join remaining completed bakes - // - ProfScope("top-level units info") out.units = *async_task_join_struct(bake_units_task, RDIM_UnitBakeResult); - ProfScope("unit vmap") out.unit_vmap = *async_task_join_struct(bake_unit_vmap_task, RDIM_UnitVMapBakeResult); - ProfScope("source files") out.src_files = *async_task_join_struct(bake_src_files_task, RDIM_SrcFileBakeResult); - ProfScope("UDTs") out.udts = *async_task_join_struct(bake_udts_task, RDIM_UDTBakeResult); - ProfScope("global vmap") out.global_vmap = *async_task_join_struct(bake_global_vmap_task, RDIM_GlobalVMapBakeResult); - ProfScope("scope vmap") out.scope_vmap = *async_task_join_struct(bake_scope_vmap_task, RDIM_ScopeVMapBakeResult); - ProfScope("inline sites") out.inline_sites = *async_task_join_struct(bake_inline_sites_task, RDIM_InlineSiteBakeResult); - ProfScope("file paths") out.file_paths = *async_task_join_struct(bake_file_paths_task, RDIM_FilePathBakeResult); - ProfScope("strings") out.strings = *async_task_join_struct(bake_strings_task, RDIM_StringBakeResult); - ProfScope("type nodes") out.type_nodes = *async_task_join_struct(bake_type_nodes_task, RDIM_TypeNodeBakeResult); - ProfScope("idx runs") out.idx_runs = *async_task_join_struct(bake_idx_runs_task, RDIM_IndexRunBakeResult); - ProfScope("line tables") out.line_tables = *async_task_join_struct(bake_line_tables_task, RDIM_LineTableBakeResult); - - ////////////////////////////// - //- rjf: join individual name map bakes - // - RDIM_NameMapBakeResult name_map_bakes[RDI_NameMapKind_COUNT] = {0}; - ProfScope("name maps") - { - for EachNonZeroEnumVal(RDI_NameMapKind, k) - { - RDIM_NameMapBakeResult *bake = async_task_join_struct(bake_name_maps_tasks[k], RDIM_NameMapBakeResult); - if(bake != 0) - { - name_map_bakes[k] = *bake; - } - } - } - - ////////////////////////////// - //- rjf: join all individual name map bakes - // - ProfScope("join all name map bakes into final name map bake") - { - out.name_maps = rdim_name_map_bake_results_combine(state->arena, name_map_bakes, ArrayCount(name_map_bakes)); - } - - - //////////////////////////////// - - out.location_blocks = rdim_str8_list_join(state->arena, &location_blocks, rdim_str8(0,0)); - out.location_data = rdim_str8_list_join(state->arena, &location_data_blobs, rdim_str8(0,0)); - - rdim_help_state = 0; - - scratch_end(scratch); - return out; -} - -internal RDIM_SerializedSectionBundle -rdim_compress(Arena *arena, RDIM_SerializedSectionBundle *in) -{ - RDIM_SerializedSectionBundle out = {0}; - - //- rjf: set up compression context - rr_lzb_simple_context ctx = {0}; - ctx.m_tableSizeBits = 14; - ctx.m_hashTable = push_array(arena, U16, 1<sections[k]; - RDIM_SerializedSection *dst = &out.sections[k]; - MemoryCopyStruct(dst, src); - - // rjf: determine if this section should be compressed - B32 should_compress = 1; - - // rjf: compress if needed - if(should_compress) - { - MemoryZero(ctx.m_hashTable, sizeof(U16)*(1<data = push_array_no_zero(arena, U8, src->encoded_size); - dst->encoded_size = rr_lzb_simple_encode_veryfast(&ctx, src->data, src->encoded_size, dst->data); - dst->unpacked_size = src->encoded_size; - dst->encoding = RDI_SectionEncoding_LZB; - } - } - - return out; -} diff --git a/src/rdi_make/rdi_make_help.h b/src/rdi_make/rdi_make_help.h deleted file mode 100644 index 08c64391..00000000 --- a/src/rdi_make/rdi_make_help.h +++ /dev/null @@ -1,342 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -#ifndef RDIM_MAKE_HELP -#define RDIM_MAKE_HELP - -//- rjf: line table baking task types - -typedef struct RDIM_BakeLineTablesIn RDIM_BakeLineTablesIn; -struct RDIM_BakeLineTablesIn -{ - RDIM_LineTableChunkList *line_tables; -}; - -//- rjf: string map baking task types - -typedef struct RDIM_BakeSrcFilesStringsIn RDIM_BakeSrcFilesStringsIn; -struct RDIM_BakeSrcFilesStringsIn -{ - RDIM_BakeStringMapTopology *top; - RDIM_BakeStringMapLoose **maps; - RDIM_SrcFileChunkList *list; -}; - -typedef struct RDIM_BakeUnitsStringsIn RDIM_BakeUnitsStringsIn; -struct RDIM_BakeUnitsStringsIn -{ - RDIM_BakeStringMapTopology *top; - RDIM_BakeStringMapLoose **maps; - RDIM_UnitChunkList *list; -}; - -typedef struct RDIM_BakeUDTsStringsInNode RDIM_BakeUDTsStringsInNode; -struct RDIM_BakeUDTsStringsInNode -{ - RDIM_BakeUDTsStringsInNode *next; - RDIM_UDT *v; - RDI_U64 count; -}; - -typedef struct RDIM_BakeTypesStringsInNode RDIM_BakeTypesStringsInNode; -struct RDIM_BakeTypesStringsInNode -{ - RDIM_BakeTypesStringsInNode *next; - RDIM_Type *v; - RDI_U64 count; -}; - -typedef struct RDIM_BakeTypesStringsIn RDIM_BakeTypesStringsIn; -struct RDIM_BakeTypesStringsIn -{ - RDIM_BakeStringMapTopology *top; - RDIM_BakeStringMapLoose **maps; - RDIM_BakeTypesStringsInNode *first; - RDIM_BakeTypesStringsInNode *last; -}; - -typedef struct RDIM_BakeUDTsStringsIn RDIM_BakeUDTsStringsIn; -struct RDIM_BakeUDTsStringsIn -{ - RDIM_BakeStringMapTopology *top; - RDIM_BakeStringMapLoose **maps; - RDIM_BakeUDTsStringsInNode *first; - RDIM_BakeUDTsStringsInNode *last; -}; - -typedef struct RDIM_BakeSymbolsStringsInNode RDIM_BakeSymbolsStringsInNode; -struct RDIM_BakeSymbolsStringsInNode -{ - RDIM_BakeSymbolsStringsInNode *next; - RDIM_Symbol *v; - RDI_U64 count; -}; - -typedef struct RDIM_BakeSymbolsStringsIn RDIM_BakeSymbolsStringsIn; -struct RDIM_BakeSymbolsStringsIn -{ - RDIM_BakeStringMapTopology *top; - RDIM_BakeStringMapLoose **maps; - RDIM_BakeSymbolsStringsInNode *first; - RDIM_BakeSymbolsStringsInNode *last; -}; - -typedef struct RDIM_BakeInlineSiteStringsInNode RDIM_BakeInlineSiteStringsInNode; -struct RDIM_BakeInlineSiteStringsInNode -{ - RDIM_BakeInlineSiteStringsInNode *next; - RDIM_InlineSite *v; - RDI_U64 count; -}; - -typedef struct RDIM_BakeInlineSiteStringsIn RDIM_BakeInlineSiteStringsIn; -struct RDIM_BakeInlineSiteStringsIn -{ - RDIM_BakeStringMapTopology *top; - RDIM_BakeStringMapLoose **maps; - RDIM_BakeInlineSiteStringsInNode *first; - RDIM_BakeInlineSiteStringsInNode *last; -}; - -typedef struct RDIM_BakeScopesStringsInNode RDIM_BakeScopesStringsInNode; -struct RDIM_BakeScopesStringsInNode -{ - RDIM_BakeScopesStringsInNode *next; - RDIM_Scope *v; - RDI_U64 count; -}; - -typedef struct RDIM_BakeScopesStringsIn RDIM_BakeScopesStringsIn; -struct RDIM_BakeScopesStringsIn -{ - RDIM_BakeStringMapTopology *top; - RDIM_BakeStringMapLoose **maps; - RDIM_BakeScopesStringsInNode *first; - RDIM_BakeScopesStringsInNode *last; -}; - -//- rjf: OLD string map baking types - -typedef struct RDIM_BuildBakeStringMapIn RDIM_BuildBakeStringMapIn; -struct RDIM_BuildBakeStringMapIn -{ - RDIM_BakePathTree *path_tree; - RDIM_BakeParams *params; -}; - -typedef struct RDIM_BuildBakeNameMapIn RDIM_BuildBakeNameMapIn; -struct RDIM_BuildBakeNameMapIn -{ - RDI_NameMapKind k; - RDI_U64 *type_indices; - RDIM_BakeParams *params; -}; - -//- rjf: string map joining task types - -typedef struct RDIM_JoinBakeStringMapSlotsIn RDIM_JoinBakeStringMapSlotsIn; -struct RDIM_JoinBakeStringMapSlotsIn -{ - RDIM_BakeStringMapTopology *top; - RDIM_BakeStringMapLoose **src_maps; - U64 src_maps_count; - RDIM_BakeStringMapLoose *dst_map; - Rng1U64 slot_idx_range; -}; - -//- rjf: string map sorting task types - -typedef struct RDIM_SortBakeStringMapSlotsIn RDIM_SortBakeStringMapSlotsIn; -struct RDIM_SortBakeStringMapSlotsIn -{ - RDIM_BakeStringMapTopology *top; - RDIM_BakeStringMapLoose *src_map; - RDIM_BakeStringMapLoose *dst_map; - U64 slot_idx; - U64 slot_count; -}; - -//- rjf: debug info baking task types - -typedef struct RDIM_BakeUnitsIn RDIM_BakeUnitsIn; -struct RDIM_BakeUnitsIn -{ - RDIM_BakeStringMapTight *strings; - RDIM_BakePathTree *path_tree; - RDIM_UnitChunkList *units; -}; - -typedef struct RDIM_BakeUnitVMapIn RDIM_BakeUnitVMapIn; -struct RDIM_BakeUnitVMapIn -{ - RDIM_UnitChunkList *units; -}; - -typedef struct RDIM_BakeSrcFilesIn RDIM_BakeSrcFilesIn; -struct RDIM_BakeSrcFilesIn -{ - RDIM_BakeStringMapTight *strings; - RDIM_BakePathTree *path_tree; - RDIM_SrcFileChunkList *src_files; -}; - -typedef struct RDIM_BakeUDTsIn RDIM_BakeUDTsIn; -struct RDIM_BakeUDTsIn -{ - RDIM_BakeStringMapTight *strings; - RDIM_UDTChunkList *udts; - RDI_U64 *type_indices; -}; - -typedef struct RDIM_BakeGlobalVariablesIn RDIM_BakeGlobalVariablesIn; -struct RDIM_BakeGlobalVariablesIn -{ - RDIM_BakeStringMapTight *strings; - RDIM_SymbolChunkList *global_variables; - RDI_U64 *type_indices; -}; - -typedef struct RDIM_BakeGlobalVMapIn RDIM_BakeGlobalVMapIn; -struct RDIM_BakeGlobalVMapIn -{ - RDIM_SymbolChunkList *global_variables; -}; - -typedef struct RDIM_BakeThreadVariablesIn RDIM_BakeThreadVariablesIn; -struct RDIM_BakeThreadVariablesIn -{ - RDIM_BakeStringMapTight *strings; - RDIM_SymbolChunkList *thread_variables; - RDI_U64 *type_indices; -}; - -typedef struct RDIM_BakeProceduresIn RDIM_BakeProceduresIn; -struct RDIM_BakeProceduresIn -{ - RDIM_BakeStringMapTight *strings; - RDIM_SymbolChunkList *procedures; - RDI_U64 *type_indices; - RDIM_String8List *location_blocks; - RDIM_String8List *location_data_blobs; -}; - -typedef struct RDIM_BakeScopesIn RDIM_BakeScopesIn; -struct RDIM_BakeScopesIn -{ - RDIM_BakeStringMapTight *strings; - RDIM_ScopeChunkList *scopes; - RDI_U64 *type_indices; - RDIM_String8List *location_blocks; - RDIM_String8List *location_data_blobs; -}; - -typedef struct RDIM_BakeScopeVMapIn RDIM_BakeScopeVMapIn; -struct RDIM_BakeScopeVMapIn -{ - RDIM_ScopeChunkList *scopes; -}; - -typedef struct RDIM_BakeInlineSitesIn RDIM_BakeInlineSitesIn; -struct RDIM_BakeInlineSitesIn -{ - RDIM_BakeStringMapTight *strings; - RDIM_InlineSiteChunkList *inline_sites; - RDI_U64 *type_indices; -}; - -typedef struct RDIM_BakeFilePathsIn RDIM_BakeFilePathsIn; -struct RDIM_BakeFilePathsIn -{ - RDIM_BakeStringMapTight *strings; - RDIM_BakePathTree *path_tree; -}; - -typedef struct RDIM_BakeStringsIn RDIM_BakeStringsIn; -struct RDIM_BakeStringsIn -{ - RDIM_BakeStringMapTight *strings; -}; - -typedef struct RDIM_BakeTypeNodesIn RDIM_BakeTypeNodesIn; -struct RDIM_BakeTypeNodesIn -{ - RDIM_BakeStringMapTight *strings; - RDIM_BakeIdxRunMap *idx_runs; - RDIM_TypeChunkList *types; - RDI_U64 *type_indices; -}; - -typedef struct RDIM_BakeNameMapIn RDIM_BakeNameMapIn; -struct RDIM_BakeNameMapIn -{ - RDIM_BakeStringMapTight *strings; - RDIM_BakeIdxRunMap *idx_runs; - RDIM_BakeNameMap *map; - RDI_NameMapKind kind; -}; - -typedef struct RDIM_BakeIdxRunsIn RDIM_BakeIdxRunsIn; -struct RDIM_BakeIdxRunsIn -{ - RDIM_BakeIdxRunMap *idx_runs; -}; - -//////////////////////////////// -//~ rjf: Baking Stage Tasks - -//- rjf: unsorted bake string map building -ASYNC_WORK_DEF(p2r_bake_src_files_strings_work); -ASYNC_WORK_DEF(p2r_bake_units_strings_work); -ASYNC_WORK_DEF(p2r_bake_types_strings_work); -ASYNC_WORK_DEF(p2r_bake_udts_strings_work); -ASYNC_WORK_DEF(p2r_bake_symbols_strings_work); -ASYNC_WORK_DEF(p2r_bake_scopes_strings_work); -ASYNC_WORK_DEF(p2r_bake_line_tables_work); - -//- rjf: bake string map joining -ASYNC_WORK_DEF(p2r_bake_string_map_join_work); - -//- rjf: bake string map sorting -ASYNC_WORK_DEF(p2r_bake_string_map_sort_work); - -//- rjf: pass 1: interner/deduper map builds -ASYNC_WORK_DEF(p2r_build_bake_name_map_work); - -//- rjf: pass 2: string-map-dependent debug info stream builds -ASYNC_WORK_DEF(p2r_bake_units_work); -ASYNC_WORK_DEF(p2r_bake_unit_vmap_work); -ASYNC_WORK_DEF(p2r_bake_src_files_work); -ASYNC_WORK_DEF(p2r_bake_udts_work); -ASYNC_WORK_DEF(p2r_bake_global_variables_work); -ASYNC_WORK_DEF(p2r_bake_global_vmap_work); -ASYNC_WORK_DEF(p2r_bake_thread_variables_work); -ASYNC_WORK_DEF(p2r_bake_procedures_work); -ASYNC_WORK_DEF(p2r_bake_scopes_work); -ASYNC_WORK_DEF(p2r_bake_scope_vmap_work); -ASYNC_WORK_DEF(p2r_bake_file_paths_work); -ASYNC_WORK_DEF(p2r_bake_strings_work); - -//- rjf: pass 3: idx-run-map-dependent debug info stream builds -ASYNC_WORK_DEF(p2r_bake_type_nodes_work); -ASYNC_WORK_DEF(p2r_bake_name_map_work); -ASYNC_WORK_DEF(p2r_bake_idx_runs_work); - -typedef struct RDIM_HelpState RDIM_HelpState; -struct RDIM_HelpState -{ - Arena *arena; - U64 work_thread_arenas_count; - Arena **work_thread_arenas; -}; - -//////////////////////////////// - -global RDIM_HelpState *rdim_help_state = 0; - -//////////////////////////////// - -internal RDIM_HelpState * rdim_help_init(void); -internal RDIM_BakeResults rdim_bake(RDIM_HelpState *state, RDIM_BakeParams *in); -internal RDIM_SerializedSectionBundle rdim_compress(Arena *arena, RDIM_SerializedSectionBundle *in); - -#endif // RDIM_MAKE_HELP diff --git a/src/rdi_make/rdi_make_local.c b/src/rdi_make/rdi_make_local.c index 01fa4949..dd75baf1 100644 --- a/src/rdi_make/rdi_make_local.c +++ b/src/rdi_make/rdi_make_local.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "lib_rdi_make/rdi_make.c" @@ -62,7 +62,7 @@ rdim_make_top_level_info(String8 image_name, Arch arch, U64 exe_hash, RDIM_Binar ASYNC_WORK_DEF(rdim_bake_src_files_strings_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeSrcFilesStringsIn *in = (RDIM_BakeSrcFilesStringsIn *)input; rdim_make_string_map_if_needed(); ProfScope("bake src file strings") rdim_bake_string_map_loose_push_src_files(arena, in->top, in->maps[thread_idx], in->list); @@ -73,7 +73,7 @@ ASYNC_WORK_DEF(rdim_bake_src_files_strings_work) ASYNC_WORK_DEF(rdim_bake_units_strings_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeUnitsStringsIn *in = (RDIM_BakeUnitsStringsIn *)input; rdim_make_string_map_if_needed(); ProfScope("bake unit strings") rdim_bake_string_map_loose_push_units(arena, in->top, in->maps[thread_idx], in->list); @@ -84,7 +84,7 @@ ASYNC_WORK_DEF(rdim_bake_units_strings_work) ASYNC_WORK_DEF(rdim_bake_types_strings_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeTypesStringsIn *in = (RDIM_BakeTypesStringsIn *)input; rdim_make_string_map_if_needed(); ProfScope("bake type strings") @@ -101,7 +101,7 @@ ASYNC_WORK_DEF(rdim_bake_types_strings_work) ASYNC_WORK_DEF(rdim_bake_udts_strings_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeUDTsStringsIn *in = (RDIM_BakeUDTsStringsIn *)input; rdim_make_string_map_if_needed(); ProfScope("bake udt strings") @@ -118,7 +118,7 @@ ASYNC_WORK_DEF(rdim_bake_udts_strings_work) ASYNC_WORK_DEF(rdim_bake_symbols_strings_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeSymbolsStringsIn *in = (RDIM_BakeSymbolsStringsIn *)input; rdim_make_string_map_if_needed(); ProfScope("bake symbol strings") @@ -135,7 +135,7 @@ ASYNC_WORK_DEF(rdim_bake_symbols_strings_work) ASYNC_WORK_DEF(rdim_bake_inline_site_strings_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeInlineSiteStringsIn *in = input; rdim_make_string_map_if_needed(); ProfScope("bake inline site strings") @@ -152,7 +152,7 @@ ASYNC_WORK_DEF(rdim_bake_inline_site_strings_work) ASYNC_WORK_DEF(rdim_bake_scopes_strings_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeScopesStringsIn *in = (RDIM_BakeScopesStringsIn *)input; rdim_make_string_map_if_needed(); ProfScope("bake scope strings") @@ -169,7 +169,7 @@ ASYNC_WORK_DEF(rdim_bake_scopes_strings_work) ASYNC_WORK_DEF(rdim_bake_line_tables_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeLineTablesIn *in = (RDIM_BakeLineTablesIn *)input; RDIM_LineTableBakeResult *out = push_array(arena, RDIM_LineTableBakeResult, 1); ProfScope("bake line tables") *out = rdim_bake_line_tables(arena, in->line_tables); @@ -184,7 +184,7 @@ ASYNC_WORK_DEF(rdim_bake_line_tables_work) ASYNC_WORK_DEF(rdim_bake_string_map_join_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_JoinBakeStringMapSlotsIn *in = (RDIM_JoinBakeStringMapSlotsIn *)input; ProfScope("join bake string maps") { @@ -214,7 +214,7 @@ ASYNC_WORK_DEF(rdim_bake_string_map_join_work) ASYNC_WORK_DEF(rdim_bake_string_map_sort_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_SortBakeStringMapSlotsIn *in = (RDIM_SortBakeStringMapSlotsIn *)input; ProfScope("sort bake string chunk list map range") { @@ -245,7 +245,7 @@ ASYNC_WORK_DEF(rdim_bake_string_map_sort_work) ASYNC_WORK_DEF(rdim_build_bake_name_map_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BuildBakeNameMapIn *in = (RDIM_BuildBakeNameMapIn *)input; RDIM_BakeNameMap *name_map = 0; ProfScope("build name map %i", in->k) name_map = rdim_bake_name_map_from_kind_params(arena, in->k, in->params); @@ -258,7 +258,7 @@ ASYNC_WORK_DEF(rdim_build_bake_name_map_work) ASYNC_WORK_DEF(rdim_bake_units_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeUnitsIn *in = (RDIM_BakeUnitsIn *)input; RDIM_UnitBakeResult *out = push_array(arena, RDIM_UnitBakeResult, 1); ProfScope("bake units") *out = rdim_bake_units(arena, in->strings, in->path_tree, in->units); @@ -269,7 +269,7 @@ ASYNC_WORK_DEF(rdim_bake_units_work) ASYNC_WORK_DEF(rdim_bake_unit_vmap_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeUnitVMapIn *in = (RDIM_BakeUnitVMapIn *)input; RDIM_UnitVMapBakeResult *out = push_array(arena, RDIM_UnitVMapBakeResult, 1); ProfScope("bake unit vmap") *out = rdim_bake_unit_vmap(arena, in->units); @@ -280,7 +280,7 @@ ASYNC_WORK_DEF(rdim_bake_unit_vmap_work) ASYNC_WORK_DEF(rdim_bake_src_files_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeSrcFilesIn *in = (RDIM_BakeSrcFilesIn *)input; RDIM_SrcFileBakeResult *out = push_array(arena, RDIM_SrcFileBakeResult, 1); ProfScope("bake src files") *out = rdim_bake_src_files(arena, in->strings, in->path_tree, in->src_files); @@ -291,7 +291,7 @@ ASYNC_WORK_DEF(rdim_bake_src_files_work) ASYNC_WORK_DEF(rdim_bake_udts_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeUDTsIn *in = (RDIM_BakeUDTsIn *)input; RDIM_UDTBakeResult *out = push_array(arena, RDIM_UDTBakeResult, 1); ProfScope("bake udts") *out = rdim_bake_udts(arena, in->strings, in->udts); @@ -302,7 +302,7 @@ ASYNC_WORK_DEF(rdim_bake_udts_work) ASYNC_WORK_DEF(rdim_bake_global_variables_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeGlobalVariablesIn *in = (RDIM_BakeGlobalVariablesIn *)input; RDIM_GlobalVariableBakeResult *out = push_array(arena, RDIM_GlobalVariableBakeResult, 1); ProfScope("bake global variables") *out = rdim_bake_global_variables(arena, in->strings, in->global_variables); @@ -313,7 +313,7 @@ ASYNC_WORK_DEF(rdim_bake_global_variables_work) ASYNC_WORK_DEF(rdim_bake_global_vmap_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeGlobalVMapIn *in = (RDIM_BakeGlobalVMapIn *)input; RDIM_GlobalVMapBakeResult *out = push_array(arena, RDIM_GlobalVMapBakeResult, 1); ProfScope("bake global vmap") *out = rdim_bake_global_vmap(arena, in->global_variables); @@ -324,7 +324,7 @@ ASYNC_WORK_DEF(rdim_bake_global_vmap_work) ASYNC_WORK_DEF(rdim_bake_thread_variables_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeThreadVariablesIn *in = (RDIM_BakeThreadVariablesIn *)input; RDIM_ThreadVariableBakeResult *out = push_array(arena, RDIM_ThreadVariableBakeResult, 1); ProfScope("bake thread variables") *out = rdim_bake_thread_variables(arena, in->strings, in->thread_variables); @@ -332,10 +332,21 @@ ASYNC_WORK_DEF(rdim_bake_thread_variables_work) return out; } +ASYNC_WORK_DEF(rdim_bake_constants_work) +{ + ProfBeginFunction(); + Arena *arena = async_root_thread_arena(rdim_local_async_root); + RDIM_BakeConstantsIn *in = (RDIM_BakeConstantsIn *)input; + RDIM_ConstantsBakeResult *out = push_array(arena, RDIM_ConstantsBakeResult, 1); + ProfScope("bake constants") *out = rdim_bake_constants(arena, in->strings, in->constants); + ProfEnd(); + return out; +} + ASYNC_WORK_DEF(rdim_bake_procedures_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeProceduresIn *in = (RDIM_BakeProceduresIn *)input; RDIM_ProcedureBakeResult *out = push_array(arena, RDIM_ProcedureBakeResult, 1); ProfScope("bake procedures") *out = rdim_bake_procedures(arena, in->strings, in->location_blocks, in->location_data_blobs, in->procedures); @@ -346,7 +357,7 @@ ASYNC_WORK_DEF(rdim_bake_procedures_work) ASYNC_WORK_DEF(rdim_bake_scopes_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeScopesIn *in = (RDIM_BakeScopesIn *)input; RDIM_ScopeBakeResult *out = push_array(arena, RDIM_ScopeBakeResult, 1); ProfScope("bake scopes") *out = rdim_bake_scopes(arena, in->strings, in->location_blocks, in->location_data_blobs, in->scopes); @@ -357,7 +368,7 @@ ASYNC_WORK_DEF(rdim_bake_scopes_work) ASYNC_WORK_DEF(rdim_bake_scope_vmap_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeScopeVMapIn *in = (RDIM_BakeScopeVMapIn *)input; RDIM_ScopeVMapBakeResult *out = push_array(arena, RDIM_ScopeVMapBakeResult, 1); ProfScope("bake scope vmap") *out = rdim_bake_scope_vmap(arena, in->scopes); @@ -368,7 +379,7 @@ ASYNC_WORK_DEF(rdim_bake_scope_vmap_work) ASYNC_WORK_DEF(rdim_bake_inline_sites_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeInlineSitesIn *in = (RDIM_BakeInlineSitesIn *)input; RDIM_InlineSiteBakeResult *out = push_array(arena, RDIM_InlineSiteBakeResult, 1); ProfScope("bake inline sites") *out = rdim_bake_inline_sites(arena, in->strings, in->inline_sites); @@ -379,7 +390,7 @@ ASYNC_WORK_DEF(rdim_bake_inline_sites_work) ASYNC_WORK_DEF(rdim_bake_file_paths_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeFilePathsIn *in = (RDIM_BakeFilePathsIn *)input; RDIM_FilePathBakeResult *out = push_array(arena, RDIM_FilePathBakeResult, 1); ProfScope("bake file paths") *out = rdim_bake_file_paths(arena, in->strings, in->path_tree); @@ -390,7 +401,7 @@ ASYNC_WORK_DEF(rdim_bake_file_paths_work) ASYNC_WORK_DEF(rdim_bake_strings_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeStringsIn *in = (RDIM_BakeStringsIn *)input; RDIM_StringBakeResult *out = push_array(arena, RDIM_StringBakeResult, 1); ProfScope("bake strings") *out = rdim_bake_strings(arena, in->strings); @@ -403,7 +414,7 @@ ASYNC_WORK_DEF(rdim_bake_strings_work) ASYNC_WORK_DEF(rdim_bake_type_nodes_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeTypeNodesIn *in = (RDIM_BakeTypeNodesIn *)input; RDIM_TypeNodeBakeResult *out = push_array(arena, RDIM_TypeNodeBakeResult, 1); ProfScope("bake type nodes") *out = rdim_bake_types(arena, in->strings, in->idx_runs, in->types); @@ -414,7 +425,7 @@ ASYNC_WORK_DEF(rdim_bake_type_nodes_work) ASYNC_WORK_DEF(rdim_bake_name_map_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeNameMapIn *in = (RDIM_BakeNameMapIn *)input; RDIM_NameMapBakeResult *out = push_array(arena, RDIM_NameMapBakeResult, 1); ProfScope("bake name map %i", in->kind) *out = rdim_bake_name_map(arena, in->strings, in->idx_runs, in->map); @@ -425,7 +436,7 @@ ASYNC_WORK_DEF(rdim_bake_name_map_work) ASYNC_WORK_DEF(rdim_bake_idx_runs_work) { ProfBeginFunction(); - Arena *arena = rdim_local_state->work_thread_arenas[thread_idx]; + Arena *arena = async_root_thread_arena(rdim_local_async_root); RDIM_BakeIdxRunsIn *in = (RDIM_BakeIdxRunsIn *)input; RDIM_IndexRunBakeResult *out = push_array(arena, RDIM_IndexRunBakeResult, 1); ProfScope("bake idx runs") *out = rdim_bake_index_runs(arena, in->idx_runs); @@ -612,28 +623,12 @@ rdim_local_resolve_incomplete_types(RDIM_TypeChunkList *types, RDIM_UDTChunkList ProfEnd(); } -internal RDIM_LocalState * -rdim_local_init(void) -{ - Arena *arena = arena_alloc(); - RDIM_LocalState *state = push_array(arena, RDIM_LocalState, 1); - state->arena = arena; - state->work_thread_arenas_count = async_thread_count(); - state->work_thread_arenas = push_array(arena, Arena *, state->work_thread_arenas_count); - for EachIndex(idx, state->work_thread_arenas_count) - { - state->work_thread_arenas[idx] = arena_alloc(); - } - return state; -} - internal RDIM_BakeResults -rdim_bake(RDIM_LocalState *state, RDIM_BakeParams *in_params) +rdim_bake(Arena *arena, ASYNC_Root *async_root, RDIM_BakeParams *in_params) { Temp scratch = scratch_begin(0,0); RDIM_BakeResults out = {0}; - - rdim_local_state = state; + rdim_local_async_root = async_root; ////////////////////////////// //- rjf: kick off line tables baking @@ -651,7 +646,7 @@ rdim_bake(RDIM_LocalState *state, RDIM_BakeParams *in_params) RDIM_BakePathTree *path_tree = 0; ProfScope("build interned path tree") { - path_tree = rdim_bake_path_tree_from_params(state->arena, in_params); + path_tree = rdim_bake_path_tree_from_params(arena, in_params); } ////////////////////////////// @@ -757,6 +752,7 @@ rdim_bake(RDIM_LocalState *state, RDIM_BakeParams *in_params) &in_params->global_variables, &in_params->thread_variables, &in_params->procedures, + &in_params->constants, }; for(U64 list_idx = 0; list_idx < ArrayCount(symbol_lists); list_idx += 1) { @@ -790,6 +786,7 @@ rdim_bake(RDIM_LocalState *state, RDIM_BakeParams *in_params) } } + // rjf: inline sites ProfScope("kick off inline site string map build task") { U64 items_per_task = 4096; @@ -882,7 +879,7 @@ rdim_bake(RDIM_LocalState *state, RDIM_BakeParams *in_params) ////////////////////////////// //- rjf: produce joined string map // - RDIM_BakeStringMapLoose *unsorted_bake_string_map = rdim_bake_string_map_loose_make(state->arena, &bake_string_map_topology); + RDIM_BakeStringMapLoose *unsorted_bake_string_map = rdim_bake_string_map_loose_make(arena, &bake_string_map_topology); ProfScope("produce joined string map") { U64 slots_per_task = 16384; @@ -909,16 +906,16 @@ rdim_bake(RDIM_LocalState *state, RDIM_BakeParams *in_params) } // rjf: insert small top-level stuff - rdim_bake_string_map_loose_push_top_level_info(state->arena, &bake_string_map_topology, unsorted_bake_string_map, &in_params->top_level_info); - rdim_bake_string_map_loose_push_binary_sections(state->arena, &bake_string_map_topology, unsorted_bake_string_map, &in_params->binary_sections); - rdim_bake_string_map_loose_push_path_tree(state->arena, &bake_string_map_topology, unsorted_bake_string_map, path_tree); + rdim_bake_string_map_loose_push_top_level_info(arena, &bake_string_map_topology, unsorted_bake_string_map, &in_params->top_level_info); + rdim_bake_string_map_loose_push_binary_sections(arena, &bake_string_map_topology, unsorted_bake_string_map, &in_params->binary_sections); + rdim_bake_string_map_loose_push_path_tree(arena, &bake_string_map_topology, unsorted_bake_string_map, path_tree); } ////////////////////////////// //- rjf: kick off string map sorting tasks // ASYNC_TaskList sort_bake_string_map_tasks = {0}; - RDIM_BakeStringMapLoose *sorted_bake_string_map__in_progress = rdim_bake_string_map_loose_make(state->arena, &bake_string_map_topology); + RDIM_BakeStringMapLoose *sorted_bake_string_map__in_progress = rdim_bake_string_map_loose_make(arena, &bake_string_map_topology); { U64 slots_per_task = 4096; U64 num_tasks = (bake_string_map_topology.slots_count+slots_per_task-1)/slots_per_task; @@ -956,10 +953,10 @@ rdim_bake(RDIM_LocalState *state, RDIM_BakeParams *in_params) //- rjf: build finalized string map // ProfBegin("build finalized string map base indices"); - RDIM_BakeStringMapBaseIndices bake_string_map_base_idxes = rdim_bake_string_map_base_indices_from_map_loose(state->arena, &bake_string_map_topology, sorted_bake_string_map); + RDIM_BakeStringMapBaseIndices bake_string_map_base_idxes = rdim_bake_string_map_base_indices_from_map_loose(arena, &bake_string_map_topology, sorted_bake_string_map); ProfEnd(); ProfBegin("build finalized string map"); - RDIM_BakeStringMapTight bake_strings = rdim_bake_string_map_tight_from_loose(state->arena, &bake_string_map_topology, &bake_string_map_base_idxes, sorted_bake_string_map); + RDIM_BakeStringMapTight bake_strings = rdim_bake_string_map_tight_from_loose(arena, &bake_string_map_topology, &bake_string_map_base_idxes, sorted_bake_string_map); ProfEnd(); ////////////////////////////// @@ -983,30 +980,53 @@ rdim_bake(RDIM_LocalState *state, RDIM_BakeParams *in_params) ASYNC_Task *bake_file_paths_task = async_task_launch(scratch.arena, rdim_bake_file_paths_work, .input = &bake_file_paths_in); RDIM_BakeStringsIn bake_strings_in = {&bake_strings}; ASYNC_Task *bake_strings_task = async_task_launch(scratch.arena, rdim_bake_strings_work, .input = &bake_strings_in); + RDIM_BakeConstantsIn bake_constants_in = {&bake_strings, &in_params->constants}; + ASYNC_Task *bake_constants_task = async_task_launch(scratch.arena, rdim_bake_constants_work, .input = &bake_constants_in); + ////////////////////////////// + //- rjf: (GIANT SERIAL DEPENDENCY CHAIN HACK OF LOCATION BLOCK BUILDING) + // + // TODO(rjf): // TODO(rjf): // TODO(rjf): { + // + // This needs to be majorly cleaned up. We are doing this giant + // serial-dependency chain of async tasks (thus removing all async + // properties) because each async task here is secretly mutating + // the same input parameter (something which breaks the rules & + // style used everywhere else in the converter). + // + // Location blocks for each category of symbol should be built + // & arranged in parallel, then joined via a very thin operation + // after the fact. We should not ever be secretly mutating input + // parameters to async tasks, we need to be only returning new + // stuff. + // RDIM_String8List location_blocks = {0}; RDIM_String8List location_data_blobs = {0}; - - // reserve null location block for opl - rdim_location_block_chunk_list_push_array(state->arena, &location_blocks, 1); - - // TODO: export location instead of VOFF - RDIM_BakeThreadVariablesIn bake_thread_variables_in = {&bake_strings, &in_params->thread_variables}; - ASYNC_Task *bake_thread_variables_task = async_task_launch(scratch.arena, rdim_bake_thread_variables_work, .input = &bake_thread_variables_in); - ProfScope("thread variables") out.thread_variables = *async_task_join_struct(bake_thread_variables_task, RDIM_ThreadVariableBakeResult); - - // TODO: export location instead of VOFF - RDIM_BakeGlobalVariablesIn bake_global_variables_in = {&bake_strings, &in_params->global_variables}; - ASYNC_Task *bake_global_variables_task = async_task_launch(scratch.arena, rdim_bake_global_variables_work, .input = &bake_global_variables_in); - ProfScope("global variables") out.global_variables = *async_task_join_struct(bake_global_variables_task, RDIM_GlobalVariableBakeResult); - - RDIM_BakeScopesIn bake_scopes_in = {&bake_strings, &in_params->scopes, &location_blocks, &location_data_blobs}; - ASYNC_Task *bake_scopes_task = async_task_launch(scratch.arena, rdim_bake_scopes_work, .input = &bake_scopes_in); - ProfScope("scopes") out.scopes = *async_task_join_struct(bake_scopes_task, RDIM_ScopeBakeResult); - - RDIM_BakeProceduresIn bake_procedures_in = {&bake_strings, &in_params->procedures, &location_blocks, &location_data_blobs}; - ASYNC_Task *bake_procedures_task = async_task_launch(scratch.arena, rdim_bake_procedures_work, .input = &bake_procedures_in); - ProfScope("procedures") out.procedures = *async_task_join_struct(bake_procedures_task, RDIM_ProcedureBakeResult); + { + // reserve null location block for opl + rdim_location_block_chunk_list_push_array(arena, &location_blocks, 1); + + // TODO: export location instead of VOFF + RDIM_BakeGlobalVariablesIn bake_global_variables_in = {&bake_strings, &in_params->global_variables}; + ASYNC_Task *bake_global_variables_task = async_task_launch(scratch.arena, rdim_bake_global_variables_work, .input = &bake_global_variables_in); + ProfScope("global variables") out.global_variables = *async_task_join_struct(bake_global_variables_task, RDIM_GlobalVariableBakeResult); + + // TODO: export location instead of VOFF + RDIM_BakeThreadVariablesIn bake_thread_variables_in = {&bake_strings, &in_params->thread_variables}; + ASYNC_Task *bake_thread_variables_task = async_task_launch(scratch.arena, rdim_bake_thread_variables_work, .input = &bake_thread_variables_in); + ProfScope("thread variables") out.thread_variables = *async_task_join_struct(bake_thread_variables_task, RDIM_ThreadVariableBakeResult); + + RDIM_BakeScopesIn bake_scopes_in = {&bake_strings, &in_params->scopes, &location_blocks, &location_data_blobs}; + ASYNC_Task *bake_scopes_task = async_task_launch(scratch.arena, rdim_bake_scopes_work, .input = &bake_scopes_in); + ProfScope("scopes") out.scopes = *async_task_join_struct(bake_scopes_task, RDIM_ScopeBakeResult); + + RDIM_BakeProceduresIn bake_procedures_in = {&bake_strings, &in_params->procedures, &location_blocks, &location_data_blobs}; + ASYNC_Task *bake_procedures_task = async_task_launch(scratch.arena, rdim_bake_procedures_work, .input = &bake_procedures_in); + ProfScope("procedures") out.procedures = *async_task_join_struct(bake_procedures_task, RDIM_ProcedureBakeResult); + } + // + //- TODO(rjf): // TODO(rjf): // TODO(rjf): } + ////////////////////////////// ////////////////////////////// //- rjf: join name map building tasks @@ -1028,15 +1048,15 @@ rdim_bake(RDIM_LocalState *state, RDIM_BakeParams *in_params) RDIM_BakeIdxRunMap *idx_runs = 0; ProfScope("build interned idx run map") { - idx_runs = rdim_bake_idx_run_map_from_params(state->arena, name_maps, in_params); + idx_runs = rdim_bake_idx_run_map_from_params(arena, name_maps, in_params); } ////////////////////////////// //- rjf: do small top-level bakes // - ProfScope("top level info") out.top_level_info = rdim_bake_top_level_info(state->arena, &bake_strings, &in_params->top_level_info); - ProfScope("binary sections") out.binary_sections = rdim_bake_binary_sections(state->arena, &bake_strings, &in_params->binary_sections); - ProfScope("top level name maps section") out.top_level_name_maps = rdim_bake_name_maps_top_level(state->arena, &bake_strings, idx_runs, name_maps); + ProfScope("top level info") out.top_level_info = rdim_bake_top_level_info(arena, &bake_strings, &in_params->top_level_info); + ProfScope("binary sections") out.binary_sections = rdim_bake_binary_sections(arena, &bake_strings, &in_params->binary_sections); + ProfScope("top level name maps section") out.top_level_name_maps = rdim_bake_name_maps_top_level(arena, &bake_strings, idx_runs, name_maps); ////////////////////////////// //- rjf: kick off pass 3 tasks @@ -1074,6 +1094,7 @@ rdim_bake(RDIM_LocalState *state, RDIM_BakeParams *in_params) ProfScope("inline sites") out.inline_sites = *async_task_join_struct(bake_inline_sites_task, RDIM_InlineSiteBakeResult); ProfScope("file paths") out.file_paths = *async_task_join_struct(bake_file_paths_task, RDIM_FilePathBakeResult); ProfScope("strings") out.strings = *async_task_join_struct(bake_strings_task, RDIM_StringBakeResult); + ProfScope("constants") out.constants = *async_task_join_struct(bake_constants_task, RDIM_ConstantsBakeResult); ProfScope("type nodes") out.type_nodes = *async_task_join_struct(bake_type_nodes_task, RDIM_TypeNodeBakeResult); ProfScope("idx runs") out.idx_runs = *async_task_join_struct(bake_idx_runs_task, RDIM_IndexRunBakeResult); ProfScope("line tables") out.line_tables = *async_task_join_struct(bake_line_tables_task, RDIM_LineTableBakeResult); @@ -1099,17 +1120,15 @@ rdim_bake(RDIM_LocalState *state, RDIM_BakeParams *in_params) // ProfScope("join all name map bakes into final name map bake") { - out.name_maps = rdim_name_map_bake_results_combine(state->arena, name_map_bakes, ArrayCount(name_map_bakes)); + out.name_maps = rdim_name_map_bake_results_combine(arena, name_map_bakes, ArrayCount(name_map_bakes)); } - //////////////////////////////// - out.location_blocks = rdim_str8_list_join(state->arena, &location_blocks, rdim_str8(0,0)); - out.location_data = rdim_str8_list_join(state->arena, &location_data_blobs, rdim_str8(0,0)); - - rdim_local_state = 0; + out.location_blocks = rdim_str8_list_join(arena, &location_blocks, rdim_str8(0,0)); + out.location_data = rdim_str8_list_join(arena, &location_data_blobs, rdim_str8(0,0)); + rdim_local_async_root = 0; scratch_end(scratch); return out; } diff --git a/src/rdi_make/rdi_make_local.h b/src/rdi_make/rdi_make_local.h index 5dc7ec6b..0a920532 100644 --- a/src/rdi_make/rdi_make_local.h +++ b/src/rdi_make/rdi_make_local.h @@ -1,16 +1,16 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RDI_MAKE_LOCAL_H #define RDI_MAKE_LOCAL_H -// rjf: base layer memory ops +//- rjf: base layer memory ops #define RDIM_MEMSET_OVERRIDE #define RDIM_MEMCPY_OVERRIDE #define rdim_memset MemorySet #define rdim_memcpy MemoryCopy -// rjf: base layer string overrides +//- rjf: base layer string overrides #define RDI_STRING8_OVERRIDE #define RDIM_String8 String8 #define RDIM_String8_BaseMember str @@ -25,7 +25,7 @@ #define RDIM_String8List_NodeCountMember node_count #define RDIM_String8List_TotalSizeMember total_size -// rjf: base layer arena overrides +//- rjf: base layer arena overrides #define RDIM_ARENA_OVERRIDE #define RDIM_Arena Arena #define rdim_arena_alloc arena_alloc @@ -34,21 +34,20 @@ #define rdim_arena_push arena_push #define rdim_arena_pop_to arena_pop_to -// rjf: base layer scratch arena overrides +//- rjf: base layer scratch arena overrides #define RDIM_SCRATCH_OVERRIDE #define RDIM_Temp Temp #define rdim_temp_arena(t) ((t).arena) #define rdim_scratch_begin scratch_begin #define rdim_scratch_end scratch_end -// rjf: base layer profiling markup overrides +//- rjf: base layer profiling markup overrides #define RDIM_ProfBegin(...) ProfBeginDynamic(__VA_ARGS__) #define RDIM_ProfEnd(...) ProfEnd() +//- rjf: main library #include "lib_rdi_make/rdi_make.h" -//////////////////////////////// - //- rjf: line table baking task types typedef struct RDIM_BakeLineTablesIn RDIM_BakeLineTablesIn; @@ -238,6 +237,13 @@ struct RDIM_BakeGlobalVariablesIn RDIM_SymbolChunkList *global_variables; }; +typedef struct RDIM_BakeConstantsIn RDIM_BakeConstantsIn; +struct RDIM_BakeConstantsIn +{ + RDIM_BakeStringMapTight *strings; + RDIM_SymbolChunkList *constants; +}; + typedef struct RDIM_BakeGlobalVMapIn RDIM_BakeGlobalVMapIn; struct RDIM_BakeGlobalVMapIn { @@ -351,6 +357,7 @@ ASYNC_WORK_DEF(rdim_bake_udts_work); ASYNC_WORK_DEF(rdim_bake_global_variables_work); ASYNC_WORK_DEF(rdim_bake_global_vmap_work); ASYNC_WORK_DEF(rdim_bake_thread_variables_work); +ASYNC_WORK_DEF(rdim_bake_constants_work); ASYNC_WORK_DEF(rdim_bake_procedures_work); ASYNC_WORK_DEF(rdim_bake_scopes_work); ASYNC_WORK_DEF(rdim_bake_scope_vmap_work); @@ -362,17 +369,10 @@ ASYNC_WORK_DEF(rdim_bake_type_nodes_work); ASYNC_WORK_DEF(rdim_bake_name_map_work); ASYNC_WORK_DEF(rdim_bake_idx_runs_work); -typedef struct RDIM_LocalState RDIM_LocalState; -struct RDIM_LocalState -{ - Arena *arena; - U64 work_thread_arenas_count; - Arena **work_thread_arenas; -}; - //////////////////////////////// +//~ rjf: Globals -global RDIM_LocalState *rdim_local_state = 0; +global ASYNC_Root *rdim_local_async_root = 0; //////////////////////////////// @@ -381,8 +381,7 @@ internal RDIM_TopLevelInfo rdim_make_top_level_info(String8 image_name, Arch arc //////////////////////////////// -internal RDIM_LocalState * rdim_local_init(void); -internal RDIM_BakeResults rdim_bake(RDIM_LocalState *state, RDIM_BakeParams *in); +internal RDIM_BakeResults rdim_bake(Arena *arena, ASYNC_Root *async_root, RDIM_BakeParams *in); internal RDIM_SerializedSectionBundle rdim_compress(Arena *arena, RDIM_SerializedSectionBundle *in); #endif // RDI_MAKE_LOCAL_H diff --git a/src/regs/generated/regs.meta.c b/src/regs/generated/regs.meta.c index 1f9f4b10..0805b542 100644 --- a/src/regs/generated/regs.meta.c +++ b/src/regs/generated/regs.meta.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/regs/generated/regs.meta.h b/src/regs/generated/regs.meta.h index f3cdf807..0f6f75a3 100644 --- a/src/regs/generated/regs.meta.h +++ b/src/regs/generated/regs.meta.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/regs/rdi/generated/regs_rdi.meta.c b/src/regs/rdi/generated/regs_rdi.meta.c index 9b0cdf65..de284856 100644 --- a/src/regs/rdi/generated/regs_rdi.meta.c +++ b/src/regs/rdi/generated/regs_rdi.meta.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/regs/rdi/generated/regs_rdi.meta.h b/src/regs/rdi/generated/regs_rdi.meta.h index 6922e280..b5d77852 100644 --- a/src/regs/rdi/generated/regs_rdi.meta.h +++ b/src/regs/rdi/generated/regs_rdi.meta.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/regs/rdi/regs_rdi.c b/src/regs/rdi/regs_rdi.c index b191f5f8..911725c1 100644 --- a/src/regs/rdi/regs_rdi.c +++ b/src/regs/rdi/regs_rdi.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #include "regs/rdi/generated/regs_rdi.meta.c" diff --git a/src/regs/rdi/regs_rdi.h b/src/regs/rdi/regs_rdi.h index 65e210f0..a7fadd80 100644 --- a/src/regs/rdi/regs_rdi.h +++ b/src/regs/rdi/regs_rdi.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef REGS_RDI_H diff --git a/src/regs/rdi/regs_rdi.mdesk b/src/regs/rdi/regs_rdi.mdesk index e3961b84..1ef1197c 100644 --- a/src/regs/rdi/regs_rdi.mdesk +++ b/src/regs/rdi/regs_rdi.mdesk @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/regs/regs.c b/src/regs/regs.c index 1cd17c35..f55d133a 100644 --- a/src/regs/regs.c +++ b/src/regs/regs.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/regs/regs.h b/src/regs/regs.h index 3e6fcbf9..4d781fc9 100644 --- a/src/regs/regs.h +++ b/src/regs/regs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef REGS_H diff --git a/src/regs/regs.mdesk b/src/regs/regs.mdesk index 5e4ae872..2d7bc1ba 100644 --- a/src/regs/regs.mdesk +++ b/src/regs/regs.mdesk @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/render/d3d11/generated/render_d3d11.meta.c b/src/render/d3d11/generated/render_d3d11.meta.c index 1431e68e..e6393a68 100644 --- a/src/render/d3d11/generated/render_d3d11.meta.c +++ b/src/render/d3d11/generated/render_d3d11.meta.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/render/d3d11/generated/render_d3d11.meta.h b/src/render/d3d11/generated/render_d3d11.meta.h index 6fd7f833..cc1949a7 100644 --- a/src/render/d3d11/generated/render_d3d11.meta.h +++ b/src/render/d3d11/generated/render_d3d11.meta.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/render/d3d11/render_d3d11.c b/src/render/d3d11/render_d3d11.c index dca4586c..c53dac66 100644 --- a/src/render/d3d11/render_d3d11.c +++ b/src/render/d3d11/render_d3d11.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/render/d3d11/render_d3d11.h b/src/render/d3d11/render_d3d11.h index b1b0d5fd..0344ff74 100644 --- a/src/render/d3d11/render_d3d11.h +++ b/src/render/d3d11/render_d3d11.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_D3D11_H diff --git a/src/render/d3d11/render_d3d11.mdesk b/src/render/d3d11/render_d3d11.mdesk index 81e2084d..0e001db1 100644 --- a/src/render/d3d11/render_d3d11.mdesk +++ b/src/render/d3d11/render_d3d11.mdesk @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/render/generated/render.meta.c b/src/render/generated/render.meta.c index 242d8de6..c1897062 100644 --- a/src/render/generated/render.meta.c +++ b/src/render/generated/render.meta.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/render/generated/render.meta.h b/src/render/generated/render.meta.h index 5fad100c..e7b65c2b 100644 --- a/src/render/generated/render.meta.h +++ b/src/render/generated/render.meta.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/render/opengl/generated/render_opengl.meta.c b/src/render/opengl/generated/render_opengl.meta.c index 7084ac1b..228b658d 100644 --- a/src/render/opengl/generated/render_opengl.meta.c +++ b/src/render/opengl/generated/render_opengl.meta.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/render/opengl/generated/render_opengl.meta.h b/src/render/opengl/generated/render_opengl.meta.h index 9f33f24d..dc8709d1 100644 --- a/src/render/opengl/generated/render_opengl.meta.h +++ b/src/render/opengl/generated/render_opengl.meta.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE diff --git a/src/render/opengl/linux/egl/render_opengl_linux_egl.c b/src/render/opengl/linux/egl/render_opengl_linux_egl.c index 3d3370c6..28505f19 100644 --- a/src/render/opengl/linux/egl/render_opengl_linux_egl.c +++ b/src/render/opengl/linux/egl/render_opengl_linux_egl.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal VoidProc * diff --git a/src/render/opengl/linux/egl/render_opengl_linux_egl.h b/src/render/opengl/linux/egl/render_opengl_linux_egl.h index 54a419d1..77d687d7 100644 --- a/src/render/opengl/linux/egl/render_opengl_linux_egl.h +++ b/src/render/opengl/linux/egl/render_opengl_linux_egl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_OPENGL_LINUX_EGL_H diff --git a/src/render/opengl/linux/glx/render_opengl_linux_glx.c b/src/render/opengl/linux/glx/render_opengl_linux_glx.c index f8ca0af0..fa7217da 100644 --- a/src/render/opengl/linux/glx/render_opengl_linux_glx.c +++ b/src/render/opengl/linux/glx/render_opengl_linux_glx.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal VoidProc * diff --git a/src/render/opengl/linux/glx/render_opengl_linux_glx.h b/src/render/opengl/linux/glx/render_opengl_linux_glx.h index 995172b0..8b312233 100644 --- a/src/render/opengl/linux/glx/render_opengl_linux_glx.h +++ b/src/render/opengl/linux/glx/render_opengl_linux_glx.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_OPENGL_LINUX_GLX_H diff --git a/src/render/opengl/linux/render_opengl_linux.c b/src/render/opengl/linux/render_opengl_linux.c index 4e0e2964..47a7f0ce 100644 --- a/src/render/opengl/linux/render_opengl_linux.c +++ b/src/render/opengl/linux/render_opengl_linux.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/render/opengl/linux/render_opengl_linux.h b/src/render/opengl/linux/render_opengl_linux.h index 21069e8d..823e104e 100644 --- a/src/render/opengl/linux/render_opengl_linux.h +++ b/src/render/opengl/linux/render_opengl_linux.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_OPENGL_LINUX_H diff --git a/src/render/opengl/render_opengl.c b/src/render/opengl/render_opengl.c index 0661e8dc..7f646b36 100644 --- a/src/render/opengl/render_opengl.c +++ b/src/render/opengl/render_opengl.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/render/opengl/render_opengl.h b/src/render/opengl/render_opengl.h index 618298e1..bdbdf051 100644 --- a/src/render/opengl/render_opengl.h +++ b/src/render/opengl/render_opengl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_OPENGL_H diff --git a/src/render/opengl/render_opengl.mdesk b/src/render/opengl/render_opengl.mdesk index d96874cd..9bfd735c 100644 --- a/src/render/opengl/render_opengl.mdesk +++ b/src/render/opengl/render_opengl.mdesk @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/render/opengl/win32/render_opengl_win32.c b/src/render/opengl/win32/render_opengl_win32.c index f031758f..e0951e4c 100644 --- a/src/render/opengl/win32/render_opengl_win32.c +++ b/src/render/opengl/win32/render_opengl_win32.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) internal VoidProc * diff --git a/src/render/opengl/win32/render_opengl_win32.h b/src/render/opengl/win32/render_opengl_win32.h index 24e53c14..5cbc0c16 100644 --- a/src/render/opengl/win32/render_opengl_win32.h +++ b/src/render/opengl/win32/render_opengl_win32.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_OPENGL_WIN32_H diff --git a/src/render/render_core.c b/src/render/render_core.c index 80ca84bf..3e5723c4 100644 --- a/src/render/render_core.c +++ b/src/render/render_core.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/render/render_core.h b/src/render/render_core.h index 7725c5a3..c23c0503 100644 --- a/src/render/render_core.h +++ b/src/render/render_core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_CORE_H diff --git a/src/render/render_core.mdesk b/src/render/render_core.mdesk index c892a9b0..2be8f472 100644 --- a/src/render/render_core.mdesk +++ b/src/render/render_core.mdesk @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/render/render_inc.c b/src/render/render_inc.c index bb15be84..ba26df73 100644 --- a/src/render/render_inc.c +++ b/src/render/render_inc.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR diff --git a/src/render/render_inc.h b/src/render/render_inc.h index d0e87c3c..efe126ef 100644 --- a/src/render/render_inc.h +++ b/src/render/render_inc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_INC_H diff --git a/src/render/stub/render_stub.c b/src/render/stub/render_stub.c index 1c8ffbca..702327f3 100644 --- a/src/render/stub/render_stub.c +++ b/src/render/stub/render_stub.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- rjf: top-level layer initialization diff --git a/src/render/stub/render_stub.h b/src/render/stub/render_stub.h index 9142c4f2..51b67de6 100644 --- a/src/render/stub/render_stub.h +++ b/src/render/stub/render_stub.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef RENDER_STUB_H diff --git a/src/scratch/convertperf.c b/src/scratch/convertperf.c index 423f5b79..717db40d 100644 --- a/src/scratch/convertperf.c +++ b/src/scratch/convertperf.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -53,7 +53,7 @@ entry_point(CmdLine *cmdline) String8 dll_name = str8_skip_last_slash(dll_path_no_ext); String8 pdb_path = push_str8f(arena, "%S.pdb", dll_path_no_ext); String8 rdi_path = push_str8f(arena, "dump/%S.rdi", dll_name); - OS_Handle handle = os_cmd_line_launchf("raddbg --convert --pdb:%S --out:%S", pdb_path, rdi_path); + OS_Handle handle = os_cmd_line_launchf("raddbg --bin %S --out:%S", pdb_path, rdi_path); os_handle_list_push(arena, &processes, handle); if(processes_first_path_n == 0) { diff --git a/src/scratch/eval_scratch.c b/src/scratch/eval_scratch.c index 233a773b..a9cb9a32 100644 --- a/src/scratch/eval_scratch.c +++ b/src/scratch/eval_scratch.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/scratch/ryan_scratch.c b/src/scratch/ryan_scratch.c index 48b3a3fc..219a644e 100644 --- a/src/scratch/ryan_scratch.c +++ b/src/scratch/ryan_scratch.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/scratch/textperf.c b/src/scratch/textperf.c index b252b9e1..3c6c963c 100644 --- a/src/scratch/textperf.c +++ b/src/scratch/textperf.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/tester/tester_main.c b/src/tester/tester_main.c index 45b3e61f..ae080379 100644 --- a/src/tester/tester_main.c +++ b/src/tester/tester_main.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -40,10 +40,10 @@ internal void entry_point(CmdLine *cmdline) { Arena *arena = arena_alloc(); - E_TypeCtx *type_ctx = push_array(arena, E_TypeCtx, 1); - e_select_type_ctx(type_ctx); - E_ParseCtx *parse_ctx = push_array(arena, E_ParseCtx, 1); - e_select_parse_ctx(parse_ctx); + E_Cache *eval_cache = e_cache_alloc(); + e_select_cache(eval_cache); + E_BaseCtx *base_ctx = push_array(arena, E_BaseCtx, 1); + e_select_base_ctx(base_ctx); E_IRCtx *ir_ctx = push_array(arena, E_IRCtx, 1); e_select_ir_ctx(ir_ctx); E_InterpretCtx *interpret_ctx = push_array(arena, E_InterpretCtx, 1); diff --git a/src/text_cache/text_cache.c b/src/text_cache/text_cache.c index 29200950..920ab6c0 100644 --- a/src/text_cache/text_cache.c +++ b/src/text_cache/text_cache.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR diff --git a/src/text_cache/text_cache.h b/src/text_cache/text_cache.h index 143a7b75..4a2595a2 100644 --- a/src/text_cache/text_cache.h +++ b/src/text_cache/text_cache.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef TEXT_CACHE_H diff --git a/src/texture_cache/texture_cache.c b/src/texture_cache/texture_cache.c index 8bc7e657..245b69f6 100644 --- a/src/texture_cache/texture_cache.c +++ b/src/texture_cache/texture_cache.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR diff --git a/src/texture_cache/texture_cache.h b/src/texture_cache/texture_cache.h index 25a00be1..70b53a85 100644 --- a/src/texture_cache/texture_cache.h +++ b/src/texture_cache/texture_cache.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef TEXTURE_CACHE_H diff --git a/src/third_party/radsort/radsort.h b/src/third_party/radsort/radsort.h index eb77580c..9b735a41 100644 --- a/src/third_party/radsort/radsort.h +++ b/src/third_party/radsort/radsort.h @@ -1,5 +1,8 @@ // New radsort. +#if !defined(RADSORT_H) +#define RADSORT_H + // To Use: // Create a less_than function and then call radsort. // @@ -49,7 +52,7 @@ typedef struct bytes8 { char b[8]; } bytes8; static RSFORCEINLINE void radsortswapper( void * a, void * b, size_t size ) { - #define RSSWAPMEM(type) ( size >= sizeof(type) ) { type v = *(type const*)a; *(type*)a = *(type const*)b; *(type*)b = v; a=rsadd_ptr(a,sizeof(type)); b=rsadd_ptr(b,sizeof(type)); size -= sizeof(type); } +#define RSSWAPMEM(type) ( size >= sizeof(type) ) { type v = *(type const*)a; *(type*)a = *(type const*)b; *(type*)b = v; a=rsadd_ptr(a,sizeof(type)); b=rsadd_ptr(b,sizeof(type)); size -= sizeof(type); } while RSSWAPMEM(bytes64); if RSSWAPMEM(bytes32); @@ -59,13 +62,13 @@ static RSFORCEINLINE void radsortswapper( void * a, void * b, size_t size ) if RSSWAPMEM(short); if RSSWAPMEM(char); - #undef RSSWAPMEM +#undef RSSWAPMEM } // since size is always constant, this big function compiles down to 4 to 12 instructions (for normal structs 4-6) static RSFORCEINLINE void radsortmover( void * a, void * b, size_t size ) { - #define RSMOVEMEM(type) ( size >= sizeof(type) ) { *(type*)a = *(type const*)b; a=rsadd_ptr(a,sizeof(type)); b=rsadd_ptr(b,sizeof(type)); size -= sizeof(type); } +#define RSMOVEMEM(type) ( size >= sizeof(type) ) { *(type*)a = *(type const*)b; a=rsadd_ptr(a,sizeof(type)); b=rsadd_ptr(b,sizeof(type)); size -= sizeof(type); } while RSMOVEMEM(bytes64); if RSMOVEMEM(bytes32); @@ -75,7 +78,7 @@ static RSFORCEINLINE void radsortmover( void * a, void * b, size_t size ) if RSMOVEMEM(short); if RSMOVEMEM(char); - #undef RSMOVEMEM +#undef RSMOVEMEM } // these macros generate tiny move/swap routines that don't go through the generic function above (mostly for debug build performance) @@ -110,17 +113,17 @@ typedef void rs_small_sort_func( void * left, size_t n, size_t element_size, is_ typedef struct RS_MAX_BUBBLE_BUF { char b[RS_SMALL_FLIP_TO_INSERTION_GT_SIZE]; } RS_MAX_BUBBLE_BUF; #define radsort( start, len, is_before_func ) \ - do { \ - char __rs_tmp[ sizeof( (start)[0] ) ]; \ - radsortinternal( start, len, sizeof( (start)[0] ), \ - is_before_func, \ - radsortswapsize( sizeof( (start)[0] ) ), \ - radsortmovesize( sizeof( (start)[0] ) ), \ - ( sizeof( (start)[0] ) > RS_SMALL_FLIP_TO_INSERTION_GT_SIZE ) ? radinsertionsort : radbubble2sort, \ - ( sizeof( (start)[0] ) > RS_SMALL_FLIP_TO_INSERTION_GT_SIZE ) ? RSS_FLIP_TO_SMALL_SORT_INSERTION : RSS_FLIP_TO_SMALL_SORT_BUBBLE2, \ - &__rs_tmp \ - ); \ - } while (0) +do { \ +char __rs_tmp[ sizeof( (start)[0] ) ]; \ +radsortinternal( start, len, sizeof( (start)[0] ), \ +is_before_func, \ +radsortswapsize( sizeof( (start)[0] ) ), \ +radsortmovesize( sizeof( (start)[0] ) ), \ +( sizeof( (start)[0] ) > RS_SMALL_FLIP_TO_INSERTION_GT_SIZE ) ? radinsertionsort : radbubble2sort, \ +( sizeof( (start)[0] ) > RS_SMALL_FLIP_TO_INSERTION_GT_SIZE ) ? RSS_FLIP_TO_SMALL_SORT_INSERTION : RSS_FLIP_TO_SMALL_SORT_BUBBLE2, \ +&__rs_tmp \ +); \ +} while (0) #define radheapsort( start, len, is_before_func ) do { radheapsortinteral( start, len, sizeof( ((start)[0]) ), is_before_func, radsortswapsize( sizeof( ((start)[0]) ) ) ); } while (0) @@ -132,27 +135,27 @@ RSFORCEINLINE void radheapsortinteral( void * start, size_t len, size_t element_ void * left; void * right; size_t length; - + left = start; right = rsadd_ptr_elements( start, len - 1 ); length = len; - + if ( length > 1 ) { // unusual small in-place heap sort void * i; void * ind; void * v; void * n; size_t s, k; - + s = length >> 1; i = rsadd_ptr_elements( left, s ); - + for(;;) { --s; i = rsadd_ptr_elements( i, -1 ); ind = i; k = ( s << 1 ) + 1; - + for(;;) { v = rsadd_ptr_elements( left, k ); @@ -163,21 +166,21 @@ RSFORCEINLINE void radheapsortinteral( void * start, size_t len, size_t element_ ++k; v = n; } - + if ( is_before( ind, v ) ) { swapper( ind, v, element_size ); ind = v; k = ( k << 1 ) + 1; - + if ( k < length ) continue; } - + // if s is non-zero, we are still building the heap! if ( s ) break; - + swapper( left, right, element_size ); right = rsadd_ptr_elements( right, -1 ); ind = left; @@ -199,18 +202,18 @@ RSFORCEINLINE void radheapsortinteral( void * start, size_t len, size_t element_ static RSFORCEINLINE void radsortgetmedian5( void * output, void * left, void * right, size_t length, size_t element_size, is_before_func * is_before, swap_func * swapper, move_func * mover ) { RS_MAX_SIMPLE_BUF mb0,mb1,mb2,mb3,mb4; - + mover( &mb0, left, element_size ); mover( &mb1, rsadd_ptr_elements( left, length >> 2 ), element_size ); mover( &mb2, rsadd_ptr_elements( left, length >> 1 ), element_size ); mover( &mb3, rsadd_ptr_elements( left, length - (length >> 2) ), element_size ); mover( &mb4, right, element_size ); - + // Basically, for simple compares, and for simple in-register types, this funcion // must turn info 7 compares and then 5-7 movs, and 12 cmovs. Any // compiler *should* do this - if this doesn't happen, then the compiler is // hosing you. You can put int 3s at the start and end of this function to check. - + rsswapsmaller( mb0, mb1 ); rsswapsmaller( mb2, mb3 ); rsswapsmaller( mb0, mb2 ); @@ -226,8 +229,8 @@ static RSFORCEINLINE void radsortgetmedian5( void * output, void * left, void * static RSFORCEINLINE void radsortgetmedian9( void * output, void * left, void * right, size_t length, size_t element_size, is_before_func * is_before, swap_func * swapper, move_func * mover ) { RS_MAX_SIMPLE_BUF mb0,mb1,mb2,mb3,mb4,mb5,mb6,mb7,mb8; // todo, temp mem! - - #ifdef RS_PREFETCH + +#ifdef RS_PREFETCH RS_PREFETCH( left ); RS_PREFETCH( right ); RS_PREFETCH( rsadd_ptr_elements( left, length >> 3 ) ); @@ -237,8 +240,8 @@ static RSFORCEINLINE void radsortgetmedian9( void * output, void * left, void * RS_PREFETCH( rsadd_ptr_elements( left, (length >> 1) + (0 >> 3) ) ); RS_PREFETCH( rsadd_ptr_elements( left, length - (length >> 2) ) ); RS_PREFETCH( rsadd_ptr_elements( left, length - (length >> 3) ) ); - #endif - +#endif + mover( &mb0, left, element_size ); mover( &mb1, rsadd_ptr_elements( left, length >> 3 ), element_size ); mover( &mb2, rsadd_ptr_elements( left, length >> 2 ), element_size ); @@ -248,7 +251,7 @@ static RSFORCEINLINE void radsortgetmedian9( void * output, void * left, void * mover( &mb6, rsadd_ptr_elements( left, length - (length >> 2) ), element_size ); mover( &mb7, rsadd_ptr_elements( left, length - (length >> 3) ), element_size ); mover( &mb8, right, element_size ); - + // Basically, for simple compares, and for simple in-register types, this funcion // should turn info 19 compares and then 15-19 movs, and 36 cmovs. However, // most compilers can only so-so job at this, and you'll end up with 3-4 jumps. @@ -272,7 +275,7 @@ static RSFORCEINLINE void radsortgetmedian9( void * output, void * left, void * rsswapsmaller( mb4, mb6 ); rsswapsmaller( mb2, mb3 ); rsswapsmaller( mb4, mb5 ); - + mover( output, &mb3, element_size ); if ( is_before( &mb4, &mb3 ) ) mover( output, &mb4, element_size ); } @@ -301,13 +304,13 @@ static RSFORCEINLINE void radbubble2sort( void * left, size_t n, size_t element_ void * i; // todo - test with bigger blocks void * s = rsadd_ptr_elements( left, 2 ); RS_MAX_BUBBLE_BUF x, y, z; - - #define rsbubbleswap( X, Y ) { int cond; cond = is_before( &Y, &X); mover( tmp, &X, element_size ); if ( cond ) mover( &X, &Y, element_size ); if ( cond ) mover( &Y, tmp, element_size ); } - + +#define rsbubbleswap( X, Y ) { int cond; cond = is_before( &Y, &X); mover( tmp, &X, element_size ); if ( cond ) mover( &X, &Y, element_size ); if ( cond ) mover( &Y, tmp, element_size ); } + for ( i = rsadd_ptr_elements( left, (int)n - 1 ) ; i > left ; i = rsadd_ptr_elements( i, -2 ) ) { void * j, * jm2; - + // load x & y mover( &x, left, element_size ); mover( &y, rsadd_ptr_elements( left, 1 ), element_size ); @@ -317,7 +320,7 @@ static RSFORCEINLINE void radbubble2sort( void * left, size_t n, size_t element_ // for ints, this loop needs to be 4 cmps, 6 cmovs, and 5 movs // anything else will kill performance - + jm2 = left; for ( j = s ; j <= i ; j = rsadd_ptr_elements( j, 1 ) ) { @@ -329,7 +332,7 @@ static RSFORCEINLINE void radbubble2sort( void * left, size_t n, size_t element_ mover( jm2, &z, element_size ); jm2 = rsadd_ptr_elements( jm2, 1 ); } - + mover( rsadd_ptr_elements( i, -1 ), &x, element_size ); mover( i, &y, element_size ); } @@ -340,7 +343,7 @@ static RSFORCEINLINE void radinsertionsort(void * start, size_t len, size_t elem { void * cur; void * prev; - + cur = rsadd_ptr_elements( start, 1 ); --len; prev = start; @@ -424,25 +427,25 @@ RSFORCEINLINE void radsortinternal( void * start, size_t len, size_t element_siz { void * left; size_t length; - + if ( len <= 1 ) return; - - #if _DEBUG - if ( element_size > sizeof( RS_MAX_SIMPLE_BUF ) ) - __debugbreak(); - #endif - + +#if _DEBUG + if ( element_size > sizeof( RS_MAX_SIMPLE_BUF ) ) + __debugbreak(); +#endif + // stack for no recursion typedef struct stks { void * left; size_t len; } stks; - + stks stk[ RSS_MAX_RECURSE ]; stks * stk_ptr = stk + RSS_MAX_RECURSE; - + // we use the stk_ptr to tell when to flip to heap. // when we hit the end of the stack, we heap it, so // back the start of the stack to log1.5 of len @@ -453,10 +456,10 @@ RSFORCEINLINE void radsortinternal( void * start, size_t len, size_t element_siz length = ( length >> 1 ) + ( length >> 2 ); } while ( length ); stk_ptr[ -1 ].len = 0; - + left = start; length = len; - + do { for(;;) @@ -484,11 +487,11 @@ RSFORCEINLINE void radsortinternal( void * start, size_t len, size_t element_siz void * rightequalpiv; size_t leftlen; void * scan, * piv, * rend, * right; - + CompilerReset(left); // we reset the compiler before each major sort - + right = rsadd_ptr_elements( left, length - 1 ); - + // check for and correct inverted blocks scan = left; rend = right; @@ -499,7 +502,7 @@ RSFORCEINLINE void radsortinternal( void * start, size_t len, size_t element_siz rend = rsadd_ptr_elements( rend, -1 ); if ( scan >= rend ) break; } - + // scan to see if the block is in order (or all the same) scan = left; do @@ -511,12 +514,12 @@ RSFORCEINLINE void radsortinternal( void * start, size_t len, size_t element_siz } while ( scan < right ); // if we get out of the loop cleanly, this block is already sorted, so just fall out and do next block break; - - doqsort: - + + doqsort: + // get the median into copy radsortgetmedian( tmp, left, right, length, element_size, is_before, swapper, mover ); - + // if scan != left, then we have a few in order, so we can skip them all if the final is under the copy if ( !is_before( scan, tmp ) ) scan = left; @@ -524,7 +527,7 @@ RSFORCEINLINE void radsortinternal( void * start, size_t len, size_t element_siz // skip values below the pivot at the start of the segment while( is_before( scan, tmp ) ) // the pivot will stop this loop scan = rsadd_ptr( scan, element_size ); - + // skip values above and equal to the pivot at the end of the segment rend = right; if ( left == start ) @@ -545,7 +548,7 @@ RSFORCEINLINE void radsortinternal( void * start, size_t len, size_t element_siz while( is_before( tmp, rend ) ) // the pivot will stop this loop rend = rsadd_ptr_elements( rend, -1 ); } - + // finally, do actual partitioning nanosort style - 65-70% of the // total time will be in this loop, for ints, this should be // 4 movs, 2 cmps, 1 cmov, 2 add, 1 jmp - 10 instructions @@ -560,7 +563,7 @@ RSFORCEINLINE void radsortinternal( void * start, size_t len, size_t element_siz if ( adv ) piv = rsadd_ptr( piv, element_size ); // needs to be a cmov scan = rsadd_ptr( scan, element_size ); } - + // now move the right side to skip over all of the equal values... // this loop should be 5 instructions rightequalpiv = piv; @@ -570,11 +573,11 @@ RSFORCEINLINE void radsortinternal( void * start, size_t len, size_t element_siz break; rightequalpiv = rsadd_ptr_elements( rightequalpiv, 1 ); } - + // ok, now get the size of each half and prepare to descend leftlen = rsdiff_ptr_elements( piv, left ); length -= rsdiff_ptr_elements( rightequalpiv, left ); - + // put the smaller segment on the stack if ( length < leftlen ) { @@ -605,3 +608,5 @@ RSFORCEINLINE void radsortinternal( void * start, size_t len, size_t element_siz #undef rsadd_ptr #undef rsadd_ptr_elements #undef rsdiff_ptr_elements + +#endif // RADSORT_H diff --git a/src/ui/generated/ui.meta.c b/src/ui/generated/ui.meta.c index f66c6b76..9bc7c017 100644 --- a/src/ui/generated/ui.meta.c +++ b/src/ui/generated/ui.meta.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE @@ -25,6 +25,7 @@ #define UI_Tag(v) DeferLoop(ui_push_tag(v), ui_pop_tag()) #define UI_BackgroundColor(v) DeferLoop(ui_push_background_color(v), ui_pop_background_color()) #define UI_TextColor(v) DeferLoop(ui_push_text_color(v), ui_pop_text_color()) +#define UI_BorderColor(v) DeferLoop(ui_push_border_color(v), ui_pop_border_color()) #define UI_Squish(v) DeferLoop(ui_push_squish(v), ui_pop_squish()) #define UI_HoverCursor(v) DeferLoop(ui_push_hover_cursor(v), ui_pop_hover_cursor()) #define UI_Font(v) DeferLoop(ui_push_font(v), ui_pop_font()) @@ -59,6 +60,7 @@ internal UI_Key ui_top_group_key(void) { UI_StackTopImpl(ui_state, GroupKey, gro internal F32 ui_top_transparency(void) { UI_StackTopImpl(ui_state, Transparency, transparency) } internal Vec4F32 ui_top_background_color(void) { UI_StackTopImpl(ui_state, BackgroundColor, background_color) } internal Vec4F32 ui_top_text_color(void) { UI_StackTopImpl(ui_state, TextColor, text_color) } +internal Vec4F32 ui_top_border_color(void) { UI_StackTopImpl(ui_state, BorderColor, border_color) } internal F32 ui_top_squish(void) { UI_StackTopImpl(ui_state, Squish, squish) } internal OS_Cursor ui_top_hover_cursor(void) { UI_StackTopImpl(ui_state, HoverCursor, hover_cursor) } internal FNT_Tag ui_top_font(void) { UI_StackTopImpl(ui_state, Font, font) } @@ -92,6 +94,7 @@ internal UI_Key ui_bottom_group_key(void) { UI_StackBottomImpl(ui_state, GroupKe internal F32 ui_bottom_transparency(void) { UI_StackBottomImpl(ui_state, Transparency, transparency) } internal Vec4F32 ui_bottom_background_color(void) { UI_StackBottomImpl(ui_state, BackgroundColor, background_color) } internal Vec4F32 ui_bottom_text_color(void) { UI_StackBottomImpl(ui_state, TextColor, text_color) } +internal Vec4F32 ui_bottom_border_color(void) { UI_StackBottomImpl(ui_state, BorderColor, border_color) } internal F32 ui_bottom_squish(void) { UI_StackBottomImpl(ui_state, Squish, squish) } internal OS_Cursor ui_bottom_hover_cursor(void) { UI_StackBottomImpl(ui_state, HoverCursor, hover_cursor) } internal FNT_Tag ui_bottom_font(void) { UI_StackBottomImpl(ui_state, Font, font) } @@ -125,6 +128,7 @@ internal UI_Key ui_push_group_key(UI_Key v) { UI_StackPushImpl(ui_state, GroupKe internal F32 ui_push_transparency(F32 v) { UI_StackPushImpl(ui_state, Transparency, transparency, F32, v) } internal Vec4F32 ui_push_background_color(Vec4F32 v) { UI_StackPushImpl(ui_state, BackgroundColor, background_color, Vec4F32, v) } internal Vec4F32 ui_push_text_color(Vec4F32 v) { UI_StackPushImpl(ui_state, TextColor, text_color, Vec4F32, v) } +internal Vec4F32 ui_push_border_color(Vec4F32 v) { UI_StackPushImpl(ui_state, BorderColor, border_color, Vec4F32, v) } internal F32 ui_push_squish(F32 v) { UI_StackPushImpl(ui_state, Squish, squish, F32, v) } internal OS_Cursor ui_push_hover_cursor(OS_Cursor v) { UI_StackPushImpl(ui_state, HoverCursor, hover_cursor, OS_Cursor, v) } internal FNT_Tag ui_push_font(FNT_Tag v) { UI_StackPushImpl(ui_state, Font, font, FNT_Tag, v) } @@ -158,6 +162,7 @@ internal UI_Key ui_pop_group_key(void) { UI_StackPopImpl(ui_state, GroupKey, gro internal F32 ui_pop_transparency(void) { UI_StackPopImpl(ui_state, Transparency, transparency) } internal Vec4F32 ui_pop_background_color(void) { UI_StackPopImpl(ui_state, BackgroundColor, background_color) } internal Vec4F32 ui_pop_text_color(void) { UI_StackPopImpl(ui_state, TextColor, text_color) } +internal Vec4F32 ui_pop_border_color(void) { UI_StackPopImpl(ui_state, BorderColor, border_color) } internal F32 ui_pop_squish(void) { UI_StackPopImpl(ui_state, Squish, squish) } internal OS_Cursor ui_pop_hover_cursor(void) { UI_StackPopImpl(ui_state, HoverCursor, hover_cursor) } internal FNT_Tag ui_pop_font(void) { UI_StackPopImpl(ui_state, Font, font) } @@ -191,6 +196,7 @@ internal UI_Key ui_set_next_group_key(UI_Key v) { UI_StackSetNextImpl(ui_state, internal F32 ui_set_next_transparency(F32 v) { UI_StackSetNextImpl(ui_state, Transparency, transparency, F32, v) } internal Vec4F32 ui_set_next_background_color(Vec4F32 v) { UI_StackSetNextImpl(ui_state, BackgroundColor, background_color, Vec4F32, v) } internal Vec4F32 ui_set_next_text_color(Vec4F32 v) { UI_StackSetNextImpl(ui_state, TextColor, text_color, Vec4F32, v) } +internal Vec4F32 ui_set_next_border_color(Vec4F32 v) { UI_StackSetNextImpl(ui_state, BorderColor, border_color, Vec4F32, v) } internal F32 ui_set_next_squish(F32 v) { UI_StackSetNextImpl(ui_state, Squish, squish, F32, v) } internal OS_Cursor ui_set_next_hover_cursor(OS_Cursor v) { UI_StackSetNextImpl(ui_state, HoverCursor, hover_cursor, OS_Cursor, v) } internal FNT_Tag ui_set_next_font(FNT_Tag v) { UI_StackSetNextImpl(ui_state, Font, font, FNT_Tag, v) } diff --git a/src/ui/generated/ui.meta.h b/src/ui/generated/ui.meta.h index 2b666b2a..a3a1648b 100644 --- a/src/ui/generated/ui.meta.h +++ b/src/ui/generated/ui.meta.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- GENERATED CODE @@ -27,6 +27,7 @@ typedef struct UI_TransparencyNode UI_TransparencyNode; struct UI_TransparencyNo typedef struct UI_TagNode UI_TagNode; struct UI_TagNode{UI_TagNode *next; String8 v;}; typedef struct UI_BackgroundColorNode UI_BackgroundColorNode; struct UI_BackgroundColorNode{UI_BackgroundColorNode *next; Vec4F32 v;}; typedef struct UI_TextColorNode UI_TextColorNode; struct UI_TextColorNode{UI_TextColorNode *next; Vec4F32 v;}; +typedef struct UI_BorderColorNode UI_BorderColorNode; struct UI_BorderColorNode{UI_BorderColorNode *next; Vec4F32 v;}; typedef struct UI_SquishNode UI_SquishNode; struct UI_SquishNode{UI_SquishNode *next; F32 v;}; typedef struct UI_HoverCursorNode UI_HoverCursorNode; struct UI_HoverCursorNode{UI_HoverCursorNode *next; OS_Cursor v;}; typedef struct UI_FontNode UI_FontNode; struct UI_FontNode{UI_FontNode *next; FNT_Tag v;}; @@ -64,6 +65,7 @@ UI_TransparencyNode transparency_nil_stack_top;\ UI_TagNode tag_nil_stack_top;\ UI_BackgroundColorNode background_color_nil_stack_top;\ UI_TextColorNode text_color_nil_stack_top;\ +UI_BorderColorNode border_color_nil_stack_top;\ UI_SquishNode squish_nil_stack_top;\ UI_HoverCursorNode hover_cursor_nil_stack_top;\ UI_FontNode font_nil_stack_top;\ @@ -100,6 +102,7 @@ state->transparency_nil_stack_top.v = 0;\ state->tag_nil_stack_top.v = str8_lit("");\ state->background_color_nil_stack_top.v = v4f32(0, 0, 0, 0);\ state->text_color_nil_stack_top.v = v4f32(0, 0, 0, 0);\ +state->border_color_nil_stack_top.v = v4f32(0, 0, 0, 0);\ state->squish_nil_stack_top.v = 0;\ state->hover_cursor_nil_stack_top.v = OS_Cursor_Pointer;\ state->font_nil_stack_top.v = fnt_tag_zero();\ @@ -138,6 +141,7 @@ struct { UI_TransparencyNode *top; F32 bottom_val; UI_TransparencyNode *free; U6 struct { UI_TagNode *top; String8 bottom_val; UI_TagNode *free; U64 gen; B32 auto_pop; } tag_stack;\ struct { UI_BackgroundColorNode *top; Vec4F32 bottom_val; UI_BackgroundColorNode *free; U64 gen; B32 auto_pop; } background_color_stack;\ struct { UI_TextColorNode *top; Vec4F32 bottom_val; UI_TextColorNode *free; U64 gen; B32 auto_pop; } text_color_stack;\ +struct { UI_BorderColorNode *top; Vec4F32 bottom_val; UI_BorderColorNode *free; U64 gen; B32 auto_pop; } border_color_stack;\ struct { UI_SquishNode *top; F32 bottom_val; UI_SquishNode *free; U64 gen; B32 auto_pop; } squish_stack;\ struct { UI_HoverCursorNode *top; OS_Cursor bottom_val; UI_HoverCursorNode *free; U64 gen; B32 auto_pop; } hover_cursor_stack;\ struct { UI_FontNode *top; FNT_Tag bottom_val; UI_FontNode *free; U64 gen; B32 auto_pop; } font_stack;\ @@ -174,6 +178,7 @@ state->transparency_stack.top = &state->transparency_nil_stack_top; state->trans state->tag_stack.top = &state->tag_nil_stack_top; state->tag_stack.bottom_val = str8_lit(""); state->tag_stack.free = 0; state->tag_stack.auto_pop = 0;\ state->background_color_stack.top = &state->background_color_nil_stack_top; state->background_color_stack.bottom_val = v4f32(0, 0, 0, 0); state->background_color_stack.free = 0; state->background_color_stack.auto_pop = 0;\ state->text_color_stack.top = &state->text_color_nil_stack_top; state->text_color_stack.bottom_val = v4f32(0, 0, 0, 0); state->text_color_stack.free = 0; state->text_color_stack.auto_pop = 0;\ +state->border_color_stack.top = &state->border_color_nil_stack_top; state->border_color_stack.bottom_val = v4f32(0, 0, 0, 0); state->border_color_stack.free = 0; state->border_color_stack.auto_pop = 0;\ state->squish_stack.top = &state->squish_nil_stack_top; state->squish_stack.bottom_val = 0; state->squish_stack.free = 0; state->squish_stack.auto_pop = 0;\ state->hover_cursor_stack.top = &state->hover_cursor_nil_stack_top; state->hover_cursor_stack.bottom_val = OS_Cursor_Pointer; state->hover_cursor_stack.free = 0; state->hover_cursor_stack.auto_pop = 0;\ state->font_stack.top = &state->font_nil_stack_top; state->font_stack.bottom_val = fnt_tag_zero(); state->font_stack.free = 0; state->font_stack.auto_pop = 0;\ @@ -210,6 +215,7 @@ if(state->transparency_stack.auto_pop) { ui_pop_transparency(); state->transpare if(state->tag_stack.auto_pop) { ui_pop_tag(); state->tag_stack.auto_pop = 0; }\ if(state->background_color_stack.auto_pop) { ui_pop_background_color(); state->background_color_stack.auto_pop = 0; }\ if(state->text_color_stack.auto_pop) { ui_pop_text_color(); state->text_color_stack.auto_pop = 0; }\ +if(state->border_color_stack.auto_pop) { ui_pop_border_color(); state->border_color_stack.auto_pop = 0; }\ if(state->squish_stack.auto_pop) { ui_pop_squish(); state->squish_stack.auto_pop = 0; }\ if(state->hover_cursor_stack.auto_pop) { ui_pop_hover_cursor(); state->hover_cursor_stack.auto_pop = 0; }\ if(state->font_stack.auto_pop) { ui_pop_font(); state->font_stack.auto_pop = 0; }\ @@ -245,6 +251,7 @@ internal F32 ui_top_transparency(void); internal String8 ui_top_tag(void); internal Vec4F32 ui_top_background_color(void); internal Vec4F32 ui_top_text_color(void); +internal Vec4F32 ui_top_border_color(void); internal F32 ui_top_squish(void); internal OS_Cursor ui_top_hover_cursor(void); internal FNT_Tag ui_top_font(void); @@ -279,6 +286,7 @@ internal F32 ui_bottom_transparency(void); internal String8 ui_bottom_tag(void); internal Vec4F32 ui_bottom_background_color(void); internal Vec4F32 ui_bottom_text_color(void); +internal Vec4F32 ui_bottom_border_color(void); internal F32 ui_bottom_squish(void); internal OS_Cursor ui_bottom_hover_cursor(void); internal FNT_Tag ui_bottom_font(void); @@ -313,6 +321,7 @@ internal F32 ui_push_transparency(F32 v); internal String8 ui_push_tag(String8 v); internal Vec4F32 ui_push_background_color(Vec4F32 v); internal Vec4F32 ui_push_text_color(Vec4F32 v); +internal Vec4F32 ui_push_border_color(Vec4F32 v); internal F32 ui_push_squish(F32 v); internal OS_Cursor ui_push_hover_cursor(OS_Cursor v); internal FNT_Tag ui_push_font(FNT_Tag v); @@ -347,6 +356,7 @@ internal F32 ui_pop_transparency(void); internal String8 ui_pop_tag(void); internal Vec4F32 ui_pop_background_color(void); internal Vec4F32 ui_pop_text_color(void); +internal Vec4F32 ui_pop_border_color(void); internal F32 ui_pop_squish(void); internal OS_Cursor ui_pop_hover_cursor(void); internal FNT_Tag ui_pop_font(void); @@ -381,6 +391,7 @@ internal F32 ui_set_next_transparency(F32 v); internal String8 ui_set_next_tag(String8 v); internal Vec4F32 ui_set_next_background_color(Vec4F32 v); internal Vec4F32 ui_set_next_text_color(Vec4F32 v); +internal Vec4F32 ui_set_next_border_color(Vec4F32 v); internal F32 ui_set_next_squish(F32 v); internal OS_Cursor ui_set_next_hover_cursor(OS_Cursor v); internal FNT_Tag ui_set_next_font(FNT_Tag v); diff --git a/src/ui/ui.mdesk b/src/ui/ui.mdesk index cbe35c8a..0617f18a 100644 --- a/src/ui/ui.mdesk +++ b/src/ui/ui.mdesk @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //- rjf: stack table @@ -38,6 +38,7 @@ UI_StackTable: { Tag tag String8 `str8_lit("")` 1 } { BackgroundColor background_color Vec4F32 `v4f32(0, 0, 0, 0)` } { TextColor text_color Vec4F32 `v4f32(0, 0, 0, 0)` } + { BorderColor border_color Vec4F32 `v4f32(0, 0, 0, 0)` } //- rjf: squish { Squish squish F32 0 } diff --git a/src/ui/ui_basic_widgets.c b/src/ui/ui_basic_widgets.c index de24ce72..f4b28a38 100644 --- a/src/ui/ui_basic_widgets.c +++ b/src/ui/ui_basic_widgets.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// diff --git a/src/ui/ui_basic_widgets.h b/src/ui/ui_basic_widgets.h index 31c592a3..a2ca4159 100644 --- a/src/ui/ui_basic_widgets.h +++ b/src/ui/ui_basic_widgets.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef UI_BASIC_WIDGETS_H diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index 9659939d..6f2bda61 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// @@ -15,13 +15,6 @@ thread_static UI_State *ui_state = 0; # include "third_party/xxHash/xxhash.h" #endif -internal U64 -ui_hash_from_string(U64 seed, String8 string) -{ - U64 result = XXH3_64bits_withSeed(string.str, string.size, seed); - return result; -} - internal String8 ui_hash_part_from_key_string(String8 string) { @@ -68,7 +61,7 @@ ui_key_from_string(UI_Key seed_key, String8 string) if(string.size != 0) { String8 hash_part = ui_hash_part_from_key_string(string); - result.u64[0] = ui_hash_from_string(seed_key.u64[0], hash_part); + result.u64[0] = u64_hash_from_seed_str8(seed_key.u64[0], hash_part); } ProfEnd(); return result; @@ -2606,6 +2599,21 @@ ui_build_box_from_key(UI_BoxFlags flags, UI_Key key) box->text_color = ui_color_from_name(str8_lit("text")); } } + if(box->flags & (UI_BoxFlag_DrawBorder| + UI_BoxFlag_DrawSideRight| + UI_BoxFlag_DrawSideLeft| + UI_BoxFlag_DrawSideTop| + UI_BoxFlag_DrawSideBottom)) + { + if(ui_state->border_color_stack.top != &ui_state->border_color_nil_stack_top) + { + box->border_color = ui_state->border_color_stack.top->v; + } + else + { + box->border_color = ui_color_from_name(str8_lit("border")); + } + } } //- rjf: auto-pop all stacks diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index 1c915ee5..79c6f3e9 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef UI_H @@ -396,6 +396,7 @@ struct UI_Box void *custom_draw_user_data; Vec4F32 background_color; Vec4F32 text_color; + Vec4F32 border_color; FNT_Tag font; F32 font_size; F32 tab_size; @@ -751,7 +752,6 @@ struct UI_State //////////////////////////////// //~ rjf: Basic Type Functions -internal U64 ui_hash_from_string(U64 seed, String8 string); internal String8 ui_hash_part_from_key_string(String8 string); internal String8 ui_display_part_from_key_string(String8 string); internal UI_Key ui_key_zero(void); @@ -969,6 +969,8 @@ internal F32 ui_top_fixed_width(void); internal F32 ui_top_fixed_height(void); internal UI_Size ui_top_pref_width(void); internal UI_Size ui_top_pref_height(void); +internal F32 ui_top_min_width(void); +internal F32 ui_top_min_height(void); internal UI_PermissionFlags ui_top_permission_flags(void); internal UI_BoxFlags ui_top_flags(void); internal UI_BoxFlags ui_top_omit_flags(void); @@ -980,6 +982,7 @@ internal F32 ui_top_transparency(void); internal String8 ui_top_tag(void); internal Vec4F32 ui_top_background_color(void); internal Vec4F32 ui_top_text_color(void); +internal Vec4F32 ui_top_border_color(void); internal F32 ui_top_squish(void); internal OS_Cursor ui_top_hover_cursor(void); internal FNT_Tag ui_top_font(void); @@ -1001,6 +1004,8 @@ internal F32 ui_bottom_fixed_width(void); internal F32 ui_bottom_fixed_height(void); internal UI_Size ui_bottom_pref_width(void); internal UI_Size ui_bottom_pref_height(void); +internal F32 ui_bottom_min_width(void); +internal F32 ui_bottom_min_height(void); internal UI_PermissionFlags ui_bottom_permission_flags(void); internal UI_BoxFlags ui_bottom_flags(void); internal UI_BoxFlags ui_bottom_omit_flags(void); @@ -1012,6 +1017,7 @@ internal F32 ui_bottom_transparency(void); internal String8 ui_bottom_tag(void); internal Vec4F32 ui_bottom_background_color(void); internal Vec4F32 ui_bottom_text_color(void); +internal Vec4F32 ui_bottom_border_color(void); internal F32 ui_bottom_squish(void); internal OS_Cursor ui_bottom_hover_cursor(void); internal FNT_Tag ui_bottom_font(void); @@ -1033,6 +1039,8 @@ internal F32 ui_push_fixed_width(F32 v); internal F32 ui_push_fixed_height(F32 v); internal UI_Size ui_push_pref_width(UI_Size v); internal UI_Size ui_push_pref_height(UI_Size v); +internal F32 ui_push_min_width(F32 v); +internal F32 ui_push_min_height(F32 v); internal UI_PermissionFlags ui_push_permission_flags(UI_PermissionFlags v); internal UI_BoxFlags ui_push_flags(UI_BoxFlags v); internal UI_BoxFlags ui_push_omit_flags(UI_BoxFlags v); @@ -1044,6 +1052,7 @@ internal F32 ui_push_transparency(F32 v); internal String8 ui_push_tag(String8 v); internal Vec4F32 ui_push_background_color(Vec4F32 v); internal Vec4F32 ui_push_text_color(Vec4F32 v); +internal Vec4F32 ui_push_border_color(Vec4F32 v); internal F32 ui_push_squish(F32 v); internal OS_Cursor ui_push_hover_cursor(OS_Cursor v); internal FNT_Tag ui_push_font(FNT_Tag v); @@ -1065,6 +1074,8 @@ internal F32 ui_pop_fixed_width(void); internal F32 ui_pop_fixed_height(void); internal UI_Size ui_pop_pref_width(void); internal UI_Size ui_pop_pref_height(void); +internal F32 ui_pop_min_width(void); +internal F32 ui_pop_min_height(void); internal UI_PermissionFlags ui_pop_permission_flags(void); internal UI_BoxFlags ui_pop_flags(void); internal UI_BoxFlags ui_pop_omit_flags(void); @@ -1076,6 +1087,7 @@ internal F32 ui_pop_transparency(void); internal String8 ui_pop_tag(void); internal Vec4F32 ui_pop_background_color(void); internal Vec4F32 ui_pop_text_color(void); +internal Vec4F32 ui_pop_border_color(void); internal F32 ui_pop_squish(void); internal OS_Cursor ui_pop_hover_cursor(void); internal FNT_Tag ui_pop_font(void); @@ -1097,6 +1109,8 @@ internal F32 ui_set_next_fixed_width(F32 v); internal F32 ui_set_next_fixed_height(F32 v); internal UI_Size ui_set_next_pref_width(UI_Size v); internal UI_Size ui_set_next_pref_height(UI_Size v); +internal F32 ui_set_next_min_width(F32 v); +internal F32 ui_set_next_min_height(F32 v); internal UI_PermissionFlags ui_set_next_permission_flags(UI_PermissionFlags v); internal UI_BoxFlags ui_set_next_flags(UI_BoxFlags v); internal UI_BoxFlags ui_set_next_omit_flags(UI_BoxFlags v); @@ -1108,6 +1122,7 @@ internal F32 ui_set_next_transparency(F32 v); internal String8 ui_set_next_tag(String8 v); internal Vec4F32 ui_set_next_background_color(Vec4F32 v); internal Vec4F32 ui_set_next_text_color(Vec4F32 v); +internal Vec4F32 ui_set_next_border_color(Vec4F32 v); internal F32 ui_set_next_squish(F32 v); internal OS_Cursor ui_set_next_hover_cursor(OS_Cursor v); internal FNT_Tag ui_set_next_font(FNT_Tag v); diff --git a/src/ui/ui_inc.c b/src/ui/ui_inc.c index c9bed64e..72ba4357 100644 --- a/src/ui/ui_inc.c +++ b/src/ui/ui_inc.c @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #undef LAYER_COLOR diff --git a/src/ui/ui_inc.h b/src/ui/ui_inc.h index 2b763f3b..3e95155d 100644 --- a/src/ui/ui_inc.h +++ b/src/ui/ui_inc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Epic Games Tools +// Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #ifndef UI_INC_H