From 7c9f127425de9f640f8fb59643894ef326a5a0d8 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Sat, 24 Feb 2024 22:03:08 -0800 Subject: [PATCH] cleanup/naming pass over raddbgi_dump, do not require specific named params --- build.bat | 2 +- src/lib_raddbgi_format/raddbgi_format_parse.c | 47 +- src/lib_raddbgi_format/raddbgi_format_parse.h | 1 + src/raddbgi_dump/raddbgi_dump.c | 1116 +++++++++++------ src/raddbgi_dump/raddbgi_dump.h | 100 +- src/raddbgi_dump/raddbgi_dump_main.c | 413 ++++++ src/raddbgi_dump/raddbgi_stringize.c | 776 ------------ src/raddbgi_dump/raddbgi_stringize.h | 114 -- 8 files changed, 1234 insertions(+), 1335 deletions(-) create mode 100644 src/raddbgi_dump/raddbgi_dump_main.c delete mode 100644 src/raddbgi_dump/raddbgi_stringize.c delete mode 100644 src/raddbgi_dump/raddbgi_stringize.h diff --git a/build.bat b/build.bat index 4db67b11..56121a31 100644 --- a/build.bat +++ b/build.bat @@ -101,7 +101,7 @@ pushd build if "%raddbg%"=="1" %compile% %gfx% ..\src\raddbg\raddbg_main.cpp %compile_link% %out%raddbg.exe || exit /b 1 if "%raddbgi_from_pdb%"=="1" %compile% ..\src\raddbgi_from_pdb\raddbgi_from_pdb_main.c %compile_link% %out%raddbgi_from_pdb.exe || exit /b 1 if "%raddbgi_from_dwarf%"=="1" %compile% ..\src\raddbgi_from_dwarf\raddbgi_from_dwarf.c %compile_link% %out%raddbgi_from_dwarf.exe || exit /b 1 -if "%raddbgi_dump%"=="1" %compile% ..\src\raddbgi_dump\raddbgi_dump.c %compile_link% %out%raddbgi_dump.exe || exit /b 1 +if "%raddbgi_dump%"=="1" %compile% ..\src\raddbgi_dump\raddbgi_dump_main.c %compile_link% %out%raddbgi_dump.exe || exit /b 1 if "%ryan_scratch%"=="1" %compile% ..\src\scratch\ryan_scratch.c %compile_link% %out%ryan_scratch.exe || exit /b 1 if "%cpp_tests%"=="1" %compile% ..\src\scratch\i_hate_c_plus_plus.cpp %compile_link% %out%cpp_tests.exe || exit /b 1 if "%look_at_raddbg%"=="1" %compile% ..\src\scratch\look_at_raddbg.c %compile_link% %out%look_at_raddbg.exe || exit /b 1 diff --git a/src/lib_raddbgi_format/raddbgi_format_parse.c b/src/lib_raddbgi_format/raddbgi_format_parse.c index cbd6a880..4f6e0b4e 100644 --- a/src/lib_raddbgi_format/raddbgi_format_parse.c +++ b/src/lib_raddbgi_format/raddbgi_format_parse.c @@ -5,7 +5,8 @@ //~ RADDBG Parse API RDI_PROC RDI_ParseStatus -rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out){ +rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out) +{ RDI_ParseStatus result = RDI_ParseStatus_Good; // out header @@ -193,30 +194,30 @@ rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out){ } } } - -#if !defined(RDI_DISABLE_NILS) - if(out->binary_sections == 0) { out->binary_sections = &rdi_binary_section_nil; out->binary_sections_count = 1; } - if(out->file_paths == 0) { out->file_paths = &rdi_file_path_node_nil; out->file_paths_count = 1; } - if(out->source_files == 0) { out->source_files = &rdi_source_file_nil; out->source_files_count = 1; } - if(out->units == 0) { out->units = &rdi_unit_nil; out->units_count = 1; } - if(out->unit_vmap == 0) { out->unit_vmap = &rdi_vmap_entry_nil; out->unit_vmap_count = 1; } - if(out->type_nodes == 0) { out->type_nodes = &rdi_type_node_nil; out->type_nodes_count = 1; } - if(out->udts == 0) { out->udts = &rdi_udt_nil; out->udts_count = 1; } - if(out->members == 0) { out->members = &rdi_member_nil; out->members_count = 1; } - if(out->enum_members == 0) { out->enum_members = &rdi_enum_member_nil; out->enum_members_count = 1; } - if(out->global_variables == 0) { out->global_variables = &rdi_global_variable_nil; out->global_variables_count = 1; } - if(out->global_vmap == 0) { out->global_vmap = &rdi_vmap_entry_nil; out->global_vmap_count = 1; } - if(out->thread_variables == 0) { out->thread_variables = &rdi_thread_variable_nil; out->thread_variables_count = 1; } - if(out->procedures == 0) { out->procedures = &rdi_procedure_nil; out->procedures_count = 1; } - if(out->scopes == 0) { out->scopes = &rdi_scope_nil; out->scopes_count = 1; } - if(out->scope_voffs == 0) { out->scope_voffs = &rdi_voff_nil; out->scope_voffs_count = 1; } - if(out->scope_vmap == 0) { out->scope_vmap = &rdi_vmap_entry_nil; out->scope_vmap_count = 1; } - if(out->locals == 0) { out->locals = &rdi_local_nil; out->locals_count = 1; } - if(out->location_blocks == 0) { out->location_blocks = &rdi_location_block_nil; out->location_blocks_count = 1; } -#endif - } +#if !defined(RDI_DISABLE_NILS) + if(out->top_level_info == 0) { out->top_level_info = &rdi_top_level_info_nil; } + if(out->binary_sections == 0) { out->binary_sections = &rdi_binary_section_nil; out->binary_sections_count = 1; } + if(out->file_paths == 0) { out->file_paths = &rdi_file_path_node_nil; out->file_paths_count = 1; } + if(out->source_files == 0) { out->source_files = &rdi_source_file_nil; out->source_files_count = 1; } + if(out->units == 0) { out->units = &rdi_unit_nil; out->units_count = 1; } + if(out->unit_vmap == 0) { out->unit_vmap = &rdi_vmap_entry_nil; out->unit_vmap_count = 1; } + if(out->type_nodes == 0) { out->type_nodes = &rdi_type_node_nil; out->type_nodes_count = 1; } + if(out->udts == 0) { out->udts = &rdi_udt_nil; out->udts_count = 1; } + if(out->members == 0) { out->members = &rdi_member_nil; out->members_count = 1; } + if(out->enum_members == 0) { out->enum_members = &rdi_enum_member_nil; out->enum_members_count = 1; } + if(out->global_variables == 0) { out->global_variables = &rdi_global_variable_nil; out->global_variables_count = 1; } + if(out->global_vmap == 0) { out->global_vmap = &rdi_vmap_entry_nil; out->global_vmap_count = 1; } + if(out->thread_variables == 0) { out->thread_variables = &rdi_thread_variable_nil; out->thread_variables_count = 1; } + if(out->procedures == 0) { out->procedures = &rdi_procedure_nil; out->procedures_count = 1; } + if(out->scopes == 0) { out->scopes = &rdi_scope_nil; out->scopes_count = 1; } + if(out->scope_voffs == 0) { out->scope_voffs = &rdi_voff_nil; out->scope_voffs_count = 1; } + if(out->scope_vmap == 0) { out->scope_vmap = &rdi_vmap_entry_nil; out->scope_vmap_count = 1; } + if(out->locals == 0) { out->locals = &rdi_local_nil; out->locals_count = 1; } + if(out->location_blocks == 0) { out->location_blocks = &rdi_location_block_nil; out->location_blocks_count = 1; } +#endif + return(result); } diff --git a/src/lib_raddbgi_format/raddbgi_format_parse.h b/src/lib_raddbgi_format/raddbgi_format_parse.h index 97377f93..9e97bcb3 100644 --- a/src/lib_raddbgi_format/raddbgi_format_parse.h +++ b/src/lib_raddbgi_format/raddbgi_format_parse.h @@ -128,6 +128,7 @@ typedef struct RDI_ParsedNameMap{ //~ Global Nils #if !defined(RDI_DISABLE_NILS) +static RDI_TopLevelInfo rdi_top_level_info_nil = {0}; static RDI_BinarySection rdi_binary_section_nil = {0}; static RDI_FilePathNode rdi_file_path_node_nil = {0}; static RDI_SourceFile rdi_source_file_nil = {0}; diff --git a/src/raddbgi_dump/raddbgi_dump.c b/src/raddbgi_dump/raddbgi_dump.c index fbc18af4..019be63b 100644 --- a/src/raddbgi_dump/raddbgi_dump.c +++ b/src/raddbgi_dump/raddbgi_dump.c @@ -1,430 +1,774 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -#include "lib_raddbgi_format/raddbgi_format.h" -#include "lib_raddbgi_format/raddbgi_format_parse.h" -#include "lib_raddbgi_format/raddbgi_format.c" -#include "lib_raddbgi_format/raddbgi_format_parse.c" - -#include "base/base_inc.h" -#include "os/os_inc.h" - -#include "raddbgi_stringize.h" -#include "raddbgi_dump.h" - -#include "base/base_inc.c" -#include "os/os_inc.c" - -#include "raddbgi_stringize.c" - //////////////////////////////// -//~ Program Parameters Parser +//~ rjf: RADDBGI Enum -> String Functions -static RADDBGIDUMP_Params* -raddbgidump_params_from_cmd_line(Arena *arena, CmdLine *cmdline){ - RADDBGIDUMP_Params *result = push_array(arena, RADDBGIDUMP_Params, 1); - - // get input raddbg - { - String8 input_name = cmd_line_string(cmdline, str8_lit("raddbg")); - if (input_name.size == 0){ - str8_list_push(arena, &result->errors, - str8_lit("missing required parameter '--raddbg:'")); - } - - if (input_name.size > 0){ - String8 input_data = os_data_from_file_path(arena, input_name); - - if (input_data.size == 0){ - str8_list_pushf(arena, &result->errors, - "could not load input file '%.*s'", str8_varg(input_name)); - } - - if (input_data.size != 0){ - result->input_name = input_name; - result->input_data = input_data; - } - } +internal String8 +rdi_string_from_data_section_tag(RDI_DataSectionTag tag){ + String8 result = {0}; + switch (tag){ +#define X(N,C) case C: result = str8_lit(#N); break; +#define Y(N) + RDI_DataSectionTagXList(X,Y) +#undef X +#undef Y } - - // error options - if (cmd_line_has_flag(cmdline, str8_lit("hide_errors"))){ - String8List vals = cmd_line_strings(cmdline, str8_lit("hide_errors")); - - // if no values - set all to hidden - if (vals.node_count == 0){ - B8 *ptr = (B8*)&result->hide_errors; - B8 *opl = ptr + sizeof(result->hide_errors); - for (;ptr < opl; ptr += 1){ - *ptr = 1; - } - } - - // for each explicit value set the corresponding flag to hidden - for (String8Node *node = vals.first; - node != 0; - node = node->next){ - if (str8_match(node->string, str8_lit("input"), 0)){ - result->hide_errors.input = 1; - } - } + return(result); +} + +internal String8 +rdi_string_from_arch(RDI_Arch arch){ + String8 result = {0}; + switch (arch){ + default: result = str8_lit(""); break; + case RDI_Arch_X86: result = str8_lit("x86"); break; + case RDI_Arch_X64: result = str8_lit("x64"); break; } - - // dump options - { - String8List vals = cmd_line_strings(cmdline, str8_lit("dump")); - if (vals.first == 0){ - B8 *ptr = &result->dump__first; - for (; ptr < &result->dump__last; ptr += 1){ - *ptr = 1; - } - } - else{ - for (String8Node *node = vals.first; - node != 0; - node = node->next){ - if (str8_match(node->string, str8_lit("data_sections"), 0)){ - result->dump_data_sections = 1; - } - else if (str8_match(node->string, str8_lit("top_level_info"), 0)){ - result->dump_top_level_info = 1; - } - else if (str8_match(node->string, str8_lit("binary_sections"), 0)){ - result->dump_binary_sections = 1; - } - else if (str8_match(node->string, str8_lit("file_paths"), 0)){ - result->dump_file_paths = 1; - } - else if (str8_match(node->string, str8_lit("source_files"), 0)){ - result->dump_source_files = 1; - } - else if (str8_match(node->string, str8_lit("units"), 0)){ - result->dump_units = 1; - } - else if (str8_match(node->string, str8_lit("unit_vmap"), 0)){ - result->dump_unit_vmap = 1; - } - else if (str8_match(node->string, str8_lit("type_nodes"), 0)){ - result->dump_type_nodes = 1; - } - else if (str8_match(node->string, str8_lit("udt_data"), 0)){ - result->dump_udt_data = 1; - } - else if (str8_match(node->string, str8_lit("global_variables"), 0)){ - result->dump_global_variables = 1; - } - else if (str8_match(node->string, str8_lit("global_vmap"), 0)){ - result->dump_global_vmap = 1; - } - else if (str8_match(node->string, str8_lit("thread_variables"), 0)){ - result->dump_thread_variables = 1; - } - else if (str8_match(node->string, str8_lit("procedures"), 0)){ - result->dump_procedures = 1; - } - else if (str8_match(node->string, str8_lit("scopes"), 0)){ - result->dump_scopes = 1; - } - else if (str8_match(node->string, str8_lit("scope_vmap"), 0)){ - result->dump_scope_vmap = 1; - } - } - } + return(result); +} + +internal String8 +rdi_string_from_language(RDI_Language language){ + String8 result = {0}; + switch (language){ +#define X(name,code) case code: result = str8_lit(#name); break; + RDI_LanguageXList(X) +#undef X + } + return(result); +} + +internal String8 +rdi_string_from_type_kind(RDI_TypeKind type_kind){ + String8 result = {0}; + switch (type_kind){ + default: result = str8_lit(""); break; +#define X(name,code) case code: result = str8_lit(#name); break; +#define XZ(name,code,size) X(name,code) +#define Y(a,n) + RDI_TypeKindXList(X,XZ,Y) +#undef X +#undef XZ +#undef Y + } + return(result); +} + +internal String8 +rdi_string_from_member_kind(RDI_MemberKind member_kind){ + String8 result = {0}; + switch (member_kind){ + default: result = str8_lit(""); break; +#define X(N,C) case C: result = str8_lit(#N); break; + RDI_MemberKindXList(X) +#undef X + } + return(result); +} + +internal String8 +rdi_string_from_local_kind(RDI_LocalKind local_kind){ + String8 result = {0}; + switch (local_kind){ + default: result = str8_lit(""); break; + case RDI_LocalKind_Parameter: result = str8_lit("Parameter"); break; + case RDI_LocalKind_Variable: result = str8_lit("Variable"); break; } - return(result); } //////////////////////////////// -//~ Entry Point +//~ rjf: RADDBGI Flags -> String Functions -int -main(int argc, char **argv){ - local_persist TCTX main_thread_tctx = {0}; - tctx_init_and_equip(&main_thread_tctx); - Arena *arena = arena_alloc(); - String8List args = os_string_list_from_argcv(arena, argc, argv); - CmdLine cmdline = cmd_line_from_string_list(arena, args); +internal void +rdi_stringize_binary_section_flags(Arena *arena, String8List *out, + RDI_BinarySectionFlags flags){ + if (flags == 0){ + str8_list_push(arena, out, str8_lit("0")); + } + if (flags & RDI_BinarySectionFlag_Read){ + str8_list_push(arena, out, str8_lit("Read ")); + } + if (flags & RDI_BinarySectionFlag_Write){ + str8_list_push(arena, out, str8_lit("Write ")); + } + if (flags & RDI_BinarySectionFlag_Execute){ + str8_list_push(arena, out, str8_lit("Execute ")); + } +} + +internal void +rdi_stringize_type_modifier_flags(Arena *arena, String8List *out, + RDI_TypeModifierFlags flags){ + if (flags == 0){ + str8_list_push(arena, out, str8_lit("0")); + } + if (flags & RDI_TypeModifierFlag_Const){ + str8_list_push(arena, out, str8_lit("Const ")); + } + if (flags & RDI_TypeModifierFlag_Volatile){ + str8_list_push(arena, out, str8_lit("Volatile ")); + } +} + +internal void +rdi_stringize_user_defined_type_flags(Arena *arena, String8List *out, + RDI_UserDefinedTypeFlags flags){ + if (flags == 0){ + str8_list_push(arena, out, str8_lit("0")); + } + if (flags & RDI_UserDefinedTypeFlag_EnumMembers){ + str8_list_push(arena, out, str8_lit("EnumMembers ")); + } +} + +internal void +rdi_stringize_link_flags(Arena *arena, String8List *out, RDI_LinkFlags flags){ + if (flags == 0){ + str8_list_push(arena, out, str8_lit("0")); + } + if (flags & RDI_LinkFlag_External){ + str8_list_push(arena, out, str8_lit("External ")); + } + if (flags & RDI_LinkFlag_TypeScoped){ + str8_list_push(arena, out, str8_lit("TypeScoped ")); + } + if (flags & RDI_LinkFlag_ProcScoped){ + str8_list_push(arena, out, str8_lit("ProcScoped ")); + } +} + +//////////////////////////////// +//~ rjf: RADDBG Compound Stringize Functions + +global char rdi_stringize_spaces[] = " "; + +internal void +rdi_stringize_data_sections(Arena *arena, String8List *out, RDI_Parsed *parsed, + U32 indent_level){ + U64 data_section_count = parsed->dsec_count; + RDI_DataSection *ptr = parsed->dsecs; + for (U64 i = 0; i < data_section_count; i += 1, ptr += 1){ + String8 tag_str = rdi_string_from_data_section_tag(ptr->tag); + str8_list_pushf(arena, out, "%.*sdata_section[%5u] = {0x%08llx, %7u, %7u} %.*s\n", + indent_level, rdi_stringize_spaces, + i, ptr->off, ptr->encoded_size, ptr->unpacked_size, str8_varg(tag_str)); + } +} + +internal void +rdi_stringize_top_level_info(Arena *arena, String8List *out, RDI_Parsed *parsed, + RDI_TopLevelInfo *tli, U32 indent_level){ + String8 arch_str = rdi_string_from_arch(tli->architecture); + String8 exe_name = {0}; + exe_name.str = rdi_string_from_idx(parsed, tli->exe_name_string_idx, &exe_name.size); - RADDBGIDUMP_Params *params = raddbgidump_params_from_cmd_line(arena, &cmdline); + str8_list_pushf(arena, out, "%.*sarchitecture=%.*s\n", + indent_level, rdi_stringize_spaces, str8_varg(arch_str)); + str8_list_pushf(arena, out, "%.*sexe_name='%.*s'\n", + indent_level, rdi_stringize_spaces, str8_varg(exe_name)); + str8_list_pushf(arena, out, "%.*svoff_max=0x%08llx\n", + indent_level, rdi_stringize_spaces, tli->voff_max); +} + +internal void +rdi_stringize_binary_section(Arena *arena, String8List *out, RDI_Parsed *parsed, + RDI_BinarySection *bin_section, U32 indent_level){ + String8 name = {0}; + name.str = rdi_string_from_idx(parsed, bin_section->name_string_idx, &name.size); + str8_list_pushf(arena, out, "%.*sname='%.*s'\n", + indent_level, rdi_stringize_spaces, str8_varg(name)); - // show input errors - if (params->errors.node_count > 0 && - !params->hide_errors.input){ - for (String8Node *node = params->errors.first; - node != 0; - node = node->next){ - fprintf(stderr, "error(input): %.*s\n", str8_varg(node->string)); + str8_list_pushf(arena, out, "%.*sflags=", indent_level, rdi_stringize_spaces); + rdi_stringize_binary_section_flags(arena, out, bin_section->flags); + str8_list_pushf(arena, out, "\n"); + + str8_list_pushf(arena, out, "%.*svoff_first=0x%08x\n", + indent_level, rdi_stringize_spaces, bin_section->voff_first); + str8_list_pushf(arena, out, "%.*svoff_opl =0x%08x\n", + indent_level, rdi_stringize_spaces, bin_section->voff_opl); + str8_list_pushf(arena, out, "%.*sfoff_first=0x%08x\n", + indent_level, rdi_stringize_spaces, bin_section->foff_first); + str8_list_pushf(arena, out, "%.*sfoff_opl =0x%08x\n", + indent_level, rdi_stringize_spaces, bin_section->foff_opl); +} + +internal void +rdi_stringize_file_path(Arena *arena, String8List *out, RDI_Parsed *parsed, + RDI_FilePathBundle *bundle, RDI_FilePathNode *file_path, + U32 indent_level){ + String8 name = {0}; + name.str = rdi_string_from_idx(parsed, file_path->name_string_idx, &name.size); + + U32 this_idx = (U32)(file_path - bundle->file_paths); + + if (file_path->source_file_idx == 0){ + str8_list_pushf(arena, out, "%.*s[%u] '%.*s'\n", + indent_level, rdi_stringize_spaces, + this_idx, str8_varg(name)); + } + else{ + str8_list_pushf(arena, out, "%.*s[%u] '%.*s'; source_file=%u\n", + indent_level, rdi_stringize_spaces, + this_idx, str8_varg(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 < bundle->file_path_count){ + child_node = bundle->file_paths + child; + } + if (child_node == 0){ + break; + } + + // stringize child + rdi_stringize_file_path(arena, out, parsed, bundle, child_node, indent_level + 1); + + // increment iterator + child = child_node->next_sibling; + } +} + +internal void +rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *parsed, + RDI_SourceFile *source_file, U32 indent_level){ + // extract line map data + RDI_ParsedLineMap line_map = {0}; + rdi_line_map_from_source_file(parsed, source_file, &line_map); + + // stringize line map data + str8_list_pushf(arena, out, "%.*slines:\n", indent_level, rdi_stringize_spaces); + + for (U32 i = 0; i < line_map.count; i += 1){ + U32 line_num = line_map.nums[i]; + + U32 digit_count = 1; + if (line_num > 0){ + U32 x = line_num; + for (;;){ + x /= 10; + if (x == 0){ + break; + } + digit_count += 1; + } + } + + str8_list_pushf(arena, out, "%.*s %u: ", + indent_level, rdi_stringize_spaces, line_num); + + U32 first = line_map.ranges[i]; + U32 opl_raw = line_map.ranges[i + 1]; + U32 opl = ClampTop(opl_raw, line_map.voff_count); + for (U32 j = first; j < opl; j += 1){ + if (j == first){ + str8_list_pushf(arena, out, "0x%08x\n", line_map.voffs[j]); + } + else{ + str8_list_pushf(arena, out, "%.*s0x%08x\n", + indent_level + digit_count + 3, rdi_stringize_spaces, + line_map.voffs[j]); + } + } + } +} + +internal void +rdi_stringize_unit(Arena *arena, String8List *out, RDI_Parsed *parsed, + RDI_Unit *unit, U32 indent_level){ + String8 unit_name = {0}; + unit_name.str = rdi_string_from_idx(parsed, unit->unit_name_string_idx, &unit_name.size); + String8 compiler_name = {0}; + compiler_name.str = rdi_string_from_idx(parsed, unit->compiler_name_string_idx, + &compiler_name.size); + + str8_list_pushf(arena, out, "%.*sunit_name='%.*s'\n", + indent_level, rdi_stringize_spaces, str8_varg(unit_name)); + str8_list_pushf(arena, out, "%.*scompiler_name='%.*s'\n", + indent_level, rdi_stringize_spaces, str8_varg(compiler_name)); + + str8_list_pushf(arena, out, "%.*ssource_file_path=%u\n", + indent_level, rdi_stringize_spaces, unit->source_file_path_node); + str8_list_pushf(arena, out, "%.*sobject_file_path=%u\n", + indent_level, rdi_stringize_spaces, unit->object_file_path_node); + str8_list_pushf(arena, out, "%.*sarchive_file_path=%u\n", + indent_level, rdi_stringize_spaces, unit->archive_file_path_node); + str8_list_pushf(arena, out, "%.*sbuild_path=%u\n", + indent_level, rdi_stringize_spaces, unit->build_path_node); + + String8 language_str = rdi_string_from_language(unit->language); + str8_list_pushf(arena, out, "%.*slanguage=%.*s\n", + indent_level, rdi_stringize_spaces, str8_varg(language_str)); + + // extract line info data + RDI_ParsedLineInfo line_info = {0}; + rdi_line_info_from_unit(parsed, unit, &line_info); + + + // stringize line info + str8_list_pushf(arena, out, "%.*slines:\n", indent_level, rdi_stringize_spaces); + + for (U32 i = 0; i < line_info.count; i += 1){ + U64 first = line_info.voffs[i]; + U64 opl = line_info.voffs[i + 1]; + RDI_Line *line = line_info.lines + i; + RDI_Column *col = 0; + if (i < line_info.col_count){ + col = line_info.cols + i; + } + + if (col == 0){ + str8_list_pushf(arena, out, "%.*s [0x%08llx,0x%08llx) file=%u; line=%u\n", + indent_level, rdi_stringize_spaces, + first, opl, line->file_idx, line->line_num); + } + else{ + str8_list_pushf(arena, out, "%.*s [0x%08llx,0x%08llx) file=%u; line=%u; columns=[%u,%u)\n", + indent_level, rdi_stringize_spaces, + first, opl, line->file_idx, line->line_num, + col->col_first, col->col_opl); + } + } +} + +internal void +rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, + RDI_TypeNode *type, U32 indent_level){ + RDI_TypeKind kind = type->kind; + String8 type_kind_str = rdi_string_from_type_kind(kind); + + str8_list_pushf(arena, out, "%.*skind=%.*s\n", + indent_level, rdi_stringize_spaces, str8_varg(type_kind_str)); + + switch (type->kind){ + case RDI_TypeKind_Modifier: + { + str8_list_pushf(arena, out, "%.*sflags=", indent_level, rdi_stringize_spaces); + rdi_stringize_type_modifier_flags(arena, out, type->flags); + str8_list_push(arena, out, str8_lit("\n")); + }break; + + default: + { + if (type->flags != 0){ + str8_list_pushf(arena, out, "%.*sflags=%x (missing stringizer path)", + indent_level, rdi_stringize_spaces, type->flags); + } + }break; + } + + str8_list_pushf(arena, out, "%.*sbyte_size=%u\n", + indent_level, rdi_stringize_spaces, type->byte_size); + + if (RDI_TypeKind_FirstBuiltIn <= kind && + kind <= RDI_TypeKind_LastBuiltIn){ + String8 name = {0}; + name.str = rdi_string_from_idx(parsed, type->built_in.name_string_idx, &name.size); + str8_list_pushf(arena, out, "%.*sbuilt_in.name='%.*s'\n", + indent_level, rdi_stringize_spaces, str8_varg(name)); + } + + else if (RDI_TypeKind_FirstConstructed <= kind && + kind <= RDI_TypeKind_LastConstructed){ + str8_list_pushf(arena, out, "%.*sconstructed.direct_type=%u\n", + indent_level, rdi_stringize_spaces, type->constructed.direct_type_idx); + + if (type->kind == RDI_TypeKind_Array){ + str8_list_pushf(arena, out, "%.*sconstructed.array_count=%u\n", + indent_level, rdi_stringize_spaces, type->constructed.count); + } + + if (type->kind == RDI_TypeKind_Function || + type->kind == RDI_TypeKind_Method){ + U32 run_first = type->constructed.param_idx_run_first; + U32 run_count_raw = type->constructed.count; + + U32 run_count = 0; + U32 *run = rdi_idx_run_from_first_count(parsed, run_first, run_count_raw, &run_count); + + U32 this_type_idx = 0; + if (run_count > 0 && type->kind == RDI_TypeKind_Method){ + this_type_idx = run[0]; + run += 1; + run_count -= 1; + } + + if (this_type_idx != 0){ + str8_list_pushf(arena, out, "%.*sconstructed.this_type=%u\n", + indent_level, rdi_stringize_spaces, this_type_idx); + } + + str8_list_pushf(arena, out, "%.*sconstructed.params={", + indent_level, rdi_stringize_spaces); + + if (run_count > 0){ + U32 last = run_count - 1; + for (U32 j = 0; j < last; j += 1){ + str8_list_pushf(arena, out, " %u,", run[j]); + } + str8_list_pushf(arena, out, " %u ", run[last]); + } + + str8_list_push(arena, out, str8_lit("}\n")); } } - // will we try to parse an input file - B32 try_parse_input = (params->errors.node_count == 0); + else if (RDI_TypeKind_FirstUserDefined <= kind && + kind <= RDI_TypeKind_LastUserDefined){ + String8 name = {0}; + name.str = rdi_string_from_idx(parsed, type->user_defined.name_string_idx, &name.size); + str8_list_pushf(arena, out, "%.*suser_defined.name='%.*s'\n", + indent_level, rdi_stringize_spaces, str8_varg(name)); + str8_list_pushf(arena, out, "%.*suser_defined.direct_type=%u\n", + indent_level, rdi_stringize_spaces, + type->user_defined.direct_type_idx); + str8_list_pushf(arena, out, "%.*suser_defined.udt=%u\n", + indent_level, rdi_stringize_spaces, + type->user_defined.udt_idx); + } - RDI_ParseStatus parse_status = RDI_ParseStatus_Good; - RDI_Parsed raddbg__ = {0}; - RDI_Parsed *raddbg = 0; - if (try_parse_input){ - parse_status = rdi_parse(params->input_data.str, params->input_data.size, &raddbg__); - if (parse_status == RDI_ParseStatus_Good){ - raddbg = &raddbg__; + else if (kind == RDI_TypeKind_Bitfield){ + str8_list_pushf(arena, out, "%.*sbitfield.off=%u\n", + indent_level, rdi_stringize_spaces, type->bitfield.off); + str8_list_pushf(arena, out, "%.*sbitfield.size=%u\n", + indent_level, rdi_stringize_spaces, type->bitfield.size); + } +} + +internal void +rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *parsed, + RDI_UDTMemberBundle *member_bundle, RDI_UDT *udt, + U32 indent_level){ + str8_list_pushf(arena, out, "%.*sself_type=%u\n", + indent_level, rdi_stringize_spaces, udt->self_type_idx); + + str8_list_pushf(arena, out, "%.*sflags=", indent_level, rdi_stringize_spaces); + rdi_stringize_user_defined_type_flags(arena, out, udt->flags); + str8_list_push(arena, out, str8_lit("\n")); + + if (udt->file_idx != 0){ + str8_list_pushf(arena, out, "%.*sloc={file=%u; line=%u; col=%u}\n", + indent_level, rdi_stringize_spaces, + udt->file_idx, udt->line, udt->col); + } + + // enum members + if (udt->flags & RDI_UserDefinedTypeFlag_EnumMembers){ + U32 first_raw = udt->member_first; + U32 opl_raw = first_raw + udt->member_count; + U32 opl = ClampTop(opl_raw, member_bundle->enum_member_count); + U32 first = ClampTop(first_raw, opl); + + if (first < opl){ + str8_list_pushf(arena, out, "%.*smembers={\n", indent_level, rdi_stringize_spaces); + RDI_EnumMember *enum_member = member_bundle->enum_members + first; + for (U32 i = first; i < opl; i += 1, enum_member += 1){ + String8 name = {0}; + name.str = rdi_string_from_idx(parsed, enum_member->name_string_idx, &name.size); + str8_list_pushf(arena, out, "%.*s '%.*s' %llu\n", + indent_level, rdi_stringize_spaces, + str8_varg(name), enum_member->val); + } + str8_list_pushf(arena, out, "%.*s}\n", indent_level, rdi_stringize_spaces); } } - if (raddbg == 0){ - // TODO(allen): improve this by looking at parse status. - fprintf(stderr, "error(parsing): error trying to parse the input file\n"); + // field members + else{ + U32 first_raw = udt->member_first; + U32 opl_raw = first_raw + udt->member_count; + U32 opl = ClampTop(opl_raw, member_bundle->member_count); + U32 first = ClampTop(first_raw, opl); + + if (first < opl){ + str8_list_pushf(arena, out, "%.*smembers={\n", indent_level, rdi_stringize_spaces); + RDI_Member *member = member_bundle->members + first; + for (U32 i = first; i < opl; i += 1, member += 1){ + str8_list_pushf(arena, out, "%.*s {\n", indent_level, rdi_stringize_spaces); + + String8 kind_str = rdi_string_from_member_kind(member->kind); + str8_list_pushf(arena, out, "%.*s kind=%.*s\n", + indent_level, rdi_stringize_spaces, str8_varg(kind_str)); + + if (member->name_string_idx != 0){ + String8 name = {0}; + name.str = rdi_string_from_idx(parsed, member->name_string_idx, &name.size); + str8_list_pushf(arena, out, "%.*s name='%.*s'\n", + indent_level, rdi_stringize_spaces, str8_varg(name)); + } + + str8_list_pushf(arena, out, "%.*s type=%u\n", + indent_level, rdi_stringize_spaces, member->type_idx); + str8_list_pushf(arena, out, "%.*s off=%u\n", + indent_level, rdi_stringize_spaces, member->off); + + str8_list_pushf(arena, out, "%.*s }\n", indent_level, rdi_stringize_spaces); + } + str8_list_pushf(arena, out, "%.*s}\n", indent_level, rdi_stringize_spaces); + } } +} + +internal void +rdi_stringize_global_variable(Arena *arena, String8List *out, RDI_Parsed *parsed, + RDI_GlobalVariable *global_variable, U32 indent_level){ + String8 name = {0}; + name.str = rdi_string_from_idx(parsed, global_variable->name_string_idx, &name.size); + str8_list_pushf(arena, out, "%.*sname='%.*s'\n", + indent_level, rdi_stringize_spaces, str8_varg(name)); - // dump + str8_list_pushf(arena, out, "%.*slink_flags=", indent_level, rdi_stringize_spaces); + rdi_stringize_link_flags(arena, out, global_variable->link_flags); + str8_list_push(arena, out, str8_lit("\n")); + + str8_list_pushf(arena, out, "%.*svoff=0x%08llx\n", + indent_level, rdi_stringize_spaces, global_variable->voff); + + str8_list_pushf(arena, out, "%.*stype_idx=%u\n", + indent_level, rdi_stringize_spaces, global_variable->type_idx); + + str8_list_pushf(arena, out, "%.*scontainer_idx=%u\n", + indent_level, rdi_stringize_spaces, global_variable->container_idx); +} + +internal void +rdi_stringize_thread_variable(Arena *arena, String8List *out, RDI_Parsed *parsed, + RDI_ThreadVariable *thread_var, + U32 indent_level){ + String8 name = {0}; + name.str = rdi_string_from_idx(parsed, thread_var->name_string_idx, &name.size); + str8_list_pushf(arena, out, "%.*sname='%.*s'\n", + indent_level, rdi_stringize_spaces, str8_varg(name)); + + str8_list_pushf(arena, out, "%.*slink_flags=", indent_level, rdi_stringize_spaces); + rdi_stringize_link_flags(arena, out, thread_var->link_flags); + str8_list_push(arena, out, str8_lit("\n")); + + str8_list_pushf(arena, out, "%.*stls_off=0x%08x\n", + indent_level, rdi_stringize_spaces, thread_var->tls_off); + + str8_list_pushf(arena, out, "%.*stype_idx=%u\n", + indent_level, rdi_stringize_spaces, thread_var->type_idx); + + str8_list_pushf(arena, out, "%.*scontainer_idx=%u\n", + indent_level, rdi_stringize_spaces, thread_var->container_idx); +} + +internal void +rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *parsed, + RDI_Procedure *proc, U32 indent_level){ + String8 name = {0}; + name.str = rdi_string_from_idx(parsed, proc->name_string_idx, &name.size); + str8_list_pushf(arena, out, "%.*sname='%.*s'\n", + indent_level, rdi_stringize_spaces, str8_varg(name)); + + String8 link_name = {0}; + link_name.str = rdi_string_from_idx(parsed, proc->link_name_string_idx, &link_name.size); + str8_list_pushf(arena, out, "%.*slink_name='%.*s'\n", + indent_level, rdi_stringize_spaces, str8_varg(link_name)); + + str8_list_pushf(arena, out, "%.*slink_flags=", indent_level, rdi_stringize_spaces); + rdi_stringize_link_flags(arena, out, proc->link_flags); + str8_list_push(arena, out, str8_lit("\n")); + + str8_list_pushf(arena, out, "%.*stype_idx=%u\n", + indent_level, rdi_stringize_spaces, proc->type_idx); + + str8_list_pushf(arena, out, "%.*sroot_scope_idx=%u\n", + indent_level, rdi_stringize_spaces, proc->root_scope_idx); + + str8_list_pushf(arena, out, "%.*scontainer_idx=%u\n", + indent_level, rdi_stringize_spaces, proc->container_idx); +} + +internal void +rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *parsed, + RDI_ScopeBundle *bundle, RDI_Scope *scope, U32 indent_level){ + + U32 this_idx = (U32)(scope - bundle->scopes); + + str8_list_pushf(arena, out, "%.*s[%u]\n", + indent_level, rdi_stringize_spaces, this_idx); + + str8_list_pushf(arena, out, "%.*s proc_idx=%u\n", + indent_level, rdi_stringize_spaces, scope->proc_idx); + + // voff ranges { - String8List dump = {0}; - - // DATA SECTIONS - if (raddbg->dsecs != 0 && params->dump_data_sections){ - str8_list_pushf(arena, &dump, "# DATA SECTIONS:\n"); - rdi_stringize_data_sections(arena, &dump, raddbg, 1); - str8_list_push(arena, &dump, str8_lit("\n")); + U32 voff_range_first_raw = scope->voff_range_first; + U32 voff_range_opl_raw = scope->voff_range_opl; + U32 voff_range_opl_clamped = ClampTop(voff_range_opl_raw, bundle->scope_voff_count); + U32 voff_range_first = ClampTop(voff_range_first_raw, voff_range_opl_clamped); + U32 voff_range_opl = voff_range_opl_clamped; + if ((voff_range_opl - voff_range_first) % 2 == 1){ + voff_range_opl -= 1; } - // TOP LEVEL INFO - if (raddbg->top_level_info != 0 && params->dump_top_level_info){ - str8_list_pushf(arena, &dump, "# TOP LEVEL INFO:\n"); - rdi_stringize_top_level_info(arena, &dump, raddbg, raddbg->top_level_info, 1); - str8_list_push(arena, &dump, str8_lit("\n")); - } + U64 *voff_ptr = bundle->scope_voffs + voff_range_first; - // BINARY SECTIONS - if (raddbg->binary_sections != 0 && params->dump_binary_sections){ - str8_list_pushf(arena, &dump, "# BINARY SECTIONS:\n"); - RDI_BinarySection *ptr = raddbg->binary_sections; - for (U32 i = 0; i < raddbg->binary_sections_count; i += 1, ptr += 1){ - str8_list_pushf(arena, &dump, " section[%u]:\n", i); - rdi_stringize_binary_section(arena, &dump, raddbg, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); + if (voff_range_opl - voff_range_first > 2){ + str8_list_pushf(arena, out, "%.*s voff_ranges={\n", + indent_level, rdi_stringize_spaces); + for (U32 i = voff_range_first; i < voff_range_opl; i += 2, voff_ptr += 2){ + str8_list_pushf(arena, out, "%.*s [0x%08llx, 0x%08llx)\n", + indent_level, rdi_stringize_spaces, + voff_ptr[0], voff_ptr[1]); } - str8_list_push(arena, &dump, str8_lit("\n")); + str8_list_pushf(arena, out, "%.*s }\n", + indent_level, rdi_stringize_spaces); } - - // FILE PATHS - if (raddbg->file_paths != 0 && params->dump_file_paths){ - RDI_FilePathBundle file_path_bundle = {0}; - { - file_path_bundle.file_paths = raddbg->file_paths; - file_path_bundle.file_path_count = raddbg->file_paths_count; - } - - str8_list_pushf(arena, &dump, "# FILE PATHS\n"); - RDI_FilePathNode *ptr = raddbg->file_paths; - for (U32 i = 0; i < raddbg->file_paths_count; i += 1, ptr += 1){ - if (ptr->parent_path_node == 0){ - rdi_stringize_file_path(arena, &dump, raddbg, &file_path_bundle, ptr, 1); - } - } - str8_list_push(arena, &dump, str8_lit("\n")); + else if (voff_range_opl - voff_range_first == 2){ + str8_list_pushf(arena, out, "%.*s voff_range=[0x%08llx, 0x%08llx)\n", + indent_level, rdi_stringize_spaces, + voff_ptr[0], voff_ptr[1]); } + } + + // locals + { + U32 local_first = scope->local_first; + U32 local_opl_raw = local_first + scope->local_count; + U32 local_opl = ClampTop(local_opl_raw, bundle->local_count); - // SOURCE FILES - if (raddbg->source_files != 0 && params->dump_source_files){ - str8_list_pushf(arena, &dump, "# SOURCE FILES\n"); - RDI_SourceFile *ptr = raddbg->source_files; - for (U32 i = 0; i < raddbg->source_files_count; i += 1, ptr += 1){ - str8_list_pushf(arena, &dump, " source_file[%u]:\n", i); - rdi_stringize_source_file(arena, &dump, raddbg, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); - } - str8_list_push(arena, &dump, str8_lit("\n")); - } - - // UNITS - if (raddbg->units != 0 && params->dump_units){ - str8_list_pushf(arena, &dump, "# UNITS\n"); - RDI_Unit *ptr = raddbg->units; - for (U32 i = 0; i < raddbg->units_count; i += 1, ptr += 1){ - str8_list_pushf(arena, &dump, " unit[%u]:\n", i); - rdi_stringize_unit(arena, &dump, raddbg, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); - } - str8_list_push(arena, &dump, str8_lit("\n")); - } - - // UNIT VMAP - if (raddbg->unit_vmap != 0 && params->dump_unit_vmap){ - str8_list_pushf(arena, &dump, "# UNIT VMAP\n"); - RDI_VMapEntry *ptr = raddbg->unit_vmap; - for (U32 i = 0; i < raddbg->unit_vmap_count; i += 1, ptr += 1){ - str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", ptr->voff, ptr->idx); - } - str8_list_push(arena, &dump, str8_lit("\n")); - } - - // TYPE NODES - if (raddbg->type_nodes != 0 && params->dump_type_nodes){ - str8_list_pushf(arena, &dump, "# TYPE NODES:\n"); - RDI_TypeNode *ptr = raddbg->type_nodes; - for (U32 i = 0; i < raddbg->type_nodes_count; i += 1, ptr += 1){ - str8_list_pushf(arena, &dump, " type[%u]:\n", i); - rdi_stringize_type_node(arena, &dump, raddbg, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); - } - str8_list_push(arena, &dump, str8_lit("\n")); - } - - // UDT DATA - if (raddbg->udts != 0 && params->dump_udt_data){ - RDI_UDTMemberBundle member_bundle = {0}; - { - member_bundle.members = raddbg->members; - member_bundle.enum_members = raddbg->enum_members; - member_bundle.member_count = raddbg->members_count; - member_bundle.enum_member_count = raddbg->enum_members_count; - } - - str8_list_pushf(arena, &dump, "# UDTS:\n"); - RDI_UDT *ptr = raddbg->udts; - for (U32 i = 0; i < raddbg->udts_count; i += 1, ptr += 1){ - str8_list_pushf(arena, &dump, " udt[%u]:\n", i); - rdi_stringize_udt(arena, &dump, raddbg, &member_bundle, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); - } - str8_list_push(arena, &dump, str8_lit("\n")); - } - - // GLOBAL VARIABLES - if (raddbg->global_variables != 0 && params->dump_global_variables){ - str8_list_pushf(arena, &dump, "# GLOBAL VARIABLES:\n"); - RDI_GlobalVariable *ptr = raddbg->global_variables; - for (U32 i = 0; i < raddbg->global_variables_count; i += 1, ptr += 1){ - str8_list_pushf(arena, &dump, " global_variable[%u]:\n", i); - rdi_stringize_global_variable(arena, &dump, raddbg, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); - } - str8_list_push(arena, &dump, str8_lit("\n")); - } - - // GLOBAL VMAP - if (raddbg->global_vmap != 0 && params->dump_global_vmap){ - str8_list_pushf(arena, &dump, "# GLOBAL VMAP:\n"); - RDI_VMapEntry *ptr = raddbg->global_vmap; - for (U32 i = 0; i < raddbg->global_vmap_count; i += 1, ptr += 1){ - str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", ptr->voff, ptr->idx); - } - str8_list_push(arena, &dump, str8_lit("\n")); - } - - // THREAD LOCAL VARIABLES - if (raddbg->thread_variables != 0 && params->dump_thread_variables){ - str8_list_pushf(arena, &dump, "# THREAD VARIABLES:\n"); - RDI_ThreadVariable *ptr = raddbg->thread_variables; - for (U32 i = 0; i < raddbg->thread_variables_count; i += 1, ptr += 1){ - str8_list_pushf(arena, &dump, " thread_variable[%u]:\n", i); - rdi_stringize_thread_variable(arena, &dump, raddbg, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); - } - str8_list_push(arena, &dump, str8_lit("\n")); - } - - // PROCEDURES - if (raddbg->procedures != 0 && params->dump_procedures){ - str8_list_pushf(arena, &dump, "# PROCEDURES:\n"); - RDI_Procedure *ptr = raddbg->procedures; - for (U32 i = 0; i < raddbg->procedures_count; i += 1, ptr += 1){ - str8_list_pushf(arena, &dump, " procedure[%u]:\n", i); - rdi_stringize_procedure(arena, &dump, raddbg, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); - } - str8_list_push(arena, &dump, str8_lit("\n")); - } - - // SCOPES - if (raddbg->scopes != 0 && params->dump_scopes){ - RDI_ScopeBundle scope_bundle = {0}; - { - scope_bundle.scopes = raddbg->scopes; - scope_bundle.scope_count = raddbg->scopes_count; - scope_bundle.scope_voffs = raddbg->scope_voffs; - scope_bundle.scope_voff_count = raddbg->scope_voffs_count; - scope_bundle.locals = raddbg->locals; - scope_bundle.local_count = raddbg->locals_count; - scope_bundle.location_blocks = raddbg->location_blocks; - scope_bundle.location_block_count = raddbg->location_blocks_count; - scope_bundle.location_data = raddbg->location_data; - scope_bundle.location_data_size = raddbg->location_data_size; - } - - str8_list_pushf(arena, &dump, "# SCOPES:\n"); - RDI_Scope *ptr = raddbg->scopes; - for (U32 i = 0; i < raddbg->scopes_count; i += 1, ptr += 1){ - if (ptr->parent_scope_idx == 0){ - rdi_stringize_scope(arena, &dump, raddbg, &scope_bundle, ptr, 1); - str8_list_push(arena, &dump, str8_lit("\n")); - } - } - str8_list_push(arena, &dump, str8_lit("\n")); - } - - // SCOPE VMAP - if (raddbg->scope_vmap != 0 && params->dump_scope_vmap){ - str8_list_pushf(arena, &dump, "# SCOPE VMAP:\n"); - RDI_VMapEntry *ptr = raddbg->scope_vmap; - for (U32 i = 0; i < raddbg->scope_vmap_count; i += 1, ptr += 1){ - str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", ptr->voff, ptr->idx); - } - str8_list_push(arena, &dump, str8_lit("\n")); - } - - // NAME MAPS - if (raddbg->name_maps != 0 && params->dump_name_map){ - str8_list_pushf(arena, &dump, "# NAME MAP:\n"); - RDI_NameMap *ptr = raddbg->name_maps; - for (U32 i = 0; i < raddbg->name_maps_count; i += 1, ptr += 1){ - str8_list_pushf(arena, &dump, " name_map[%u]:\n", i); + if (local_first < local_opl){ + RDI_Local *local_ptr = bundle->locals + local_first; + for (U32 i = local_first; i < local_opl; i += 1, local_ptr += 1){ + str8_list_pushf(arena, out, "%.*s local[%u]\n", + indent_level, rdi_stringize_spaces, i); - RDI_ParsedNameMap name_map = {0}; - rdi_name_map_parse(raddbg, ptr, &name_map); + String8 local_kind_str = rdi_string_from_local_kind(local_ptr->kind); + str8_list_pushf(arena, out, "%.*s kind=%.*s\n", + indent_level, rdi_stringize_spaces, str8_varg(local_kind_str)); - RDI_NameMapBucket *bucket = name_map.buckets; - for (U32 j = 0; j < name_map.bucket_count; j += 1, bucket += 1){ - if (bucket->node_count > 0){ - str8_list_pushf(arena, &dump, " bucket[%u]:\n", j); - RDI_NameMapNode *node = name_map.nodes + bucket->first_node; - RDI_NameMapNode *node_opl = node + bucket->node_count; - for (; node < node_opl; node += 1){ - String8 string = {0}; - string.str = rdi_string_from_idx(raddbg, node->string_idx, &string.size); - str8_list_pushf(arena, &dump, " match \"%.*s\": ", str8_varg(string)); - if (node->match_count == 1){ - str8_list_pushf(arena, &dump, "%u", node->match_idx_or_idx_run_first); - } - else{ - RDI_U32 idx_count = 0; - RDI_U32 *idx_run = - rdi_idx_run_from_first_count(raddbg, node->match_idx_or_idx_run_first, - node->match_count, &idx_count); - if (idx_count > 0){ - RDI_U32 last = idx_count - 1; - for (U32 k = 0; k < last; k += 1){ - str8_list_pushf(arena, &dump, "%u, ", idx_run[k]); + String8 name = {0}; + name.str = rdi_string_from_idx(parsed, local_ptr->name_string_idx, &name.size); + str8_list_pushf(arena, out, "%.*s name='%.*s'\n", + indent_level, rdi_stringize_spaces, str8_varg(name)); + + str8_list_pushf(arena, out, "%.*s type_idx=%u\n", + indent_level, rdi_stringize_spaces, local_ptr->type_idx); + + U32 location_first = local_ptr->location_first; + U32 location_opl_raw = local_ptr->location_opl; + U32 location_opl = ClampTop(location_opl_raw, bundle->location_block_count); + + if (location_first < location_opl){ + str8_list_pushf(arena, out, "%.*s locations:\n", indent_level, rdi_stringize_spaces); + RDI_LocationBlock *block_ptr = bundle->location_blocks + location_first; + for (U32 j = location_first; j < location_opl; j += 1, block_ptr += 1){ + if (block_ptr->scope_off_first == 0 && block_ptr->scope_off_opl == max_U32){ + str8_list_pushf(arena, out, "%.*s case *always*:\n", indent_level, rdi_stringize_spaces); + } + else{ + str8_list_pushf(arena, out, "%.*s case [0x%08x, 0x%08x):\n", + indent_level, rdi_stringize_spaces, + block_ptr->scope_off_first, block_ptr->scope_off_opl); + } + + if (block_ptr->location_data_off >= bundle->location_data_size){ + str8_list_pushf(arena, out, "%.*s \n", + indent_level, rdi_stringize_spaces); + } + else{ + str8_list_pushf(arena, out, "%.*s ", indent_level, rdi_stringize_spaces); + + U8 *loc_data_opl = bundle->location_data + bundle->location_data_size; + U8 *loc_base_ptr = bundle->location_data + block_ptr->location_data_off; + RDI_LocationKind kind = (RDI_LocationKind)*loc_base_ptr; + switch (kind){ + default: + { + str8_list_pushf(arena, out, "\n"); + }break; + + case RDI_LocationKind_AddrBytecodeStream: + { + str8_list_pushf(arena, out, "AddrBytecodeStream\n"); + str8_list_pushf(arena, out, "%.*s ", indent_level, rdi_stringize_spaces); + U8 *bytecode_ptr = loc_base_ptr + 1; + for (;bytecode_ptr < loc_data_opl && *bytecode_ptr != 0; bytecode_ptr += 1){ + str8_list_pushf(arena, out, "%02x ", *bytecode_ptr); } - str8_list_pushf(arena, &dump, "%u", idx_run[last]); - } + str8_list_pushf(arena, out, "\n"); + }break; + + case RDI_LocationKind_ValBytecodeStream: + { + str8_list_pushf(arena, out, "ValBytecodeStream\n"); + str8_list_pushf(arena, out, "%.*s ", indent_level, rdi_stringize_spaces); + U8 *bytecode_ptr = loc_base_ptr + 1; + for (;bytecode_ptr < loc_data_opl && *bytecode_ptr != 0; bytecode_ptr += 1){ + str8_list_pushf(arena, out, "%02x ", *bytecode_ptr); + } + str8_list_pushf(arena, out, "\n"); + }break; + + case RDI_LocationKind_AddrRegisterPlusU16: + { + if (loc_base_ptr + sizeof(RDI_LocationRegisterPlusU16) > loc_data_opl){ + str8_list_pushf(arena, out, "AddrRegisterPlusU16( )\n"); + } + else{ + RDI_LocationRegisterPlusU16 *loc = (RDI_LocationRegisterPlusU16*)loc_base_ptr; + str8_list_pushf(arena, out, "AddrRegisterPlusU16(reg: %u, off: %u)\n", + loc->register_code, loc->offset); + } + }break; + + case RDI_LocationKind_AddrAddrRegisterPlusU16: + { + if (loc_base_ptr + sizeof(RDI_LocationRegisterPlusU16) > loc_data_opl){ + str8_list_pushf(arena, out, "AddrAddrRegisterPlusU16( )\n"); + } + else{ + RDI_LocationRegisterPlusU16 *loc = (RDI_LocationRegisterPlusU16*)loc_base_ptr; + str8_list_pushf(arena, out, "AddrAddrRegisterPlusU16(reg: %u, off: %u)\n", + loc->register_code, loc->offset); + } + }break; + + case RDI_LocationKind_ValRegister: + { + if (loc_base_ptr + sizeof(RDI_LocationRegister) > loc_data_opl){ + str8_list_pushf(arena, out, "ValRegister( )\n"); + } + else{ + RDI_LocationRegister *loc = (RDI_LocationRegister*)loc_base_ptr; + str8_list_pushf(arena, out, "ValRegister(reg: %u)\n", loc->register_code); + } + }break; } - str8_list_pushf(arena, &dump, "\n"); } } } - - str8_list_push(arena, &dump, str8_lit("\n")); } - str8_list_push(arena, &dump, str8_lit("\n")); - } - - // print dump - for(String8Node *node = dump.first; node != 0; node = node->next) - { - fwrite(node->string.str, 1, node->string.size, stdout); } } - return(0); + // TODO(allen): static locals + + for (U32 child = scope->first_child_scope_idx; + child != 0;){ + // get scope for child + RDI_Scope *child_scope = 0; + if (child < bundle->scope_count){ + child_scope = bundle->scopes + child; + } + if (child_scope == 0){ + break; + } + + // stringize child + rdi_stringize_scope(arena, out, parsed, bundle, child_scope, indent_level + 1); + + // increment iterator + child = child_scope->next_sibling_scope_idx; + } + + str8_list_pushf(arena, out, "%.*s[/%u]\n", + indent_level, rdi_stringize_spaces, this_idx); } diff --git a/src/raddbgi_dump/raddbgi_dump.h b/src/raddbgi_dump/raddbgi_dump.h index c7b43265..add5f987 100644 --- a/src/raddbgi_dump/raddbgi_dump.h +++ b/src/raddbgi_dump/raddbgi_dump.h @@ -1,45 +1,75 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -#ifndef RDI_DUMP_H -#define RDI_DUMP_H +#ifndef RADDBGI_DUMP_H +#define RADDBGI_DUMP_H //////////////////////////////// -//~ Program Parameters Type +//~ rjf: RADDBG Stringize Helper Types -typedef struct RADDBGIDUMP_Params{ - String8 input_name; - String8 input_data; - - struct{ - B8 input; - } hide_errors; - - B8 dump__first; - B8 dump_data_sections; - B8 dump_top_level_info; - B8 dump_binary_sections; - B8 dump_file_paths; - B8 dump_source_files; - B8 dump_units; - B8 dump_unit_vmap; - B8 dump_type_nodes; - B8 dump_udt_data; - B8 dump_global_variables; - B8 dump_global_vmap; - B8 dump_thread_variables; - B8 dump_procedures; - B8 dump_scopes; - B8 dump_scope_vmap; - B8 dump_name_map; - B8 dump__last; - - String8List errors; -} RADDBGIDUMP_Params; +typedef struct RDI_FilePathBundle RDI_FilePathBundle; +struct RDI_FilePathBundle +{ + RDI_FilePathNode *file_paths; + U32 file_path_count; +}; + +typedef struct RDI_UDTMemberBundle RDI_UDTMemberBundle; +struct RDI_UDTMemberBundle +{ + RDI_Member *members; + RDI_EnumMember *enum_members; + U32 member_count; + U32 enum_member_count; +}; + +typedef struct RDI_ScopeBundle RDI_ScopeBundle; +struct RDI_ScopeBundle +{ + RDI_Scope *scopes; + U64 *scope_voffs; + RDI_Local *locals; + RDI_LocationBlock *location_blocks; + U8 *location_data; + U32 scope_count; + U32 scope_voff_count; + U32 local_count; + U32 location_block_count; + U32 location_data_size; +}; //////////////////////////////// -//~ Program Parameters Parser +//~ rjf: RADDBGI Enum -> String Functions -static RADDBGIDUMP_Params *raddbgidump_params_from_cmd_line(Arena *arena, CmdLine *cmdline); +internal String8 rdi_string_from_data_section_tag(RDI_DataSectionTag tag); +internal String8 rdi_string_from_arch(RDI_Arch arch); +internal String8 rdi_string_from_language(RDI_Language language); +internal String8 rdi_string_from_type_kind(RDI_TypeKind type_kind); +internal String8 rdi_string_from_member_kind(RDI_MemberKind member_kind); +internal String8 rdi_string_from_local_kind(RDI_LocalKind local_kind); -#endif //RDI_DUMP_H +//////////////////////////////// +//~ rjf: RADDBGI Flags -> String Functions + +internal void rdi_stringize_binary_section_flags(Arena *arena, String8List *out, RDI_BinarySectionFlags flags); +internal void rdi_stringize_type_modifier_flags(Arena *arena, String8List *out, RDI_TypeModifierFlags flags); +internal void rdi_stringize_user_defined_type_flags(Arena *arena, String8List *out, RDI_UserDefinedTypeFlags flags); +internal void rdi_stringize_link_flags(Arena *arena, String8List *out, RDI_LinkFlags flags); + +//////////////////////////////// +//~ rjf: RADDBG Compound Stringize Functions + +internal void rdi_stringize_data_sections(Arena *arena, String8List *out, RDI_Parsed *parsed, U32 indent_level); +internal void rdi_stringize_top_level_info(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_TopLevelInfo *tli, U32 indent_level); +internal void rdi_stringize_binary_section(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_BinarySection *bin_section, U32 indent_level); +internal void rdi_stringize_file_path(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_FilePathBundle *bundle, RDI_FilePathNode *file_path, U32 indent_level); +internal void rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_SourceFile *source_file, U32 indent_level); +internal void rdi_stringize_unit(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_Unit *unit, U32 indent_level); +internal void rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_TypeNode *type, U32 indent_level); +internal void rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_UDTMemberBundle *bundle, RDI_UDT *udt, U32 indent_level); +internal void rdi_stringize_global_variable(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_GlobalVariable *global_variable, U32 indent_level); +internal void rdi_stringize_thread_variable(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_ThreadVariable *thread_var, U32 indent_level); +internal void rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_Procedure *proc, U32 indent_level); +internal void rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_ScopeBundle *bundle, RDI_Scope *scope, U32 indent_level); + +#endif // RADDBGI_DUMP_H diff --git a/src/raddbgi_dump/raddbgi_dump_main.c b/src/raddbgi_dump/raddbgi_dump_main.c new file mode 100644 index 00000000..ed355078 --- /dev/null +++ b/src/raddbgi_dump/raddbgi_dump_main.c @@ -0,0 +1,413 @@ +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//////////////////////////////// +//~ rjf: Includes + +//- rjf: [lib] +#include "lib_raddbgi_format/raddbgi_format.h" +#include "lib_raddbgi_format/raddbgi_format_parse.h" +#include "lib_raddbgi_format/raddbgi_format.c" +#include "lib_raddbgi_format/raddbgi_format_parse.c" + +//- rjf: [h] +#include "base/base_inc.h" +#include "os/os_inc.h" +#include "raddbgi_dump.h" + +//- rjf: [c] +#include "base/base_inc.c" +#include "os/os_inc.c" +#include "raddbgi_dump.c" + +//////////////////////////////// +//~ rjf: Entry Point + +int +main(int argc, char **argv) +{ + ////////////////////////////// + //- rjf: set up + // + local_persist TCTX main_thread_tctx = {0}; + tctx_init_and_equip(&main_thread_tctx); + Arena *arena = arena_alloc(); + String8List args = os_string_list_from_argcv(arena, argc, argv); + CmdLine cmdline = cmd_line_from_string_list(arena, args); + String8List errors = {0}; + + ////////////////////////////// + //- rjf: extract command line parameters + // + typedef U32 DumpFlags; + enum + { + DumpFlag_DataSections = (1<<0), + DumpFlag_TopLevelInfo = (1<<1), + DumpFlag_BinarySections = (1<<2), + DumpFlag_FilePaths = (1<<3), + DumpFlag_SourceFiles = (1<<4), + DumpFlag_Units = (1<<5), + DumpFlag_UnitVMap = (1<<6), + DumpFlag_TypeNodes = (1<<7), + DumpFlag_UDTs = (1<<8), + DumpFlag_GlobalVariables = (1<<9), + DumpFlag_GlobalVMap = (1<<10), + DumpFlag_ThreadVariables = (1<<11), + DumpFlag_Procedures = (1<<12), + DumpFlag_Scopes = (1<<13), + DumpFlag_ScopeVMap = (1<<14), + DumpFlag_NameMaps = (1<<15), + }; + String8 input_name = {0}; + String8 input_data = {0}; + DumpFlags dump_flags = (U32)0xffffffff; + { + // rjf: extract input file path & load data + input_name = str8_list_first(&cmdline.inputs); + if(input_name.size > 0) { input_data = os_data_from_file_path(arena, input_name); } + else {str8_list_pushf(arena, &errors, "error (input): No input RADDBGI file specified.");} + if(input_name.size != 0 && input_data.size == 0) { str8_list_pushf(arena, &errors, "error (input): No input RADDBGI file successfully loaded; either the path or file contents are invalid."); } + + // rjf: extract dump options + { + String8List dump_options = cmd_line_strings(&cmdline, str8_lit("dump")); + if(dump_options.first != 0) + { + dump_flags = 0; + for(String8Node *n = dump_options.first; n != 0; n = n->next) + { + if(0){} + else if(str8_match(n->string, str8_lit("data_sections"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_DataSections; } + else if(str8_match(n->string, str8_lit("top_level_info"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_TopLevelInfo; } + else if(str8_match(n->string, str8_lit("binary_sections"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_BinarySections; } + else if(str8_match(n->string, str8_lit("file_paths"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_FilePaths; } + else if(str8_match(n->string, str8_lit("source_files"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_SourceFiles; } + else if(str8_match(n->string, str8_lit("units"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_Units; } + else if(str8_match(n->string, str8_lit("unit_vmap"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_UnitVMap; } + else if(str8_match(n->string, str8_lit("type_nodes"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_TypeNodes; } + else if(str8_match(n->string, str8_lit("udt_data"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_UDTs; } + else if(str8_match(n->string, str8_lit("global_variables"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_GlobalVariables; } + else if(str8_match(n->string, str8_lit("global_vmap"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_GlobalVMap; } + else if(str8_match(n->string, str8_lit("thread_variables"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_ThreadVariables; } + else if(str8_match(n->string, str8_lit("procedures"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_Procedures; } + else if(str8_match(n->string, str8_lit("scopes"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_Scopes; } + else if(str8_match(n->string, str8_lit("scope_vmap"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_ScopeVMap; } + else if(str8_match(n->string, str8_lit("name_maps"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_NameMaps; } + } + } + } + } + + ////////////////////////////// + //- rjf: parse raddbg from input data + // + RDI_ParseStatus parse_status = RDI_ParseStatus_Good; + RDI_Parsed raddbg_ = {0}; + RDI_Parsed *raddbg = &raddbg_; + { + parse_status = rdi_parse(input_data.str, input_data.size, &raddbg_); + if(parse_status == RDI_ParseStatus_Good) + { + str8_list_pushf(arena, &errors, "error (parse): RADDBGI file wasn't parsed successfully. (0x%x)", parse_status); + } + } + + ////////////////////////////// + //- rjf: output error strings to stderr + // + for(String8Node *n = errors.first; n != 0; n = n->next) + { + fwrite(n->string.str, 1, n->string.size, stderr); + fprintf(stderr, "\n"); + } + + ////////////////////////////// + //- rjf: build dump strings + // + String8List dump = {0}; + if(parse_status == RDI_ParseStatus_Good) + { + //- rjf: DATA SECTIONS + if(dump_flags & DumpFlag_DataSections) + { + str8_list_pushf(arena, &dump, "# DATA SECTIONS:\n"); + rdi_stringize_data_sections(arena, &dump, raddbg, 1); + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: TOP LEVEL INFO + if(dump_flags & DumpFlag_TopLevelInfo) + { + str8_list_pushf(arena, &dump, "# TOP LEVEL INFO:\n"); + rdi_stringize_top_level_info(arena, &dump, raddbg, raddbg->top_level_info, 1); + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: BINARY SECTIONS + if(dump_flags & DumpFlag_BinarySections) + { + str8_list_pushf(arena, &dump, "# BINARY SECTIONS:\n"); + RDI_BinarySection *ptr = raddbg->binary_sections; + for(U32 i = 0; i < raddbg->binary_sections_count; i += 1, ptr += 1) + { + str8_list_pushf(arena, &dump, " section[%u]:\n", i); + rdi_stringize_binary_section(arena, &dump, raddbg, ptr, 2); + str8_list_push(arena, &dump, str8_lit("\n")); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: FILE PATHS + if(dump_flags & DumpFlag_FilePaths) + { + RDI_FilePathBundle file_path_bundle = {0}; + { + file_path_bundle.file_paths = raddbg->file_paths; + file_path_bundle.file_path_count = raddbg->file_paths_count; + } + str8_list_pushf(arena, &dump, "# FILE PATHS\n"); + RDI_FilePathNode *ptr = raddbg->file_paths; + for(U32 i = 0; i < raddbg->file_paths_count; i += 1, ptr += 1) + { + if(ptr->parent_path_node == 0) + { + rdi_stringize_file_path(arena, &dump, raddbg, &file_path_bundle, ptr, 1); + } + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: SOURCE FILES + if(dump_flags & DumpFlag_SourceFiles) + { + str8_list_pushf(arena, &dump, "# SOURCE FILES\n"); + RDI_SourceFile *ptr = raddbg->source_files; + for(U32 i = 0; i < raddbg->source_files_count; i += 1, ptr += 1) + { + str8_list_pushf(arena, &dump, " source_file[%u]:\n", i); + rdi_stringize_source_file(arena, &dump, raddbg, ptr, 2); + str8_list_push(arena, &dump, str8_lit("\n")); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: UNITS + if(dump_flags & DumpFlag_Units) + { + str8_list_pushf(arena, &dump, "# UNITS\n"); + RDI_Unit *ptr = raddbg->units; + for (U32 i = 0; i < raddbg->units_count; i += 1, ptr += 1) + { + str8_list_pushf(arena, &dump, " unit[%u]:\n", i); + rdi_stringize_unit(arena, &dump, raddbg, ptr, 2); + str8_list_push(arena, &dump, str8_lit("\n")); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: UNIT VMAP + if(dump_flags & DumpFlag_UnitVMap) + { + str8_list_pushf(arena, &dump, "# UNIT VMAP\n"); + RDI_VMapEntry *ptr = raddbg->unit_vmap; + for(U32 i = 0; i < raddbg->unit_vmap_count; i += 1, ptr += 1) + { + str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", ptr->voff, ptr->idx); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: TYPE NODES + if(dump_flags & DumpFlag_TypeNodes) + { + str8_list_pushf(arena, &dump, "# TYPE NODES:\n"); + RDI_TypeNode *ptr = raddbg->type_nodes; + for(U32 i = 0; i < raddbg->type_nodes_count; i += 1, ptr += 1) + { + str8_list_pushf(arena, &dump, " type[%u]:\n", i); + rdi_stringize_type_node(arena, &dump, raddbg, ptr, 2); + str8_list_push(arena, &dump, str8_lit("\n")); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: UDT DATA + if(dump_flags & DumpFlag_UDTs) + { + RDI_UDTMemberBundle member_bundle = {0}; + { + member_bundle.members = raddbg->members; + member_bundle.enum_members = raddbg->enum_members; + member_bundle.member_count = raddbg->members_count; + member_bundle.enum_member_count = raddbg->enum_members_count; + } + str8_list_pushf(arena, &dump, "# UDTS:\n"); + RDI_UDT *ptr = raddbg->udts; + for(U32 i = 0; i < raddbg->udts_count; i += 1, ptr += 1) + { + str8_list_pushf(arena, &dump, " udt[%u]:\n", i); + rdi_stringize_udt(arena, &dump, raddbg, &member_bundle, ptr, 2); + str8_list_push(arena, &dump, str8_lit("\n")); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: GLOBAL VARIABLES + if(dump_flags & DumpFlag_GlobalVariables) + { + str8_list_pushf(arena, &dump, "# GLOBAL VARIABLES:\n"); + RDI_GlobalVariable *ptr = raddbg->global_variables; + for(U32 i = 0; i < raddbg->global_variables_count; i += 1, ptr += 1) + { + str8_list_pushf(arena, &dump, " global_variable[%u]:\n", i); + rdi_stringize_global_variable(arena, &dump, raddbg, ptr, 2); + str8_list_push(arena, &dump, str8_lit("\n")); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: GLOBAL VMAP + if(dump_flags & DumpFlag_GlobalVMap) + { + str8_list_pushf(arena, &dump, "# GLOBAL VMAP:\n"); + RDI_VMapEntry *ptr = raddbg->global_vmap; + for(U32 i = 0; i < raddbg->global_vmap_count; i += 1, ptr += 1) + { + str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", ptr->voff, ptr->idx); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: THREAD LOCAL VARIABLES + if(dump_flags & DumpFlag_ThreadVariables) + { + str8_list_pushf(arena, &dump, "# THREAD VARIABLES:\n"); + RDI_ThreadVariable *ptr = raddbg->thread_variables; + for(U32 i = 0; i < raddbg->thread_variables_count; i += 1, ptr += 1) + { + str8_list_pushf(arena, &dump, " thread_variable[%u]:\n", i); + rdi_stringize_thread_variable(arena, &dump, raddbg, ptr, 2); + str8_list_push(arena, &dump, str8_lit("\n")); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: PROCEDURES + if(dump_flags & DumpFlag_Procedures) + { + str8_list_pushf(arena, &dump, "# PROCEDURES:\n"); + RDI_Procedure *ptr = raddbg->procedures; + for(U32 i = 0; i < raddbg->procedures_count; i += 1, ptr += 1) + { + str8_list_pushf(arena, &dump, " procedure[%u]:\n", i); + rdi_stringize_procedure(arena, &dump, raddbg, ptr, 2); + str8_list_push(arena, &dump, str8_lit("\n")); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: SCOPES + if(dump_flags & DumpFlag_Scopes) + { + RDI_ScopeBundle scope_bundle = {0}; + { + scope_bundle.scopes = raddbg->scopes; + scope_bundle.scope_count = raddbg->scopes_count; + scope_bundle.scope_voffs = raddbg->scope_voffs; + scope_bundle.scope_voff_count = raddbg->scope_voffs_count; + scope_bundle.locals = raddbg->locals; + scope_bundle.local_count = raddbg->locals_count; + scope_bundle.location_blocks = raddbg->location_blocks; + scope_bundle.location_block_count = raddbg->location_blocks_count; + scope_bundle.location_data = raddbg->location_data; + scope_bundle.location_data_size = raddbg->location_data_size; + } + str8_list_pushf(arena, &dump, "# SCOPES:\n"); + RDI_Scope *ptr = raddbg->scopes; + for(U32 i = 0; i < raddbg->scopes_count; i += 1, ptr += 1) + { + if(ptr->parent_scope_idx == 0) + { + rdi_stringize_scope(arena, &dump, raddbg, &scope_bundle, ptr, 1); + str8_list_push(arena, &dump, str8_lit("\n")); + } + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: SCOPE VMAP + if(dump_flags & DumpFlag_ScopeVMap) + { + str8_list_pushf(arena, &dump, "# SCOPE VMAP:\n"); + RDI_VMapEntry *ptr = raddbg->scope_vmap; + for(U32 i = 0; i < raddbg->scope_vmap_count; i += 1, ptr += 1) + { + str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", ptr->voff, ptr->idx); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: NAME MAPS + if(dump_flags & DumpFlag_NameMaps) + { + str8_list_pushf(arena, &dump, "# NAME MAP:\n"); + RDI_NameMap *ptr = raddbg->name_maps; + for(U32 i = 0; i < raddbg->name_maps_count; i += 1, ptr += 1) + { + RDI_ParsedNameMap name_map = {0}; + rdi_name_map_parse(raddbg, ptr, &name_map); + str8_list_pushf(arena, &dump, " name_map[%u]:\n", i); + RDI_NameMapBucket *bucket = name_map.buckets; + for(U32 j = 0; j < name_map.bucket_count; j += 1, bucket += 1) + { + if(bucket->node_count > 0) + { + str8_list_pushf(arena, &dump, " bucket[%u]:\n", j); + RDI_NameMapNode *node = name_map.nodes + bucket->first_node; + RDI_NameMapNode *node_opl = node + bucket->node_count; + for(;node < node_opl; node += 1) + { + String8 string = {0}; + string.str = rdi_string_from_idx(raddbg, node->string_idx, &string.size); + str8_list_pushf(arena, &dump, " match \"%.*s\": ", str8_varg(string)); + if(node->match_count == 1) + { + str8_list_pushf(arena, &dump, "%u", node->match_idx_or_idx_run_first); + } + else + { + RDI_U32 idx_count = 0; + RDI_U32 *idx_run = + rdi_idx_run_from_first_count(raddbg, node->match_idx_or_idx_run_first, + node->match_count, &idx_count); + if(idx_count > 0) + { + RDI_U32 last = idx_count - 1; + for(U32 k = 0; k < last; k += 1) + { + str8_list_pushf(arena, &dump, "%u, ", idx_run[k]); + } + str8_list_pushf(arena, &dump, "%u", idx_run[last]); + } + } + str8_list_pushf(arena, &dump, "\n"); + } + } + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + } + + ////////////////////////////// + //- rjf: write dump to stdout + // + for(String8Node *n = dump.first; n != 0; n = n->next) + { + fwrite(n->string.str, 1, n->string.size, stdout); + } + + return 0; +} diff --git a/src/raddbgi_dump/raddbgi_stringize.c b/src/raddbgi_dump/raddbgi_stringize.c deleted file mode 100644 index b87898fa..00000000 --- a/src/raddbgi_dump/raddbgi_stringize.c +++ /dev/null @@ -1,776 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -//////////////////////////////// -//~ RADDBG Common Stringize Functions - -static String8 -rdi_string_from_data_section_tag(RDI_DataSectionTag tag){ - String8 result = {0}; - switch (tag){ -#define X(N,C) case C: result = str8_lit(#N); break; -#define Y(N) - RDI_DataSectionTagXList(X,Y) -#undef X -#undef Y - } - return(result); -} - -static String8 -rdi_string_from_arch(RDI_Arch arch){ - String8 result = {0}; - switch (arch){ - default: result = str8_lit(""); break; - case RDI_Arch_X86: result = str8_lit("x86"); break; - case RDI_Arch_X64: result = str8_lit("x64"); break; - } - return(result); -} - -static String8 -rdi_string_from_language(RDI_Language language){ - String8 result = {0}; - switch (language){ -#define X(name,code) case code: result = str8_lit(#name); break; - RDI_LanguageXList(X) -#undef X - } - return(result); -} - -static String8 -rdi_string_from_type_kind(RDI_TypeKind type_kind){ - String8 result = {0}; - switch (type_kind){ - default: result = str8_lit(""); break; -#define X(name,code) case code: result = str8_lit(#name); break; -#define XZ(name,code,size) X(name,code) -#define Y(a,n) - RDI_TypeKindXList(X,XZ,Y) -#undef X -#undef XZ -#undef Y - } - return(result); -} - -static String8 -rdi_string_from_member_kind(RDI_MemberKind member_kind){ - String8 result = {0}; - switch (member_kind){ - default: result = str8_lit(""); break; -#define X(N,C) case C: result = str8_lit(#N); break; - RDI_MemberKindXList(X) -#undef X - } - return(result); -} - -static String8 -rdi_string_from_local_kind(RDI_LocalKind local_kind){ - String8 result = {0}; - switch (local_kind){ - default: result = str8_lit(""); break; - case RDI_LocalKind_Parameter: result = str8_lit("Parameter"); break; - case RDI_LocalKind_Variable: result = str8_lit("Variable"); break; - } - return(result); -} - - -//////////////////////////////// -//~ RADDBG Flags Stringize Functions - -static void -rdi_stringize_binary_section_flags(Arena *arena, String8List *out, - RDI_BinarySectionFlags flags){ - if (flags == 0){ - str8_list_push(arena, out, str8_lit("0")); - } - if (flags & RDI_BinarySectionFlag_Read){ - str8_list_push(arena, out, str8_lit("Read ")); - } - if (flags & RDI_BinarySectionFlag_Write){ - str8_list_push(arena, out, str8_lit("Write ")); - } - if (flags & RDI_BinarySectionFlag_Execute){ - str8_list_push(arena, out, str8_lit("Execute ")); - } -} - -static void -rdi_stringize_type_modifier_flags(Arena *arena, String8List *out, - RDI_TypeModifierFlags flags){ - if (flags == 0){ - str8_list_push(arena, out, str8_lit("0")); - } - if (flags & RDI_TypeModifierFlag_Const){ - str8_list_push(arena, out, str8_lit("Const ")); - } - if (flags & RDI_TypeModifierFlag_Volatile){ - str8_list_push(arena, out, str8_lit("Volatile ")); - } -} - -static void -rdi_stringize_user_defined_type_flags(Arena *arena, String8List *out, - RDI_UserDefinedTypeFlags flags){ - if (flags == 0){ - str8_list_push(arena, out, str8_lit("0")); - } - if (flags & RDI_UserDefinedTypeFlag_EnumMembers){ - str8_list_push(arena, out, str8_lit("EnumMembers ")); - } -} - -static void -rdi_stringize_link_flags(Arena *arena, String8List *out, RDI_LinkFlags flags){ - if (flags == 0){ - str8_list_push(arena, out, str8_lit("0")); - } - if (flags & RDI_LinkFlag_External){ - str8_list_push(arena, out, str8_lit("External ")); - } - if (flags & RDI_LinkFlag_TypeScoped){ - str8_list_push(arena, out, str8_lit("TypeScoped ")); - } - if (flags & RDI_LinkFlag_ProcScoped){ - str8_list_push(arena, out, str8_lit("ProcScoped ")); - } -} - - -//////////////////////////////// -//~ RADDBG Compound Stringize Functions - -static char rdi_stringize_spaces[] = " "; - -static void -rdi_stringize_data_sections(Arena *arena, String8List *out, RDI_Parsed *parsed, - U32 indent_level){ - U64 data_section_count = parsed->dsec_count; - RDI_DataSection *ptr = parsed->dsecs; - for (U64 i = 0; i < data_section_count; i += 1, ptr += 1){ - String8 tag_str = rdi_string_from_data_section_tag(ptr->tag); - str8_list_pushf(arena, out, "%.*sdata_section[%5u] = {0x%08llx, %7u, %7u} %.*s\n", - indent_level, rdi_stringize_spaces, - i, ptr->off, ptr->encoded_size, ptr->unpacked_size, str8_varg(tag_str)); - } -} - -static void -rdi_stringize_top_level_info(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_TopLevelInfo *tli, U32 indent_level){ - String8 arch_str = rdi_string_from_arch(tli->architecture); - String8 exe_name = {0}; - exe_name.str = rdi_string_from_idx(parsed, tli->exe_name_string_idx, &exe_name.size); - - str8_list_pushf(arena, out, "%.*sarchitecture=%.*s\n", - indent_level, rdi_stringize_spaces, str8_varg(arch_str)); - str8_list_pushf(arena, out, "%.*sexe_name='%.*s'\n", - indent_level, rdi_stringize_spaces, str8_varg(exe_name)); - str8_list_pushf(arena, out, "%.*svoff_max=0x%08llx\n", - indent_level, rdi_stringize_spaces, tli->voff_max); -} - -static void -rdi_stringize_binary_section(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_BinarySection *bin_section, U32 indent_level){ - String8 name = {0}; - name.str = rdi_string_from_idx(parsed, bin_section->name_string_idx, &name.size); - str8_list_pushf(arena, out, "%.*sname='%.*s'\n", - indent_level, rdi_stringize_spaces, str8_varg(name)); - - str8_list_pushf(arena, out, "%.*sflags=", indent_level, rdi_stringize_spaces); - rdi_stringize_binary_section_flags(arena, out, bin_section->flags); - str8_list_pushf(arena, out, "\n"); - - str8_list_pushf(arena, out, "%.*svoff_first=0x%08x\n", - indent_level, rdi_stringize_spaces, bin_section->voff_first); - str8_list_pushf(arena, out, "%.*svoff_opl =0x%08x\n", - indent_level, rdi_stringize_spaces, bin_section->voff_opl); - str8_list_pushf(arena, out, "%.*sfoff_first=0x%08x\n", - indent_level, rdi_stringize_spaces, bin_section->foff_first); - str8_list_pushf(arena, out, "%.*sfoff_opl =0x%08x\n", - indent_level, rdi_stringize_spaces, bin_section->foff_opl); -} - -static void -rdi_stringize_file_path(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_FilePathBundle *bundle, RDI_FilePathNode *file_path, - U32 indent_level){ - String8 name = {0}; - name.str = rdi_string_from_idx(parsed, file_path->name_string_idx, &name.size); - - U32 this_idx = (U32)(file_path - bundle->file_paths); - - if (file_path->source_file_idx == 0){ - str8_list_pushf(arena, out, "%.*s[%u] '%.*s'\n", - indent_level, rdi_stringize_spaces, - this_idx, str8_varg(name)); - } - else{ - str8_list_pushf(arena, out, "%.*s[%u] '%.*s'; source_file=%u\n", - indent_level, rdi_stringize_spaces, - this_idx, str8_varg(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 < bundle->file_path_count){ - child_node = bundle->file_paths + child; - } - if (child_node == 0){ - break; - } - - // stringize child - rdi_stringize_file_path(arena, out, parsed, bundle, child_node, indent_level + 1); - - // increment iterator - child = child_node->next_sibling; - } -} - -static void -rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_SourceFile *source_file, U32 indent_level){ - // extract line map data - RDI_ParsedLineMap line_map = {0}; - rdi_line_map_from_source_file(parsed, source_file, &line_map); - - // stringize line map data - str8_list_pushf(arena, out, "%.*slines:\n", indent_level, rdi_stringize_spaces); - - for (U32 i = 0; i < line_map.count; i += 1){ - U32 line_num = line_map.nums[i]; - - U32 digit_count = 1; - if (line_num > 0){ - U32 x = line_num; - for (;;){ - x /= 10; - if (x == 0){ - break; - } - digit_count += 1; - } - } - - str8_list_pushf(arena, out, "%.*s %u: ", - indent_level, rdi_stringize_spaces, line_num); - - U32 first = line_map.ranges[i]; - U32 opl_raw = line_map.ranges[i + 1]; - U32 opl = ClampTop(opl_raw, line_map.voff_count); - for (U32 j = first; j < opl; j += 1){ - if (j == first){ - str8_list_pushf(arena, out, "0x%08x\n", line_map.voffs[j]); - } - else{ - str8_list_pushf(arena, out, "%.*s0x%08x\n", - indent_level + digit_count + 3, rdi_stringize_spaces, - line_map.voffs[j]); - } - } - } -} - -static void -rdi_stringize_unit(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_Unit *unit, U32 indent_level){ - String8 unit_name = {0}; - unit_name.str = rdi_string_from_idx(parsed, unit->unit_name_string_idx, &unit_name.size); - String8 compiler_name = {0}; - compiler_name.str = rdi_string_from_idx(parsed, unit->compiler_name_string_idx, - &compiler_name.size); - - str8_list_pushf(arena, out, "%.*sunit_name='%.*s'\n", - indent_level, rdi_stringize_spaces, str8_varg(unit_name)); - str8_list_pushf(arena, out, "%.*scompiler_name='%.*s'\n", - indent_level, rdi_stringize_spaces, str8_varg(compiler_name)); - - str8_list_pushf(arena, out, "%.*ssource_file_path=%u\n", - indent_level, rdi_stringize_spaces, unit->source_file_path_node); - str8_list_pushf(arena, out, "%.*sobject_file_path=%u\n", - indent_level, rdi_stringize_spaces, unit->object_file_path_node); - str8_list_pushf(arena, out, "%.*sarchive_file_path=%u\n", - indent_level, rdi_stringize_spaces, unit->archive_file_path_node); - str8_list_pushf(arena, out, "%.*sbuild_path=%u\n", - indent_level, rdi_stringize_spaces, unit->build_path_node); - - String8 language_str = rdi_string_from_language(unit->language); - str8_list_pushf(arena, out, "%.*slanguage=%.*s\n", - indent_level, rdi_stringize_spaces, str8_varg(language_str)); - - // extract line info data - RDI_ParsedLineInfo line_info = {0}; - rdi_line_info_from_unit(parsed, unit, &line_info); - - - // stringize line info - str8_list_pushf(arena, out, "%.*slines:\n", indent_level, rdi_stringize_spaces); - - for (U32 i = 0; i < line_info.count; i += 1){ - U64 first = line_info.voffs[i]; - U64 opl = line_info.voffs[i + 1]; - RDI_Line *line = line_info.lines + i; - RDI_Column *col = 0; - if (i < line_info.col_count){ - col = line_info.cols + i; - } - - if (col == 0){ - str8_list_pushf(arena, out, "%.*s [0x%08llx,0x%08llx) file=%u; line=%u\n", - indent_level, rdi_stringize_spaces, - first, opl, line->file_idx, line->line_num); - } - else{ - str8_list_pushf(arena, out, "%.*s [0x%08llx,0x%08llx) file=%u; line=%u; columns=[%u,%u)\n", - indent_level, rdi_stringize_spaces, - first, opl, line->file_idx, line->line_num, - col->col_first, col->col_opl); - } - } -} - -static void -rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_TypeNode *type, U32 indent_level){ - RDI_TypeKind kind = type->kind; - String8 type_kind_str = rdi_string_from_type_kind(kind); - - str8_list_pushf(arena, out, "%.*skind=%.*s\n", - indent_level, rdi_stringize_spaces, str8_varg(type_kind_str)); - - switch (type->kind){ - case RDI_TypeKind_Modifier: - { - str8_list_pushf(arena, out, "%.*sflags=", indent_level, rdi_stringize_spaces); - rdi_stringize_type_modifier_flags(arena, out, type->flags); - str8_list_push(arena, out, str8_lit("\n")); - }break; - - default: - { - if (type->flags != 0){ - str8_list_pushf(arena, out, "%.*sflags=%x (missing stringizer path)", - indent_level, rdi_stringize_spaces, type->flags); - } - }break; - } - - str8_list_pushf(arena, out, "%.*sbyte_size=%u\n", - indent_level, rdi_stringize_spaces, type->byte_size); - - if (RDI_TypeKind_FirstBuiltIn <= kind && - kind <= RDI_TypeKind_LastBuiltIn){ - String8 name = {0}; - name.str = rdi_string_from_idx(parsed, type->built_in.name_string_idx, &name.size); - str8_list_pushf(arena, out, "%.*sbuilt_in.name='%.*s'\n", - indent_level, rdi_stringize_spaces, str8_varg(name)); - } - - else if (RDI_TypeKind_FirstConstructed <= kind && - kind <= RDI_TypeKind_LastConstructed){ - str8_list_pushf(arena, out, "%.*sconstructed.direct_type=%u\n", - indent_level, rdi_stringize_spaces, type->constructed.direct_type_idx); - - if (type->kind == RDI_TypeKind_Array){ - str8_list_pushf(arena, out, "%.*sconstructed.array_count=%u\n", - indent_level, rdi_stringize_spaces, type->constructed.count); - } - - if (type->kind == RDI_TypeKind_Function || - type->kind == RDI_TypeKind_Method){ - U32 run_first = type->constructed.param_idx_run_first; - U32 run_count_raw = type->constructed.count; - - U32 run_count = 0; - U32 *run = rdi_idx_run_from_first_count(parsed, run_first, run_count_raw, &run_count); - - U32 this_type_idx = 0; - if (run_count > 0 && type->kind == RDI_TypeKind_Method){ - this_type_idx = run[0]; - run += 1; - run_count -= 1; - } - - if (this_type_idx != 0){ - str8_list_pushf(arena, out, "%.*sconstructed.this_type=%u\n", - indent_level, rdi_stringize_spaces, this_type_idx); - } - - str8_list_pushf(arena, out, "%.*sconstructed.params={", - indent_level, rdi_stringize_spaces); - - if (run_count > 0){ - U32 last = run_count - 1; - for (U32 j = 0; j < last; j += 1){ - str8_list_pushf(arena, out, " %u,", run[j]); - } - str8_list_pushf(arena, out, " %u ", run[last]); - } - - str8_list_push(arena, out, str8_lit("}\n")); - } - } - - else if (RDI_TypeKind_FirstUserDefined <= kind && - kind <= RDI_TypeKind_LastUserDefined){ - String8 name = {0}; - name.str = rdi_string_from_idx(parsed, type->user_defined.name_string_idx, &name.size); - str8_list_pushf(arena, out, "%.*suser_defined.name='%.*s'\n", - indent_level, rdi_stringize_spaces, str8_varg(name)); - str8_list_pushf(arena, out, "%.*suser_defined.direct_type=%u\n", - indent_level, rdi_stringize_spaces, - type->user_defined.direct_type_idx); - str8_list_pushf(arena, out, "%.*suser_defined.udt=%u\n", - indent_level, rdi_stringize_spaces, - type->user_defined.udt_idx); - } - - else if (kind == RDI_TypeKind_Bitfield){ - str8_list_pushf(arena, out, "%.*sbitfield.off=%u\n", - indent_level, rdi_stringize_spaces, type->bitfield.off); - str8_list_pushf(arena, out, "%.*sbitfield.size=%u\n", - indent_level, rdi_stringize_spaces, type->bitfield.size); - } -} - -static void -rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_UDTMemberBundle *member_bundle, RDI_UDT *udt, - U32 indent_level){ - str8_list_pushf(arena, out, "%.*sself_type=%u\n", - indent_level, rdi_stringize_spaces, udt->self_type_idx); - - str8_list_pushf(arena, out, "%.*sflags=", indent_level, rdi_stringize_spaces); - rdi_stringize_user_defined_type_flags(arena, out, udt->flags); - str8_list_push(arena, out, str8_lit("\n")); - - if (udt->file_idx != 0){ - str8_list_pushf(arena, out, "%.*sloc={file=%u; line=%u; col=%u}\n", - indent_level, rdi_stringize_spaces, - udt->file_idx, udt->line, udt->col); - } - - // enum members - if (udt->flags & RDI_UserDefinedTypeFlag_EnumMembers){ - U32 first_raw = udt->member_first; - U32 opl_raw = first_raw + udt->member_count; - U32 opl = ClampTop(opl_raw, member_bundle->enum_member_count); - U32 first = ClampTop(first_raw, opl); - - if (first < opl){ - str8_list_pushf(arena, out, "%.*smembers={\n", indent_level, rdi_stringize_spaces); - RDI_EnumMember *enum_member = member_bundle->enum_members + first; - for (U32 i = first; i < opl; i += 1, enum_member += 1){ - String8 name = {0}; - name.str = rdi_string_from_idx(parsed, enum_member->name_string_idx, &name.size); - str8_list_pushf(arena, out, "%.*s '%.*s' %llu\n", - indent_level, rdi_stringize_spaces, - str8_varg(name), enum_member->val); - } - str8_list_pushf(arena, out, "%.*s}\n", indent_level, rdi_stringize_spaces); - } - } - - // field members - else{ - U32 first_raw = udt->member_first; - U32 opl_raw = first_raw + udt->member_count; - U32 opl = ClampTop(opl_raw, member_bundle->member_count); - U32 first = ClampTop(first_raw, opl); - - if (first < opl){ - str8_list_pushf(arena, out, "%.*smembers={\n", indent_level, rdi_stringize_spaces); - RDI_Member *member = member_bundle->members + first; - for (U32 i = first; i < opl; i += 1, member += 1){ - str8_list_pushf(arena, out, "%.*s {\n", indent_level, rdi_stringize_spaces); - - String8 kind_str = rdi_string_from_member_kind(member->kind); - str8_list_pushf(arena, out, "%.*s kind=%.*s\n", - indent_level, rdi_stringize_spaces, str8_varg(kind_str)); - - if (member->name_string_idx != 0){ - String8 name = {0}; - name.str = rdi_string_from_idx(parsed, member->name_string_idx, &name.size); - str8_list_pushf(arena, out, "%.*s name='%.*s'\n", - indent_level, rdi_stringize_spaces, str8_varg(name)); - } - - str8_list_pushf(arena, out, "%.*s type=%u\n", - indent_level, rdi_stringize_spaces, member->type_idx); - str8_list_pushf(arena, out, "%.*s off=%u\n", - indent_level, rdi_stringize_spaces, member->off); - - str8_list_pushf(arena, out, "%.*s }\n", indent_level, rdi_stringize_spaces); - } - str8_list_pushf(arena, out, "%.*s}\n", indent_level, rdi_stringize_spaces); - } - } -} - -static void -rdi_stringize_global_variable(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_GlobalVariable *global_variable, U32 indent_level){ - String8 name = {0}; - name.str = rdi_string_from_idx(parsed, global_variable->name_string_idx, &name.size); - str8_list_pushf(arena, out, "%.*sname='%.*s'\n", - indent_level, rdi_stringize_spaces, str8_varg(name)); - - str8_list_pushf(arena, out, "%.*slink_flags=", indent_level, rdi_stringize_spaces); - rdi_stringize_link_flags(arena, out, global_variable->link_flags); - str8_list_push(arena, out, str8_lit("\n")); - - str8_list_pushf(arena, out, "%.*svoff=0x%08llx\n", - indent_level, rdi_stringize_spaces, global_variable->voff); - - str8_list_pushf(arena, out, "%.*stype_idx=%u\n", - indent_level, rdi_stringize_spaces, global_variable->type_idx); - - str8_list_pushf(arena, out, "%.*scontainer_idx=%u\n", - indent_level, rdi_stringize_spaces, global_variable->container_idx); -} - -static void -rdi_stringize_thread_variable(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_ThreadVariable *thread_var, - U32 indent_level){ - String8 name = {0}; - name.str = rdi_string_from_idx(parsed, thread_var->name_string_idx, &name.size); - str8_list_pushf(arena, out, "%.*sname='%.*s'\n", - indent_level, rdi_stringize_spaces, str8_varg(name)); - - str8_list_pushf(arena, out, "%.*slink_flags=", indent_level, rdi_stringize_spaces); - rdi_stringize_link_flags(arena, out, thread_var->link_flags); - str8_list_push(arena, out, str8_lit("\n")); - - str8_list_pushf(arena, out, "%.*stls_off=0x%08x\n", - indent_level, rdi_stringize_spaces, thread_var->tls_off); - - str8_list_pushf(arena, out, "%.*stype_idx=%u\n", - indent_level, rdi_stringize_spaces, thread_var->type_idx); - - str8_list_pushf(arena, out, "%.*scontainer_idx=%u\n", - indent_level, rdi_stringize_spaces, thread_var->container_idx); -} - -static void -rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_Procedure *proc, U32 indent_level){ - String8 name = {0}; - name.str = rdi_string_from_idx(parsed, proc->name_string_idx, &name.size); - str8_list_pushf(arena, out, "%.*sname='%.*s'\n", - indent_level, rdi_stringize_spaces, str8_varg(name)); - - String8 link_name = {0}; - link_name.str = rdi_string_from_idx(parsed, proc->link_name_string_idx, &link_name.size); - str8_list_pushf(arena, out, "%.*slink_name='%.*s'\n", - indent_level, rdi_stringize_spaces, str8_varg(link_name)); - - str8_list_pushf(arena, out, "%.*slink_flags=", indent_level, rdi_stringize_spaces); - rdi_stringize_link_flags(arena, out, proc->link_flags); - str8_list_push(arena, out, str8_lit("\n")); - - str8_list_pushf(arena, out, "%.*stype_idx=%u\n", - indent_level, rdi_stringize_spaces, proc->type_idx); - - str8_list_pushf(arena, out, "%.*sroot_scope_idx=%u\n", - indent_level, rdi_stringize_spaces, proc->root_scope_idx); - - str8_list_pushf(arena, out, "%.*scontainer_idx=%u\n", - indent_level, rdi_stringize_spaces, proc->container_idx); -} - -static void -rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_ScopeBundle *bundle, RDI_Scope *scope, U32 indent_level){ - - U32 this_idx = (U32)(scope - bundle->scopes); - - str8_list_pushf(arena, out, "%.*s[%u]\n", - indent_level, rdi_stringize_spaces, this_idx); - - str8_list_pushf(arena, out, "%.*s proc_idx=%u\n", - indent_level, rdi_stringize_spaces, scope->proc_idx); - - // voff ranges - { - U32 voff_range_first_raw = scope->voff_range_first; - U32 voff_range_opl_raw = scope->voff_range_opl; - U32 voff_range_opl_clamped = ClampTop(voff_range_opl_raw, bundle->scope_voff_count); - U32 voff_range_first = ClampTop(voff_range_first_raw, voff_range_opl_clamped); - U32 voff_range_opl = voff_range_opl_clamped; - if ((voff_range_opl - voff_range_first) % 2 == 1){ - voff_range_opl -= 1; - } - - U64 *voff_ptr = bundle->scope_voffs + voff_range_first; - - if (voff_range_opl - voff_range_first > 2){ - str8_list_pushf(arena, out, "%.*s voff_ranges={\n", - indent_level, rdi_stringize_spaces); - for (U32 i = voff_range_first; i < voff_range_opl; i += 2, voff_ptr += 2){ - str8_list_pushf(arena, out, "%.*s [0x%08llx, 0x%08llx)\n", - indent_level, rdi_stringize_spaces, - voff_ptr[0], voff_ptr[1]); - } - str8_list_pushf(arena, out, "%.*s }\n", - indent_level, rdi_stringize_spaces); - } - else if (voff_range_opl - voff_range_first == 2){ - str8_list_pushf(arena, out, "%.*s voff_range=[0x%08llx, 0x%08llx)\n", - indent_level, rdi_stringize_spaces, - voff_ptr[0], voff_ptr[1]); - } - } - - // locals - { - U32 local_first = scope->local_first; - U32 local_opl_raw = local_first + scope->local_count; - U32 local_opl = ClampTop(local_opl_raw, bundle->local_count); - - if (local_first < local_opl){ - RDI_Local *local_ptr = bundle->locals + local_first; - for (U32 i = local_first; i < local_opl; i += 1, local_ptr += 1){ - str8_list_pushf(arena, out, "%.*s local[%u]\n", - indent_level, rdi_stringize_spaces, i); - - String8 local_kind_str = rdi_string_from_local_kind(local_ptr->kind); - str8_list_pushf(arena, out, "%.*s kind=%.*s\n", - indent_level, rdi_stringize_spaces, str8_varg(local_kind_str)); - - String8 name = {0}; - name.str = rdi_string_from_idx(parsed, local_ptr->name_string_idx, &name.size); - str8_list_pushf(arena, out, "%.*s name='%.*s'\n", - indent_level, rdi_stringize_spaces, str8_varg(name)); - - str8_list_pushf(arena, out, "%.*s type_idx=%u\n", - indent_level, rdi_stringize_spaces, local_ptr->type_idx); - - U32 location_first = local_ptr->location_first; - U32 location_opl_raw = local_ptr->location_opl; - U32 location_opl = ClampTop(location_opl_raw, bundle->location_block_count); - - if (location_first < location_opl){ - str8_list_pushf(arena, out, "%.*s locations:\n", indent_level, rdi_stringize_spaces); - RDI_LocationBlock *block_ptr = bundle->location_blocks + location_first; - for (U32 j = location_first; j < location_opl; j += 1, block_ptr += 1){ - if (block_ptr->scope_off_first == 0 && block_ptr->scope_off_opl == max_U32){ - str8_list_pushf(arena, out, "%.*s case *always*:\n", indent_level, rdi_stringize_spaces); - } - else{ - str8_list_pushf(arena, out, "%.*s case [0x%08x, 0x%08x):\n", - indent_level, rdi_stringize_spaces, - block_ptr->scope_off_first, block_ptr->scope_off_opl); - } - - if (block_ptr->location_data_off >= bundle->location_data_size){ - str8_list_pushf(arena, out, "%.*s \n", - indent_level, rdi_stringize_spaces); - } - else{ - str8_list_pushf(arena, out, "%.*s ", indent_level, rdi_stringize_spaces); - - U8 *loc_data_opl = bundle->location_data + bundle->location_data_size; - U8 *loc_base_ptr = bundle->location_data + block_ptr->location_data_off; - RDI_LocationKind kind = (RDI_LocationKind)*loc_base_ptr; - switch (kind){ - default: - { - str8_list_pushf(arena, out, "\n"); - }break; - - case RDI_LocationKind_AddrBytecodeStream: - { - str8_list_pushf(arena, out, "AddrBytecodeStream\n"); - str8_list_pushf(arena, out, "%.*s ", indent_level, rdi_stringize_spaces); - U8 *bytecode_ptr = loc_base_ptr + 1; - for (;bytecode_ptr < loc_data_opl && *bytecode_ptr != 0; bytecode_ptr += 1){ - str8_list_pushf(arena, out, "%02x ", *bytecode_ptr); - } - str8_list_pushf(arena, out, "\n"); - }break; - - case RDI_LocationKind_ValBytecodeStream: - { - str8_list_pushf(arena, out, "ValBytecodeStream\n"); - str8_list_pushf(arena, out, "%.*s ", indent_level, rdi_stringize_spaces); - U8 *bytecode_ptr = loc_base_ptr + 1; - for (;bytecode_ptr < loc_data_opl && *bytecode_ptr != 0; bytecode_ptr += 1){ - str8_list_pushf(arena, out, "%02x ", *bytecode_ptr); - } - str8_list_pushf(arena, out, "\n"); - }break; - - case RDI_LocationKind_AddrRegisterPlusU16: - { - if (loc_base_ptr + sizeof(RDI_LocationRegisterPlusU16) > loc_data_opl){ - str8_list_pushf(arena, out, "AddrRegisterPlusU16( )\n"); - } - else{ - RDI_LocationRegisterPlusU16 *loc = (RDI_LocationRegisterPlusU16*)loc_base_ptr; - str8_list_pushf(arena, out, "AddrRegisterPlusU16(reg: %u, off: %u)\n", - loc->register_code, loc->offset); - } - }break; - - case RDI_LocationKind_AddrAddrRegisterPlusU16: - { - if (loc_base_ptr + sizeof(RDI_LocationRegisterPlusU16) > loc_data_opl){ - str8_list_pushf(arena, out, "AddrAddrRegisterPlusU16( )\n"); - } - else{ - RDI_LocationRegisterPlusU16 *loc = (RDI_LocationRegisterPlusU16*)loc_base_ptr; - str8_list_pushf(arena, out, "AddrAddrRegisterPlusU16(reg: %u, off: %u)\n", - loc->register_code, loc->offset); - } - }break; - - case RDI_LocationKind_ValRegister: - { - if (loc_base_ptr + sizeof(RDI_LocationRegister) > loc_data_opl){ - str8_list_pushf(arena, out, "ValRegister( )\n"); - } - else{ - RDI_LocationRegister *loc = (RDI_LocationRegister*)loc_base_ptr; - str8_list_pushf(arena, out, "ValRegister(reg: %u)\n", loc->register_code); - } - }break; - } - } - } - } - } - } - } - - // TODO(allen): static locals - - for (U32 child = scope->first_child_scope_idx; - child != 0;){ - // get scope for child - RDI_Scope *child_scope = 0; - if (child < bundle->scope_count){ - child_scope = bundle->scopes + child; - } - if (child_scope == 0){ - break; - } - - // stringize child - rdi_stringize_scope(arena, out, parsed, bundle, child_scope, indent_level + 1); - - // increment iterator - child = child_scope->next_sibling_scope_idx; - } - - str8_list_pushf(arena, out, "%.*s[/%u]\n", - indent_level, rdi_stringize_spaces, this_idx); -} diff --git a/src/raddbgi_dump/raddbgi_stringize.h b/src/raddbgi_dump/raddbgi_stringize.h deleted file mode 100644 index 51534416..00000000 --- a/src/raddbgi_dump/raddbgi_stringize.h +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2024 Epic Games Tools -// Licensed under the MIT license (https://opensource.org/license/mit/) - -#ifndef RADDBGI_STRINGIZE_H -#define RADDBGI_STRINGIZE_H - -//////////////////////////////// -//~ RADDBG Stringize Helper Types - -typedef struct RDI_FilePathBundle{ - RDI_FilePathNode *file_paths; - U32 file_path_count; -} RDI_FilePathBundle; - -typedef struct RDI_UDTMemberBundle{ - RDI_Member *members; - RDI_EnumMember *enum_members; - U32 member_count; - U32 enum_member_count; -} RDI_UDTMemberBundle; - -typedef struct RDI_ScopeBundle{ - RDI_Scope *scopes; - U64 *scope_voffs; - RDI_Local *locals; - RDI_LocationBlock *location_blocks; - U8 *location_data; - U32 scope_count; - U32 scope_voff_count; - U32 local_count; - U32 location_block_count; - U32 location_data_size; -} RDI_ScopeBundle; - -//////////////////////////////// -//~ RADDBG Common Stringize Functions - -static String8 rdi_string_from_data_section_tag(RDI_DataSectionTag tag); -static String8 rdi_string_from_arch(RDI_Arch arch); -static String8 rdi_string_from_language(RDI_Language language); -static String8 rdi_string_from_type_kind(RDI_TypeKind type_kind); -static String8 rdi_string_from_member_kind(RDI_MemberKind member_kind); -static String8 rdi_string_from_local_kind(RDI_LocalKind local_kind); - -//////////////////////////////// -//~ RADDBG Flags Stringize Functions - -static void rdi_stringize_binary_section_flags(Arena *arena, String8List *out, - RDI_BinarySectionFlags flags); - -static void rdi_stringize_type_modifier_flags(Arena *arena, String8List *out, - RDI_TypeModifierFlags flags); - -static void rdi_stringize_user_defined_type_flags(Arena *arena, String8List *out, - RDI_UserDefinedTypeFlags flags); - -static void rdi_stringize_link_flags(Arena *arena, String8List *out, - RDI_LinkFlags flags); - -//////////////////////////////// -//~ RADDBG Compound Stringize Functions - -static void -rdi_stringize_data_sections(Arena *arena, String8List *out, RDI_Parsed *parsed, - U32 indent_level); - -static void -rdi_stringize_top_level_info(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_TopLevelInfo *tli, U32 indent_level); - -static void -rdi_stringize_binary_section(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_BinarySection *bin_section, U32 indent_level); - -static void -rdi_stringize_file_path(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_FilePathBundle *bundle, RDI_FilePathNode *file_path, - U32 indent_level); - -static void -rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_SourceFile *source_file, U32 indent_level); - -static void -rdi_stringize_unit(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_Unit *unit, U32 indent_level); - -static void -rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_TypeNode *type, U32 indent_level); - -static void -rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_UDTMemberBundle *bundle, RDI_UDT *udt, - U32 indent_level); - -static void -rdi_stringize_global_variable(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_GlobalVariable *global_variable, U32 indent_level); - -static void -rdi_stringize_thread_variable(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_ThreadVariable *thread_var, - U32 indent_level); - -static void -rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_Procedure *proc, U32 indent_level); - -static void -rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_ScopeBundle *bundle, RDI_Scope *scope, U32 indent_level); - -#endif // RADDBGI_STRINGIZE_H