From 061abb4545b2b2a36abac333d0640f5f8560a5ee Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Sat, 1 Jun 2024 19:32:24 -0700 Subject: [PATCH 01/44] appease clang --- build.bat | 2 +- project.4coder | 2 +- src/df/core/df_core.h | 12 ++++++++---- .../dwrite/font_provider_dwrite.h | 18 ++++++++++-------- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/build.bat b/build.bat index 41f8ecb9..74e5ea3e 100644 --- a/build.bat +++ b/build.bat @@ -42,7 +42,7 @@ if "%asan%"=="1" set auto_compile_flags=%auto_compile_flags% -fsanitize=add :: --- Compile/Link Line Definitions ------------------------------------------ set cl_common= /I..\src\ /I..\local\ /nologo /FC /Z7 -set clang_common= -I..\src\ -I..\local\ -gcodeview -fdiagnostics-absolute-paths -Wall -Wno-unknown-warning-option -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf +set clang_common= -I..\src\ -I..\local\ -gcodeview -fdiagnostics-absolute-paths -Wall -Wno-unknown-warning-option -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf set cl_debug= call cl /Od /DBUILD_DEBUG=1 %cl_common% %auto_compile_flags% set cl_release= call cl /O2 /DBUILD_DEBUG=0 %cl_common% %auto_compile_flags% set clang_debug= call clang -g -O0 -DBUILD_DEBUG=1 %clang_common% %auto_compile_flags% diff --git a/project.4coder b/project.4coder index 9f070887..241a911b 100644 --- a/project.4coder +++ b/project.4coder @@ -47,7 +47,7 @@ commands = { .rjf_f1 = { - .win = "build raddbg telemetry", + .win = "build raddbg telemetry clang", .linux = "", .out = "*compilation*", .footer_panel = true, diff --git a/src/df/core/df_core.h b/src/df/core/df_core.h index 1a5e032d..a8a72850 100644 --- a/src/df/core/df_core.h +++ b/src/df/core/df_core.h @@ -265,10 +265,15 @@ struct DF_Eval //////////////////////////////// //~ rjf: View Rule Hook Types -#define DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_SIG(name) DF_Eval name(Arena *arena, DI_Scope *di_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_Eval eval, struct DF_CfgVal *val) +typedef struct DF_CfgNode DF_CfgNode; +typedef struct DF_CfgVal DF_CfgVal; +typedef struct DF_CfgTable DF_CfgTable; +typedef struct DF_EvalView DF_EvalView; +typedef struct DF_EvalVizBlockList DF_EvalVizBlockList; +#define DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_SIG(name) DF_Eval name(Arena *arena, DI_Scope *di_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_Eval eval, DF_CfgVal *val) #define DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME(name) df_core_view_rule_eval_resolution__##name #define DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_DEF(name) internal DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_SIG(DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME(name)) -#define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_SIG(name) void name(Arena *arena, DI_Scope *di_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, struct DF_EvalView *eval_view, DF_Eval eval, String8 string, struct DF_CfgTable *cfg_table, DF_ExpandKey parent_key, DF_ExpandKey key, S32 depth, struct DF_CfgNode *cfg, struct DF_EvalVizBlockList *out) +#define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_SIG(name) void name(Arena *arena, DI_Scope *di_scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, EVAL_String2ExprMap *macro_map, DF_EvalView *eval_view, DF_Eval eval, String8 string, DF_CfgTable *cfg_table, DF_ExpandKey parent_key, DF_ExpandKey key, S32 depth, DF_CfgNode *cfg, struct DF_EvalVizBlockList *out) #define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(name) df_core_view_rule_viz_block_prod__##name #define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(name) internal DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_SIG(DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(name)) typedef DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_SIG(DF_CoreViewRuleEvalResolutionHookFunctionType); @@ -1270,8 +1275,7 @@ read_only global DF_Entity df_g_nil_entity = 0, // rjf: name equipment - 0, - zero_struct, + {0}, 0, // rjf: timestamp diff --git a/src/font_provider/dwrite/font_provider_dwrite.h b/src/font_provider/dwrite/font_provider_dwrite.h index 973104fe..6a21ea13 100644 --- a/src/font_provider/dwrite/font_provider_dwrite.h +++ b/src/font_provider/dwrite/font_provider_dwrite.h @@ -192,16 +192,17 @@ static inline UINT32 IDWriteBitmapRenderTarget_Releas //- rjf: font file loader interface types +typedef struct FP_DWrite_FontFileLoader FP_DWrite_FontFileLoader; typedef struct FP_DWrite_FontFileLoaderVTable FP_DWrite_FontFileLoaderVTable; + struct FP_DWrite_FontFileLoaderVTable { HRESULT (*QueryInterface)(void *obj, REFIID riid, void *ptr_to_object); ULONG (*AddRef)(void *obj); ULONG (*Release)(void *obj); - HRESULT (*CreateStreamFromKey)(struct FP_DWrite_FontFileLoader *loader, void const *font_file_ref_key, UINT32 font_file_ref_key_size, IDWriteFontFileStream **stream_out); + HRESULT (*CreateStreamFromKey)(FP_DWrite_FontFileLoader *loader, void const *font_file_ref_key, UINT32 font_file_ref_key_size, IDWriteFontFileStream **stream_out); }; -typedef struct FP_DWrite_FontFileLoader FP_DWrite_FontFileLoader; struct FP_DWrite_FontFileLoader { FP_DWrite_FontFileLoaderVTable *lpVtbl; @@ -209,26 +210,27 @@ struct FP_DWrite_FontFileLoader //- rjf: font file stream interface types +typedef struct FP_DWrite_FontFileStream FP_DWrite_FontFileStream; typedef struct FP_DWrite_FontFileStreamVTable FP_DWrite_FontFileStreamVTable; +typedef struct FP_DWrite_FontFileStreamNode FP_DWrite_FontFileStreamNode; + struct FP_DWrite_FontFileStreamVTable { HRESULT (*QueryInterface)(void *obj, REFIID riid, void *ptr_to_object); ULONG (*AddRef)(void *obj); ULONG (*Release)(void *obj); - HRESULT (*ReadFileFragment)(struct FP_DWrite_FontFileStream *obj, void const **fragment_start, UINT64 file_offset, UINT64 fragment_size, void **fragment_context); - HRESULT (*ReleaseFileFragment)(struct FP_DWrite_FontFileStream *obj, void *fragment_context); - HRESULT (*GetFileSize)(struct FP_DWrite_FontFileStream *obj, UINT64 *size_out); - HRESULT (*GetLastWriteTime)(struct FP_DWrite_FontFileStream *obj, UINT64 *time_out); + HRESULT (*ReadFileFragment)(FP_DWrite_FontFileStream *obj, void const **fragment_start, UINT64 file_offset, UINT64 fragment_size, void **fragment_context); + HRESULT (*ReleaseFileFragment)(FP_DWrite_FontFileStream *obj, void *fragment_context); + HRESULT (*GetFileSize)(FP_DWrite_FontFileStream *obj, UINT64 *size_out); + HRESULT (*GetLastWriteTime)(FP_DWrite_FontFileStream *obj, UINT64 *time_out); }; -typedef struct FP_DWrite_FontFileStream FP_DWrite_FontFileStream; struct FP_DWrite_FontFileStream { FP_DWrite_FontFileStreamVTable *lpVtbl; String8 *data; }; -typedef struct FP_DWrite_FontFileStreamNode FP_DWrite_FontFileStreamNode; struct FP_DWrite_FontFileStreamNode { FP_DWrite_FontFileStreamNode *next; From 8438faca061677f2462caba296cf8ec38be14469 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Sat, 1 Jun 2024 19:37:05 -0700 Subject: [PATCH 02/44] fix project.4coder --- project.4coder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.4coder b/project.4coder index 241a911b..9f070887 100644 --- a/project.4coder +++ b/project.4coder @@ -47,7 +47,7 @@ commands = { .rjf_f1 = { - .win = "build raddbg telemetry clang", + .win = "build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, From fcb839b788dc6ca7a0eab9692d6c488b8df0bbd8 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Sun, 2 Jun 2024 21:22:01 -0700 Subject: [PATCH 03/44] introduce separate rdi table element types for isolated line tables & inline sites --- src/lib_rdi_format/rdi_format.h | 22 +++++++++++++++++++ src/rdi_format/rdi_format.mdesk | 38 ++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/lib_rdi_format/rdi_format.h b/src/lib_rdi_format/rdi_format.h index ddd1cf7e..ea5a20ce 100644 --- a/src/lib_rdi_format/rdi_format.h +++ b/src/lib_rdi_format/rdi_format.h @@ -797,6 +797,16 @@ RDI_U32 line_info_col_data_idx; RDI_U32 line_info_count; }; +typedef struct RDI_LineTable RDI_LineTable; +struct RDI_LineTable +{ +RDI_U32 voffs_base_idx; +RDI_U32 lines_base_idx; +RDI_U32 cols_base_idx; +RDI_U32 lines_count; +RDI_U32 cols_count; +}; + typedef struct RDI_Line RDI_Line; struct RDI_Line { @@ -934,6 +944,18 @@ RDI_U32 static_local_idx_run_first; RDI_U32 static_local_count; }; +typedef struct RDI_InlineSite RDI_InlineSite; +struct RDI_InlineSite +{ +RDI_U32 name_string_idx; +RDI_U32 call_src_file_idx; +RDI_U32 call_line_num; +RDI_U32 call_col_num; +RDI_U32 type_idx; +RDI_U32 owner_type_idx; +RDI_U32 line_table_idx; +}; + typedef struct RDI_Local RDI_Local; struct RDI_Local { diff --git a/src/rdi_format/rdi_format.mdesk b/src/rdi_format/rdi_format.mdesk index 89f284be..578b5a93 100644 --- a/src/rdi_format/rdi_format.mdesk +++ b/src/rdi_format/rdi_format.mdesk @@ -507,6 +507,16 @@ RDI_UnitMemberTable: //////////////////////////////// //~ rjf: Line Info Type Tables +@table(name type desc) +RDI_LineTableMemberTable: +{ + {voffs_base_idx RDI_U32 ""} // U64[lines_count+1] (sorted ranges) + {lines_base_idx RDI_U32 ""} // RDI_Line[lines_count] + {cols_base_idx RDI_U32 ""} // RDI_Column[cols_count] + {lines_count RDI_U32 ""} + {cols_count RDI_U32 ""} +} + @table(name type desc) RDI_LineMemberTable: { @@ -521,6 +531,11 @@ RDI_ColumnMemberTable: {col_opl RDI_U16 ""} } +@struct RDI_LineTable: +{ + @expand(RDI_LineTableMemberTable a) `$(a.type) $(a.name)` +} + @struct RDI_Line: { @expand(RDI_LineMemberTable a) `$(a.type) $(a.name)` @@ -808,9 +823,9 @@ RDI_LocalKindTable: @table(name value) RDI_LocationKindTable: { - {NULL 0x0} - {AddrBytecodeStream 0x1} - {ValBytecodeStream 0x2} + {NULL 0x0} + {AddrBytecodeStream 0x1} + {ValBytecodeStream 0x2} {AddrRegPlusU16 0x3} {AddrAddrRegPlusU16 0x4} {ValReg 0x5} @@ -862,6 +877,18 @@ RDI_ScopeMemberTable: {static_local_count RDI_U32 ""} } +@table(name type desc) +RDI_InlineSiteMemberTable: +{ + {name_string_idx RDI_U32 ""} + {call_src_file_idx RDI_U32 ""} + {call_line_num RDI_U32 ""} + {call_col_num RDI_U32 ""} + {type_idx RDI_U32 ""} + {owner_type_idx RDI_U32 ""} + {line_table_idx RDI_U32 ""} +} + @table(name type desc) RDI_LocalMemberTable: { @@ -953,6 +980,11 @@ RDI_LocationRegMemberTable: @expand(RDI_ScopeMemberTable a) `$(a.type) $(a.name)` } +@struct RDI_InlineSite: +{ + @expand(RDI_InlineSiteMemberTable a) `$(a.type) $(a.name)` +} + @struct RDI_Local: { @expand(RDI_LocalMemberTable a) `$(a.type) $(a.name)` From 44fbbc24ee16562f2b94ca604cf7aac301ca54f0 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 3 Jun 2024 15:32:14 -0700 Subject: [PATCH 04/44] rdi, rdi_make, rdi_from_pdb, rdi_dump, df, dasm, etc: extract line tables from per-unit data sections, have top-level line info tables with units referring to line tables, and line tables just referring to sub-ranges of top-level sections; fix off-by-one string index in rdi generation --- project.4coder | 2 +- src/dasm_cache/dasm_cache.c | 5 +- src/dbgi/dbgi.h | 4 + src/df/core/df_core.c | 23 +- src/lib_rdi_format/rdi_format.h | 256 ++++++++-- src/lib_rdi_format/rdi_format_parse.c | 469 +++++++++--------- src/lib_rdi_format/rdi_format_parse.h | 194 ++++---- src/lib_rdi_make/rdi_make.c | 316 ++++++++++-- src/lib_rdi_make/rdi_make.h | 94 +++- .../rdi_breakpad_from_pdb_main.c | 2 +- src/rdi_dump/rdi_dump.c | 236 ++++----- src/rdi_dump/rdi_dump.h | 1 + src/rdi_dump/rdi_dump_main.c | 40 +- src/rdi_format/rdi_format.mdesk | 228 +++++++-- src/rdi_from_pdb/rdi_from_pdb.c | 175 ++++--- src/rdi_from_pdb/rdi_from_pdb.h | 13 +- src/task_system/task_system.c | 2 +- 17 files changed, 1355 insertions(+), 705 deletions(-) diff --git a/project.4coder b/project.4coder index 9f070887..a9e4873a 100644 --- a/project.4coder +++ b/project.4coder @@ -56,7 +56,7 @@ commands = }, .rjf_f2 = { - .win = "build mule_peb_trample", + .win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main.rdi && rdi_dump mule_main.rdi > mule_main.dump && popd", .linux = "", .out = "*compilation*", .footer_panel = true, diff --git a/src/dasm_cache/dasm_cache.c b/src/dasm_cache/dasm_cache.c index ef3418f1..dc10bed7 100644 --- a/src/dasm_cache/dasm_cache.c +++ b/src/dasm_cache/dasm_cache.c @@ -457,8 +457,9 @@ dasm_parse_thread__entry_point(void *p) U64 voff = (params.vaddr+off) - params.base_vaddr; U32 unit_idx = rdi_vmap_idx_from_voff(rdi->unit_vmap, rdi->unit_vmap_count, voff); RDI_Unit *unit = rdi_element_from_idx(rdi, units, unit_idx); - RDI_ParsedLineInfo unit_line_info = {0}; - rdi_line_info_from_unit(rdi, unit, &unit_line_info); + RDI_LineTable *line_table = rdi_element_from_idx(rdi, line_tables, unit->line_table_idx); + RDI_ParsedLineTable unit_line_info = {0}; + rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff); if(line_info_idx < unit_line_info.count) { diff --git a/src/dbgi/dbgi.h b/src/dbgi/dbgi.h index ece98ae6..0198b1ee 100644 --- a/src/dbgi/dbgi.h +++ b/src/dbgi/dbgi.h @@ -209,6 +209,10 @@ global RDI_Parsed di_rdi_parsed_nil = &rdi_binary_section_nil, 1, &rdi_file_path_node_nil, 1, &rdi_source_file_nil, 1, + &rdi_line_table_nil, 1, + &rdi_voff_nil, 1, + &rdi_line_nil, 1, + &rdi_column_nil, 1, &rdi_unit_nil, 1, &rdi_vmap_entry_nil, 1, &rdi_type_node_nil, 1, diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index c627903c..ae40f5e3 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -3276,9 +3276,10 @@ df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entit { U64 base_voff = voffs[idx]; U64 unit_idx = rdi_vmap_idx_from_voff(rdi->unit_vmap, rdi->unit_vmap_count, base_voff); - RDI_Unit *unit = &rdi->units[unit_idx]; - RDI_ParsedLineInfo unit_line_info = {0}; - rdi_line_info_from_unit(rdi, unit, &unit_line_info); + RDI_Unit *unit = rdi_element_from_idx(rdi, units, unit_idx); + RDI_LineTable *line_table = rdi_element_from_idx(rdi, line_tables, unit->line_table_idx); + RDI_ParsedLineTable unit_line_info = {0}; + rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff); if(unit_line_info.voffs != 0) { @@ -3320,15 +3321,16 @@ df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff) if(rdi->unit_vmap != 0 && rdi->units != 0 && rdi->source_files != 0) { U64 unit_idx = rdi_vmap_idx_from_voff(rdi->unit_vmap, rdi->unit_vmap_count, voff); - RDI_Unit *unit = &rdi->units[unit_idx]; - RDI_ParsedLineInfo unit_line_info = {0}; - rdi_line_info_from_unit(rdi, unit, &unit_line_info); + RDI_Unit *unit = rdi_element_from_idx(rdi, units, unit_idx); + RDI_LineTable *line_table = rdi_element_from_idx(rdi, line_tables, unit->line_table_idx); + RDI_ParsedLineTable unit_line_info = {0}; + rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff); if(line_info_idx < unit_line_info.count) { RDI_Line *line = &unit_line_info.lines[line_info_idx]; RDI_Column *column = (line_info_idx < unit_line_info.col_count) ? &unit_line_info.cols[line_info_idx] : 0; - RDI_SourceFile *file = &rdi->source_files[line->file_idx]; + RDI_SourceFile *file = rdi_element_from_idx(rdi, source_files, line->file_idx); String8 file_normalized_full_path = {0}; file_normalized_full_path.str = rdi_string_from_idx(rdi, file->normal_full_path_string_idx, &file_normalized_full_path.size); MemoryCopyStruct(&result.dbgi_key, dbgi_key); @@ -3956,9 +3958,10 @@ df_eval_parse_ctx_from_src_loc(DI_Scope *scope, DF_Entity *file, TxtPt pt) { U64 base_voff = voffs[idx]; U64 unit_idx = rdi_vmap_idx_from_voff(rdi->unit_vmap, rdi->unit_vmap_count, base_voff); - RDI_Unit *unit = &rdi->units[unit_idx]; - RDI_ParsedLineInfo unit_line_info = {0}; - rdi_line_info_from_unit(rdi, unit, &unit_line_info); + RDI_Unit *unit = rdi_element_from_idx(rdi, units, unit_idx); + RDI_LineTable *line_table = rdi_element_from_idx(rdi, line_tables, unit->line_table_idx); + RDI_ParsedLineTable unit_line_info = {0}; + rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff); Rng1U64 range = r1u64(base_voff, unit_line_info.voffs[line_info_idx+1]); S64 actual_line = (S64)unit_line_info.lines[line_info_idx].line_num; diff --git a/src/lib_rdi_format/rdi_format.h b/src/lib_rdi_format/rdi_format.h index ea5a20ce..9ef88fcc 100644 --- a/src/lib_rdi_format/rdi_format.h +++ b/src/lib_rdi_format/rdi_format.h @@ -45,7 +45,7 @@ typedef int64_t RDI_S64; // \"raddbg\0\0\" #define RDI_MAGIC_CONSTANT 0x0000676264646172 -#define RDI_ENCODING_VERSION 1 +#define RDI_ENCODING_VERSION 2 //////////////////////////////////////////////////////////////// //~ Format Types & Functions @@ -61,33 +61,35 @@ RDI_DataSectionTag_IndexRuns = 0x0004, RDI_DataSectionTag_BinarySections = 0x0005, RDI_DataSectionTag_FilePathNodes = 0x0006, RDI_DataSectionTag_SourceFiles = 0x0007, -RDI_DataSectionTag_Units = 0x0008, -RDI_DataSectionTag_UnitVmap = 0x0009, -RDI_DataSectionTag_TypeNodes = 0x000A, -RDI_DataSectionTag_UDTs = 0x000B, -RDI_DataSectionTag_Members = 0x000C, -RDI_DataSectionTag_EnumMembers = 0x000D, -RDI_DataSectionTag_GlobalVariables = 0x000E, -RDI_DataSectionTag_GlobalVmap = 0x000F, -RDI_DataSectionTag_ThreadVariables = 0x0010, -RDI_DataSectionTag_Procedures = 0x0011, -RDI_DataSectionTag_Scopes = 0x0012, -RDI_DataSectionTag_ScopeVoffData = 0x0013, -RDI_DataSectionTag_ScopeVmap = 0x0014, -RDI_DataSectionTag_Locals = 0x0015, -RDI_DataSectionTag_LocationBlocks = 0x0016, -RDI_DataSectionTag_LocationData = 0x0017, -RDI_DataSectionTag_NameMaps = 0x0018, -RDI_DataSectionTag_PRIMARY_COUNT = 0x0019, +RDI_DataSectionTag_LineTables = 0x0008, +RDI_DataSectionTag_LineInfoVoffs = 0x0009, +RDI_DataSectionTag_LineInfoLines = 0x000A, +RDI_DataSectionTag_LineInfoColumns = 0x000B, +RDI_DataSectionTag_Units = 0x000C, +RDI_DataSectionTag_UnitVmap = 0x000D, +RDI_DataSectionTag_TypeNodes = 0x000E, +RDI_DataSectionTag_UDTs = 0x000F, +RDI_DataSectionTag_Members = 0x0010, +RDI_DataSectionTag_EnumMembers = 0x0011, +RDI_DataSectionTag_GlobalVariables = 0x0012, +RDI_DataSectionTag_GlobalVmap = 0x0013, +RDI_DataSectionTag_ThreadVariables = 0x0014, +RDI_DataSectionTag_Procedures = 0x0015, +RDI_DataSectionTag_Scopes = 0x0016, +RDI_DataSectionTag_ScopeVoffData = 0x0017, +RDI_DataSectionTag_ScopeVmap = 0x0018, +RDI_DataSectionTag_InlineSites = 0x0019, +RDI_DataSectionTag_Locals = 0x001A, +RDI_DataSectionTag_LocationBlocks = 0x001B, +RDI_DataSectionTag_LocationData = 0x001C, +RDI_DataSectionTag_NameMaps = 0x001D, +RDI_DataSectionTag_PRIMARY_COUNT = 0x001E, RDI_DataSectionTag_SECONDARY = 0x80000000, -RDI_DataSectionTag_LineInfoVoffs = RDI_DataSectionTag_SECONDARY|0x0001, -RDI_DataSectionTag_LineInfoData = RDI_DataSectionTag_SECONDARY|0x0002, -RDI_DataSectionTag_LineInfoColumns = RDI_DataSectionTag_SECONDARY|0x0003, -RDI_DataSectionTag_LineMapNumbers = RDI_DataSectionTag_SECONDARY|0x0004, -RDI_DataSectionTag_LineMapRanges = RDI_DataSectionTag_SECONDARY|0x0005, -RDI_DataSectionTag_LineMapVoffs = RDI_DataSectionTag_SECONDARY|0x0006, -RDI_DataSectionTag_NameMapBuckets = RDI_DataSectionTag_SECONDARY|0x0007, -RDI_DataSectionTag_NameMapNodes = RDI_DataSectionTag_SECONDARY|0x0008, +RDI_DataSectionTag_LineMapNumbers = RDI_DataSectionTag_SECONDARY|0x0001, +RDI_DataSectionTag_LineMapRanges = RDI_DataSectionTag_SECONDARY|0x0002, +RDI_DataSectionTag_LineMapVoffs = RDI_DataSectionTag_SECONDARY|0x0003, +RDI_DataSectionTag_NameMapBuckets = RDI_DataSectionTag_SECONDARY|0x0004, +RDI_DataSectionTag_NameMapNodes = RDI_DataSectionTag_SECONDARY|0x0005, } RDI_DataSectionTagEnum; typedef RDI_U32 RDI_DataSectionEncoding; @@ -485,6 +487,12 @@ RDI_NameMapKind_NormalSourcePaths = 6, RDI_NameMapKind_COUNT = 7, } RDI_NameMapKindEnum; +#define RDI_Header_XList \ +X(RDI_U64, magic)\ +X(RDI_U32, encoding_version)\ +X(RDI_U32, data_section_off)\ +X(RDI_U32, data_section_count)\ + #define RDI_DataSectionTag_XList \ X(NULL)\ X(TopLevelInfo)\ @@ -494,6 +502,10 @@ X(IndexRuns)\ X(BinarySections)\ X(FilePathNodes)\ X(SourceFiles)\ +X(LineTables)\ +X(LineInfoVoffs)\ +X(LineInfoLines)\ +X(LineInfoColumns)\ X(Units)\ X(UnitVmap)\ X(TypeNodes)\ @@ -507,15 +519,13 @@ X(Procedures)\ X(Scopes)\ X(ScopeVoffData)\ X(ScopeVmap)\ +X(InlineSites)\ X(Locals)\ X(LocationBlocks)\ X(LocationData)\ X(NameMaps)\ X(PRIMARY_COUNT)\ X(SECONDARY)\ -X(LineInfoVoffs)\ -X(LineInfoData)\ -X(LineInfoColumns)\ X(LineMapNumbers)\ X(LineMapRanges)\ X(LineMapVoffs)\ @@ -526,15 +536,80 @@ X(NameMapNodes)\ X(Unpacked)\ X(LZB)\ +#define RDI_DataSection_XList \ +X(RDI_DataSectionTag, tag)\ +X(RDI_DataSectionEncoding, encoding)\ +X(RDI_U64, off)\ +X(RDI_U64, encoded_size)\ +X(RDI_U64, unpacked_size)\ + +#define RDI_VMapEntry_XList \ +X(RDI_U64, voff)\ +X(RDI_U64, idx)\ + #define RDI_Arch_XList \ X(NULL)\ X(X86)\ X(X64)\ +#define RDI_TopLevelInfo_XList \ +X(RDI_Arch, arch)\ +X(RDI_U32, exe_name_string_idx)\ +X(RDI_U64, exe_hash)\ +X(RDI_U64, voff_max)\ + #define RDI_BinarySectionFlags_XList \ -X(NULL)\ -X(X86)\ -X(X64)\ +X(Read)\ +X(Write)\ +X(Execute)\ + +#define RDI_BinarySection_XList \ +X(RDI_U32, name_string_idx)\ +X(RDI_BinarySectionFlags, flags)\ +X(RDI_U64, voff_first)\ +X(RDI_U64, voff_opl)\ +X(RDI_U64, foff_first)\ +X(RDI_U64, foff_opl)\ + +#define RDI_FilePathNode_XList \ +X(RDI_U32, name_string_idx)\ +X(RDI_U32, parent_path_node)\ +X(RDI_U32, first_child)\ +X(RDI_U32, next_sibling)\ +X(RDI_U32, source_file_idx)\ + +#define RDI_SourceFile_XList \ +X(RDI_U32, file_path_node_idx)\ +X(RDI_U32, normal_full_path_string_idx)\ +X(RDI_U32, line_map_count)\ +X(RDI_U32, line_map_nums_data_idx)\ +X(RDI_U32, line_map_range_data_idx)\ +X(RDI_U32, line_map_voff_data_idx)\ + +#define RDI_Unit_XList \ +X(RDI_U32, unit_name_string_idx)\ +X(RDI_U32, compiler_name_string_idx)\ +X(RDI_U32, source_file_path_node)\ +X(RDI_U32, object_file_path_node)\ +X(RDI_U32, archive_file_path_node)\ +X(RDI_U32, build_path_node)\ +X(RDI_Language, language)\ +X(RDI_U32, line_table_idx)\ + +#define RDI_LineTable_XList \ +X(RDI_U32, voffs_base_idx)\ +X(RDI_U32, lines_base_idx)\ +X(RDI_U32, cols_base_idx)\ +X(RDI_U32, lines_count)\ +X(RDI_U32, cols_count)\ + +#define RDI_Line_XList \ +X(RDI_U32, file_idx)\ +X(RDI_U32, line_num)\ + +#define RDI_Column_XList \ +X(RDI_U16, col_first)\ +X(RDI_U16, col_opl)\ #define RDI_Language_XList \ X(NULL)\ @@ -602,9 +677,23 @@ X(Variadic)\ X(Const)\ X(Volatile)\ -#define RDI_UDTFlag_XList \ +#define RDI_TypeNode_XList \ +X(RDI_TypeKind, kind)\ +X(RDI_U16, flags)\ +X(RDI_U32, byte_size)\ + +#define RDI_UDTFlags_XList \ X(EnumMembers)\ +#define RDI_UDT_XList \ +X(RDI_U32, self_type_idx)\ +X(RDI_UDTFlags, flags)\ +X(RDI_U32, member_first)\ +X(RDI_U32, member_count)\ +X(RDI_U32, file_idx)\ +X(RDI_U32, line)\ +X(RDI_U32, col)\ + #define RDI_MemberKind_XList \ X(NULL)\ X(DataField)\ @@ -617,6 +706,18 @@ X(Base)\ X(VirtualBase)\ X(NestedType)\ +#define RDI_Member_XList \ +X(RDI_MemberKind, kind)\ +X(RDI_U16, pad)\ +X(RDI_U32, name_string_idx)\ +X(RDI_U32, type_idx)\ +X(RDI_U32, off)\ + +#define RDI_EnumMember_XList \ +X(RDI_U32, name_string_idx)\ +X(RDI_U32, pad)\ +X(RDI_U64, val)\ + #define RDI_LinkFlags_XList \ X(External)\ X(TypeScoped)\ @@ -635,6 +736,74 @@ X(AddrRegPlusU16)\ X(AddrAddrRegPlusU16)\ X(ValReg)\ +#define RDI_GlobalVariable_XList \ +X(RDI_U32, name_string_idx)\ +X(RDI_LinkFlags, link_flags)\ +X(RDI_U64, voff)\ +X(RDI_U32, type_idx)\ +X(RDI_U32, container_idx)\ + +#define RDI_ThreadVariable_XList \ +X(RDI_U32, name_string_idx)\ +X(RDI_LinkFlags, link_flags)\ +X(RDI_U32, tls_off)\ +X(RDI_U32, type_idx)\ +X(RDI_U32, container_idx)\ + +#define RDI_Procedure_XList \ +X(RDI_U32, name_string_idx)\ +X(RDI_U32, link_name_string_idx)\ +X(RDI_LinkFlags, link_flags)\ +X(RDI_U32, type_idx)\ +X(RDI_U32, root_scope_idx)\ +X(RDI_U32, container_idx)\ + +#define RDI_Scope_XList \ +X(RDI_U32, proc_idx)\ +X(RDI_U32, parent_scope_idx)\ +X(RDI_U32, first_child_scope_idx)\ +X(RDI_U32, next_sibling_scope_idx)\ +X(RDI_U32, voff_range_first)\ +X(RDI_U32, voff_range_opl)\ +X(RDI_U32, local_first)\ +X(RDI_U32, local_count)\ +X(RDI_U32, static_local_idx_run_first)\ +X(RDI_U32, static_local_count)\ + +#define RDI_InlineSite_XList \ +X(RDI_U32, name_string_idx)\ +X(RDI_U32, call_src_file_idx)\ +X(RDI_U32, call_line_num)\ +X(RDI_U32, call_col_num)\ +X(RDI_U32, type_idx)\ +X(RDI_U32, owner_type_idx)\ +X(RDI_U32, line_table_idx)\ + +#define RDI_Local_XList \ +X(RDI_LocalKind, kind)\ +X(RDI_U32, name_string_idx)\ +X(RDI_U32, type_idx)\ +X(RDI_U32, pad)\ +X(RDI_U32, location_first)\ +X(RDI_U32, location_opl)\ + +#define RDI_LocationBlock_XList \ +X(RDI_U32, scope_off_first)\ +X(RDI_U32, scope_off_opl)\ +X(RDI_U32, location_data_off)\ + +#define RDI_LocationBytecodeStream_XList \ +X(RDI_LocationKind, kind)\ + +#define RDI_LocationRegPlusU16_XList \ +X(RDI_LocationKind, kind)\ +X(RDI_RegCode, reg_code)\ +X(RDI_U16, offset)\ + +#define RDI_LocationReg_XList \ +X(RDI_LocationKind, kind)\ +X(RDI_RegCode, reg_code)\ + #define RDI_EvalOp_XList \ X(Stop)\ X(Noop)\ @@ -708,6 +877,20 @@ X(LinkNameProcedures)\ X(NormalSourcePaths)\ X(COUNT)\ +#define RDI_NameMap_XList \ +X(RDI_NameMapKind, kind)\ +X(RDI_U32, bucket_data_idx)\ +X(RDI_U32, node_data_idx)\ + +#define RDI_NameMapBucket_XList \ +X(RDI_U32, first_node)\ +X(RDI_U32, node_count)\ + +#define RDI_NameMapNode_XList \ +X(RDI_U32, string_idx)\ +X(RDI_U32, match_count)\ +X(RDI_U32, match_idx_or_idx_run_first)\ + #define RDI_EVAL_CTRLBITS(decodeN,popN,pushN) ((decodeN) | ((popN) << 4) | ((pushN) << 6)) #define RDI_DECODEN_FROM_CTRLBITS(ctrlbits) ((ctrlbits) & 0xf) #define RDI_POPN_FROM_CTRLBITS(ctrlbits) (((ctrlbits) >> 4) & 0x3) @@ -791,10 +974,7 @@ RDI_U32 object_file_path_node; RDI_U32 archive_file_path_node; RDI_U32 build_path_node; RDI_Language language; -RDI_U32 line_info_voffs_data_idx; -RDI_U32 line_info_data_idx; -RDI_U32 line_info_col_data_idx; -RDI_U32 line_info_count; +RDI_U32 line_table_idx; }; typedef struct RDI_LineTable RDI_LineTable; diff --git a/src/lib_rdi_format/rdi_format_parse.c b/src/lib_rdi_format/rdi_format_parse.c index dafce68b..63b6e5f1 100644 --- a/src/lib_rdi_format/rdi_format_parse.c +++ b/src/lib_rdi_format/rdi_format_parse.c @@ -2,116 +2,136 @@ // Licensed under the MIT license (https://opensource.org/license/mit/) //////////////////////////////// -//~ RADDBG Parse API +//~ Top-Level Parsing API RDI_PROC RDI_ParseStatus rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out) { RDI_ParseStatus result = RDI_ParseStatus_Good; - // out header + ////////////////////////////// + //- rjf: extract header + // RDI_Header *hdr = 0; + if(result == RDI_ParseStatus_Good) { - if (sizeof(*hdr) <= size){ + if(sizeof(*hdr) <= size) + { hdr = (RDI_Header*)data; } - - // (errors) - if (hdr == 0 || hdr->magic != RDI_MAGIC_CONSTANT){ + if(hdr == 0 || hdr->magic != RDI_MAGIC_CONSTANT) + { hdr = 0; result = RDI_ParseStatus_HeaderDoesNotMatch; } - if (hdr != 0 && hdr->encoding_version != 1){ + if(hdr != 0 && hdr->encoding_version != RDI_ENCODING_VERSION) + { hdr = 0; result = RDI_ParseStatus_UnsupportedVersionNumber; } } - // out data sections + ////////////////////////////// + //- rjf: extract data sections + // RDI_DataSection *dsecs = 0; RDI_U32 dsec_count = 0; - if (hdr != 0){ + if(result == RDI_ParseStatus_Good) + { RDI_U64 opl = (RDI_U64)hdr->data_section_off + (RDI_U64)hdr->data_section_count*sizeof(*dsecs); - if (opl <= size){ + if(opl <= size) + { dsecs = (RDI_DataSection*)(data + hdr->data_section_off); dsec_count = hdr->data_section_count; } - - // (errors) - if (dsecs == 0){ + if(dsecs == 0) + { result = RDI_ParseStatus_InvalidDataSecionLayout; } } - // extract primary data section indexes + ////////////////////////////// + //- rjf: extract primary data section indexes + // RDI_U32 dsec_idx[RDI_DataSectionTag_PRIMARY_COUNT] = {0}; - if (result == RDI_ParseStatus_Good){ + if(result == RDI_ParseStatus_Good) + { RDI_DataSection *sec_ptr = dsecs; - for (RDI_U32 i = 0; i < dsec_count; i += 1, sec_ptr += 1){ - if (sec_ptr->tag < RDI_DataSectionTag_PRIMARY_COUNT){ + for(RDI_U32 i = 0; i < dsec_count; i += 1, sec_ptr += 1) + { + if(sec_ptr->tag < RDI_DataSectionTag_PRIMARY_COUNT) + { dsec_idx[sec_ptr->tag] = i; } } } - // fill out data block (part 1) - if (result == RDI_ParseStatus_Good){ + ////////////////////////////// + //- rjf: fill out raw data info + // + if(result == RDI_ParseStatus_Good) + { out->raw_data = data; out->raw_data_size = size; out->dsecs = dsecs; out->dsec_count = dsec_count; - for (RDI_U32 i = 0; i < RDI_DataSectionTag_PRIMARY_COUNT; i += 1){ + for(RDI_U32 i = 0; i < RDI_DataSectionTag_PRIMARY_COUNT; i += 1) + { out->dsec_idx[i] = dsec_idx[i]; } } - // out string table + ////////////////////////////// + //- rjf: extract string table info + // RDI_U8 *string_data = 0; RDI_U64 string_opl = 0; RDI_U32 *string_offs = 0; RDI_U64 string_count = 0; - if (result == RDI_ParseStatus_Good){ - rdi_parse__extract_primary(out, string_data, &string_opl, - RDI_DataSectionTag_StringData); - + if(result == RDI_ParseStatus_Good) + { RDI_U64 table_entry_count = 0; - rdi_parse__extract_primary(out, string_offs, &table_entry_count, - RDI_DataSectionTag_StringTable); - if (table_entry_count > 0){ + rdi_parse__extract_primary(out, string_offs, &table_entry_count, RDI_DataSectionTag_StringTable); + rdi_parse__extract_primary(out, string_data, &string_opl, RDI_DataSectionTag_StringData); + if(table_entry_count > 0) + { string_count = table_entry_count - 1; } - - // (errors) - if (string_data == 0){ + if(string_data == 0) + { result = RDI_ParseStatus_MissingStringDataSection; } - else if (string_offs == 0){ + else if (string_offs == 0) + { result = RDI_ParseStatus_MissingStringTableSection; } } - // out index runs + ////////////////////////////// + //- rjf: extract index run table info + // RDI_U32 *idx_run_data = 0; RDI_U64 idx_run_count = 0; - if (result == RDI_ParseStatus_Good){ - rdi_parse__extract_primary(out, idx_run_data, &idx_run_count, - RDI_DataSectionTag_IndexRuns); - - // (errors) - if (idx_run_data == 0){ + if(result == RDI_ParseStatus_Good) + { + rdi_parse__extract_primary(out, idx_run_data, &idx_run_count, RDI_DataSectionTag_IndexRuns); + if(idx_run_data == 0) + { result = RDI_ParseStatus_MissingIndexRunSection; } } - if (result == RDI_ParseStatus_Good){ - // fill out primary data structures (part 2) + ////////////////////////////// + //- rjf: extract info tables + // + if(result == RDI_ParseStatus_Good) + { out->string_data = string_data; out->string_offs = string_offs; out->string_data_size = string_opl; out->string_count = string_count; out->idx_run_data = idx_run_data; out->idx_run_count = idx_run_count; - { RDI_TopLevelInfo *tli = 0; RDI_U64 dummy = 0; @@ -121,71 +141,32 @@ rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out) } out->top_level_info = tli; } - - rdi_parse__extract_primary(out, out->binary_sections, &out->binary_sections_count, - RDI_DataSectionTag_BinarySections); - - rdi_parse__extract_primary(out, out->file_paths, &out->file_paths_count, - RDI_DataSectionTag_FilePathNodes); - - rdi_parse__extract_primary(out, out->source_files, &out->source_files_count, - RDI_DataSectionTag_SourceFiles); - - rdi_parse__extract_primary(out, out->units, &out->units_count, - RDI_DataSectionTag_Units); - - rdi_parse__extract_primary(out, out->unit_vmap, &out->unit_vmap_count, - RDI_DataSectionTag_UnitVmap); - - rdi_parse__extract_primary(out, out->unit_vmap, &out->unit_vmap_count, - RDI_DataSectionTag_UnitVmap); - - rdi_parse__extract_primary(out, out->type_nodes, &out->type_nodes_count, - RDI_DataSectionTag_TypeNodes); - - rdi_parse__extract_primary(out, out->udts, &out->udts_count, - RDI_DataSectionTag_UDTs); - - rdi_parse__extract_primary(out, out->members, &out->members_count, - RDI_DataSectionTag_Members); - - rdi_parse__extract_primary(out, out->enum_members, &out->enum_members_count, - RDI_DataSectionTag_EnumMembers); - - rdi_parse__extract_primary(out, out->global_variables, &out->global_variables_count, - RDI_DataSectionTag_GlobalVariables); - - rdi_parse__extract_primary(out, out->global_vmap, &out->global_vmap_count, - RDI_DataSectionTag_GlobalVmap); - - rdi_parse__extract_primary(out, out->thread_variables, &out->thread_variables_count, - RDI_DataSectionTag_ThreadVariables); - - rdi_parse__extract_primary(out, out->procedures, &out->procedures_count, - RDI_DataSectionTag_Procedures); - - rdi_parse__extract_primary(out, out->scopes, &out->scopes_count, - RDI_DataSectionTag_Scopes); - - rdi_parse__extract_primary(out, out->scope_voffs, &out->scope_voffs_count, - RDI_DataSectionTag_ScopeVoffData); - - rdi_parse__extract_primary(out, out->scope_vmap, &out->scope_vmap_count, - RDI_DataSectionTag_ScopeVmap); - - rdi_parse__extract_primary(out, out->locals, &out->locals_count, - RDI_DataSectionTag_Locals); - - rdi_parse__extract_primary(out, out->location_blocks, &out->location_blocks_count, - RDI_DataSectionTag_LocationBlocks); - - rdi_parse__extract_primary(out, out->location_data, &out->location_data_size, - RDI_DataSectionTag_LocationData); - + rdi_parse__extract_primary(out, out->binary_sections, &out->binary_sections_count, RDI_DataSectionTag_BinarySections); + rdi_parse__extract_primary(out, out->file_paths, &out->file_paths_count, RDI_DataSectionTag_FilePathNodes); + rdi_parse__extract_primary(out, out->source_files, &out->source_files_count, RDI_DataSectionTag_SourceFiles); + rdi_parse__extract_primary(out, out->line_tables, &out->line_tables_count, RDI_DataSectionTag_LineTables); + rdi_parse__extract_primary(out, out->line_info_voffs, &out->line_info_voffs_count, RDI_DataSectionTag_LineInfoVoffs); + rdi_parse__extract_primary(out, out->line_info_lines, &out->line_info_lines_count, RDI_DataSectionTag_LineInfoLines); + rdi_parse__extract_primary(out, out->line_info_columns, &out->line_info_columns_count, RDI_DataSectionTag_LineInfoColumns); + rdi_parse__extract_primary(out, out->units, &out->units_count, RDI_DataSectionTag_Units); + rdi_parse__extract_primary(out, out->unit_vmap, &out->unit_vmap_count, RDI_DataSectionTag_UnitVmap); + rdi_parse__extract_primary(out, out->unit_vmap, &out->unit_vmap_count, RDI_DataSectionTag_UnitVmap); + rdi_parse__extract_primary(out, out->type_nodes, &out->type_nodes_count, RDI_DataSectionTag_TypeNodes); + rdi_parse__extract_primary(out, out->udts, &out->udts_count, RDI_DataSectionTag_UDTs); + rdi_parse__extract_primary(out, out->members, &out->members_count, RDI_DataSectionTag_Members); + rdi_parse__extract_primary(out, out->enum_members, &out->enum_members_count, RDI_DataSectionTag_EnumMembers); + rdi_parse__extract_primary(out, out->global_variables, &out->global_variables_count, RDI_DataSectionTag_GlobalVariables); + rdi_parse__extract_primary(out, out->global_vmap, &out->global_vmap_count, RDI_DataSectionTag_GlobalVmap); + rdi_parse__extract_primary(out, out->thread_variables, &out->thread_variables_count, RDI_DataSectionTag_ThreadVariables); + rdi_parse__extract_primary(out, out->procedures, &out->procedures_count, RDI_DataSectionTag_Procedures); + rdi_parse__extract_primary(out, out->scopes, &out->scopes_count, RDI_DataSectionTag_Scopes); + rdi_parse__extract_primary(out, out->scope_voffs, &out->scope_voffs_count, RDI_DataSectionTag_ScopeVoffData); + rdi_parse__extract_primary(out, out->scope_vmap, &out->scope_vmap_count, RDI_DataSectionTag_ScopeVmap); + rdi_parse__extract_primary(out, out->locals, &out->locals_count, RDI_DataSectionTag_Locals); + rdi_parse__extract_primary(out, out->location_blocks, &out->location_blocks_count, RDI_DataSectionTag_LocationBlocks); + rdi_parse__extract_primary(out, out->location_data, &out->location_data_size, RDI_DataSectionTag_LocationData); + rdi_parse__extract_primary(out, out->name_maps, &out->name_maps_count, RDI_DataSectionTag_NameMaps); { - rdi_parse__extract_primary(out, out->name_maps, &out->name_maps_count, - RDI_DataSectionTag_NameMaps); - RDI_NameMap *name_map_ptr = out->name_maps; RDI_NameMap *name_map_opl = out->name_maps + out->name_maps_count; for (; name_map_ptr < name_map_opl; name_map_ptr += 1){ @@ -196,8 +177,11 @@ rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out) } } + ////////////////////////////// + //- rjf: fill any missing tables with nil elements + // #if !defined(RDI_DISABLE_NILS) - if(out->top_level_info == 0) { out->top_level_info = &rdi_top_level_info_nil; } + 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; } @@ -218,9 +202,14 @@ rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out) if(out->location_blocks == 0) { out->location_blocks = &rdi_location_block_nil; out->location_blocks_count = 1; } #endif - return(result); + return result; } +//////////////////////////////// +//~ Parsed Info Extraction Helpers + +//- top-level info + RDI_PROC RDI_U64 rdi_decompressed_size_from_parsed(RDI_Parsed *rdi) { @@ -232,11 +221,15 @@ rdi_decompressed_size_from_parsed(RDI_Parsed *rdi) return decompressed_size; } +//- strings + RDI_PROC RDI_U8* -rdi_string_from_idx(RDI_Parsed *parsed, RDI_U32 idx, RDI_U64 *len_out){ +rdi_string_from_idx(RDI_Parsed *parsed, RDI_U32 idx, RDI_U64 *len_out) +{ RDI_U8 *result = 0; RDI_U64 len_result = 0; - if (idx < parsed->string_count){ + if(idx < parsed->string_count) + { RDI_U32 off_raw = parsed->string_offs[idx]; RDI_U32 opl_raw = parsed->string_offs[idx + 1]; RDI_U32 opl = rdi_parse__min(opl_raw, parsed->string_data_size); @@ -245,108 +238,113 @@ rdi_string_from_idx(RDI_Parsed *parsed, RDI_U32 idx, RDI_U64 *len_out){ len_result = opl - off; } *len_out = len_result; - return(result); + return result; } +//- index runs + RDI_PROC RDI_U32* -rdi_idx_run_from_first_count(RDI_Parsed *parsed, - RDI_U32 raw_first, RDI_U32 raw_count, - RDI_U32 *n_out){ +rdi_idx_run_from_first_count(RDI_Parsed *parsed, RDI_U32 raw_first, RDI_U32 raw_count, RDI_U32 *n_out) +{ RDI_U32 raw_opl = raw_first + raw_count; RDI_U32 opl = rdi_parse__min(raw_opl, parsed->idx_run_count); RDI_U32 first = rdi_parse__min(raw_first, opl); - RDI_U32 *result = 0; - if (first < parsed->idx_run_count){ + if(first < parsed->idx_run_count) + { result = parsed->idx_run_data + first; } *n_out = opl - first; - return(result); + return result; } //- line info RDI_PROC void -rdi_line_info_from_unit(RDI_Parsed *p, RDI_Unit *unit, RDI_ParsedLineInfo *out){ - RDI_U64 line_info_voff_count = 0; - RDI_U64 *voffs = (RDI_U64*) - rdi_data_from_dsec(p, unit->line_info_voffs_data_idx, sizeof(RDI_U64), - RDI_DataSectionTag_LineInfoVoffs, - &line_info_voff_count); +rdi_parsed_from_line_table(RDI_Parsed *p, RDI_LineTable *line_table, RDI_ParsedLineTable *out) +{ + //- rjf: extract top-level line info tables + RDI_U64 all_voffs_count = 0; + RDI_U64 *all_voffs = (RDI_U64 *)rdi_data_from_dsec(p, p->dsec_idx[RDI_DataSectionTag_LineInfoVoffs], sizeof(RDI_U64), RDI_DataSectionTag_LineInfoVoffs, &all_voffs_count); + RDI_U64 *all_voffs_opl = all_voffs + all_voffs_count; + RDI_U64 all_lines_count = 0; + RDI_Line *all_lines = (RDI_Line *)rdi_data_from_dsec(p, p->dsec_idx[RDI_DataSectionTag_LineInfoLines], sizeof(RDI_Line), RDI_DataSectionTag_LineInfoLines, &all_lines_count); + RDI_Line *all_lines_opl = all_lines + all_lines_count; + RDI_U64 all_cols_count = 0; + RDI_Column *all_cols = (RDI_Column *)rdi_data_from_dsec(p, p->dsec_idx[RDI_DataSectionTag_LineInfoColumns], sizeof(RDI_Column), RDI_DataSectionTag_LineInfoColumns, &all_cols_count); + RDI_Column *all_cols_opl = all_cols + all_cols_count; - RDI_U64 line_info_count_raw = 0; - RDI_Line *lines = (RDI_Line*) - rdi_data_from_dsec(p, unit->line_info_data_idx, sizeof(RDI_Line), - RDI_DataSectionTag_LineInfoData, - &line_info_count_raw); + //- rjf: extract ranges of top-level tables belonging to this line table + RDI_U64 *lt_voffs = all_voffs + line_table->voffs_base_idx; + RDI_Line *lt_lines = all_lines + line_table->lines_base_idx; + RDI_Column *lt_cols = all_cols + line_table->cols_base_idx; + RDI_U64 lines_count = line_table->lines_count; + RDI_U64 cols_count = line_table->cols_count; + if(lt_voffs >= all_voffs_opl) {lt_voffs = all_voffs; lines_count = 0;} + if(lt_lines >= all_lines_opl) {lt_lines = all_lines; lines_count = 0;} + if(lt_cols >= all_cols_opl) {lt_cols = all_cols; cols_count = 0;} - RDI_U64 column_info_count_raw = 0; - RDI_Column *cols = (RDI_Column*) - rdi_data_from_dsec(p, unit->line_info_col_data_idx, sizeof(RDI_Column), - RDI_DataSectionTag_LineInfoColumns, - &column_info_count_raw); - - RDI_U32 line_info_count_a = (line_info_voff_count > 0)?line_info_voff_count - 1:0; - RDI_U32 line_info_count = rdi_parse__min(line_info_count_a, line_info_count_raw); - RDI_U32 column_info_count = rdi_parse__min(column_info_count_raw, line_info_count); - - out->voffs = voffs; - out->lines = lines; - out->cols = cols; - out->count = line_info_count; - out->col_count = column_info_count; + //- rjf: fill result + out->voffs = lt_voffs; + out->lines = lt_lines; + out->cols = lt_cols; + out->count = lines_count; + out->col_count = cols_count; } RDI_PROC RDI_U64 -rdi_line_info_idx_from_voff(RDI_ParsedLineInfo *line_info, RDI_U64 voff) +rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff) { RDI_U64 result = 0; - if (line_info->count > 0 && line_info->voffs[0] <= voff && voff < line_info->voffs[line_info->count - 1]){ + if(line_info->count > 0 && line_info->voffs[0] <= voff && voff < line_info->voffs[line_info->count - 1]) + { // assuming: (i < j) -> (vmap[i].voff < vmap[j].voff) // find i such that: (vmap[i].voff <= voff) && (voff < vmap[i + 1].voff) RDI_U32 first = 0; RDI_U32 opl = line_info->count; - for (;;){ + for(;;) + { RDI_U32 mid = (first + opl)/2; - if (line_info->voffs[mid] < voff){ + if(line_info->voffs[mid] < voff) + { first = mid; } - else if (line_info->voffs[mid] > voff){ + else if(line_info->voffs[mid] > voff) + { opl = mid; } - else{ + else + { first = mid; break; } - if (opl - first <= 1){ + if(opl - first <= 1) + { break; } } result = (RDI_U64)first; } - return(result); + return result; } RDI_PROC void -rdi_line_map_from_source_file(RDI_Parsed *p, RDI_SourceFile *srcfile, - RDI_ParsedLineMap *out){ +rdi_line_map_from_source_file(RDI_Parsed *p, RDI_SourceFile *srcfile, RDI_ParsedLineMap *out) +{ RDI_U64 num_count = 0; - RDI_U32 *nums = (RDI_U32*) - rdi_data_from_dsec(p, srcfile->line_map_nums_data_idx, sizeof(RDI_U32), - RDI_DataSectionTag_LineMapNumbers, - &num_count); + RDI_U32 *nums = (RDI_U32*)rdi_data_from_dsec(p, srcfile->line_map_nums_data_idx, sizeof(RDI_U32), + RDI_DataSectionTag_LineMapNumbers, + &num_count); RDI_U64 range_count = 0; - RDI_U32 *ranges = (RDI_U32*) - rdi_data_from_dsec(p, srcfile->line_map_range_data_idx, sizeof(RDI_U32), - RDI_DataSectionTag_LineMapRanges, - &range_count); + RDI_U32 *ranges = (RDI_U32*)rdi_data_from_dsec(p, srcfile->line_map_range_data_idx, sizeof(RDI_U32), + RDI_DataSectionTag_LineMapRanges, + &range_count); RDI_U64 voff_count = 0; - RDI_U64 *voffs = (RDI_U64*) - rdi_data_from_dsec(p, srcfile->line_map_voff_data_idx, sizeof(RDI_U64), - RDI_DataSectionTag_LineMapVoffs, - &voff_count); + RDI_U64 *voffs = (RDI_U64*)rdi_data_from_dsec(p, srcfile->line_map_voff_data_idx, sizeof(RDI_U64), + RDI_DataSectionTag_LineMapVoffs, + &voff_count); RDI_U32 count_a = (range_count > 0)?(range_count - 1):0; RDI_U32 count_b = rdi_parse__min(count_a, num_count); @@ -360,30 +358,36 @@ rdi_line_map_from_source_file(RDI_Parsed *p, RDI_SourceFile *srcfile, } RDI_PROC RDI_U64* -rdi_line_voffs_from_num(RDI_ParsedLineMap *map, RDI_U32 linenum, RDI_U32 *n_out){ +rdi_line_voffs_from_num(RDI_ParsedLineMap *map, RDI_U32 linenum, RDI_U32 *n_out) +{ RDI_U64 *result = 0; *n_out = 0; - RDI_U32 closest_i = 0; - if (map->count > 0 && map->nums[0] <= linenum){ + if(map->count > 0 && map->nums[0] <= linenum) + { // assuming: (i < j) -> (nums[i] < nums[j]) // find i such that: (nums[i] <= linenum) && (linenum < nums[i + 1]) RDI_U32 *nums = map->nums; RDI_U32 first = 0; RDI_U32 opl = map->count; - for (;;){ + for(;;) + { RDI_U32 mid = (first + opl)/2; - if (nums[mid] < linenum){ + if(nums[mid] < linenum) + { first = mid; } - else if (nums[mid] > linenum){ + else if(nums[mid] > linenum) + { opl = mid; } - else{ + else + { first = mid; break; } - if (opl - first <= 1){ + if(opl - first <= 1) + { break; } } @@ -391,54 +395,62 @@ rdi_line_voffs_from_num(RDI_ParsedLineMap *map, RDI_U32 linenum, RDI_U32 *n_out) } // round up instead of down if possible - if (closest_i + 1 < map->count && - map->nums[closest_i] < linenum){ + if(closest_i + 1 < map->count && map->nums[closest_i] < linenum) + { closest_i += 1; } // set result if possible - if (closest_i < map->count){ + if(closest_i < map->count) + { RDI_U32 first = map->ranges[closest_i]; RDI_U32 opl = map->ranges[closest_i + 1]; - if (opl < map->voff_count){ + if(opl < map->voff_count) + { result = map->voffs + first; *n_out = opl - first; } } - return(result); + return result; } - -//- vmaps +//- vmap lookups RDI_PROC RDI_U64 -rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U32 vmap_count, RDI_U64 voff){ +rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U32 vmap_count, RDI_U64 voff) +{ RDI_U64 result = 0; - if (vmap_count > 0 && vmap[0].voff <= voff && voff < vmap[vmap_count - 1].voff){ + if(vmap_count > 0 && vmap[0].voff <= voff && voff < vmap[vmap_count - 1].voff) + { // assuming: (i < j) -> (vmap[i].voff < vmap[j].voff) // find i such that: (vmap[i].voff <= voff) && (voff < vmap[i + 1].voff) RDI_U32 first = 0; RDI_U32 opl = vmap_count; - for (;;){ + for(;;) + { RDI_U32 mid = (first + opl)/2; - if (vmap[mid].voff < voff){ + if(vmap[mid].voff < voff) + { first = mid; } - else if (vmap[mid].voff > voff){ + else if(vmap[mid].voff > voff) + { opl = mid; } - else{ + else + { first = mid; break; } - if (opl - first <= 1){ + if(opl - first <= 1) + { break; } } result = (RDI_U64)vmap[first].idx; } - return(result); + return result; } //- name maps @@ -446,47 +458,48 @@ rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U32 vmap_count, RDI_U64 voff){ RDI_PROC RDI_NameMap* rdi_name_map_from_kind(RDI_Parsed *p, RDI_NameMapKind kind){ RDI_NameMap *result = 0; - if (0 < kind && kind < RDI_NameMapKind_COUNT){ + if(0 < kind && kind < RDI_NameMapKind_COUNT) + { result = p->name_maps_by_kind[kind]; } - return(result); + return result; } RDI_PROC void -rdi_name_map_parse(RDI_Parsed *p, RDI_NameMap *mapptr, RDI_ParsedNameMap *out){ +rdi_name_map_parse(RDI_Parsed *p, RDI_NameMap *mapptr, RDI_ParsedNameMap *out) +{ out->buckets = 0; out->bucket_count = 0; - if (mapptr != 0){ - out->buckets = (RDI_NameMapBucket*) - rdi_data_from_dsec(p, mapptr->bucket_data_idx, sizeof(RDI_NameMapBucket), - RDI_DataSectionTag_NameMapBuckets, &out->bucket_count); - out->nodes = (RDI_NameMapNode*) - rdi_data_from_dsec(p, mapptr->node_data_idx, sizeof(RDI_NameMapNode), - RDI_DataSectionTag_NameMapNodes, &out->node_count); + if(mapptr != 0) + { + out->buckets = (RDI_NameMapBucket*)rdi_data_from_dsec(p, mapptr->bucket_data_idx, sizeof(RDI_NameMapBucket), RDI_DataSectionTag_NameMapBuckets, &out->bucket_count); + out->nodes = (RDI_NameMapNode*)rdi_data_from_dsec(p, mapptr->node_data_idx, sizeof(RDI_NameMapNode), RDI_DataSectionTag_NameMapNodes, &out->node_count); } } RDI_PROC RDI_NameMapNode* -rdi_name_map_lookup(RDI_Parsed *p, RDI_ParsedNameMap *map, - RDI_U8 *str, RDI_U64 len){ +rdi_name_map_lookup(RDI_Parsed *p, RDI_ParsedNameMap *map, RDI_U8 *str, RDI_U64 len) +{ RDI_NameMapNode *result = 0; - if (map->bucket_count > 0){ + if(map->bucket_count > 0) + { RDI_NameMapBucket *buckets = map->buckets; RDI_U64 bucket_count = map->bucket_count; RDI_U64 hash = rdi_hash(str, len); RDI_U64 bucket_index = hash%bucket_count; RDI_NameMapBucket *bucket = map->buckets + bucket_index; - RDI_NameMapNode *node = map->nodes + bucket->first_node; RDI_NameMapNode *node_opl = node + bucket->node_count; - for (;node < node_opl; node += 1){ + for(;node < node_opl; node += 1) + { // extract a string from this node RDI_U64 nlen = 0; RDI_U8 *nstr = rdi_string_from_idx(p, node->string_idx, &nlen); // compare this to the needle string RDI_S32 match = 0; - if (nlen == len){ + if(nlen == len) + { RDI_U8 *a = str; RDI_U8 *aopl = str + len; RDI_U8 *b = nstr; @@ -495,60 +508,64 @@ rdi_name_map_lookup(RDI_Parsed *p, RDI_ParsedNameMap *map, } // stop with a matching node in result - if (match){ + if(match) + { result = node; break; } } } - return(result); + return result; } RDI_PROC RDI_U32* -rdi_matches_from_map_node(RDI_Parsed *p, RDI_NameMapNode *node, - RDI_U32 *n_out){ +rdi_matches_from_map_node(RDI_Parsed *p, RDI_NameMapNode *node, RDI_U32 *n_out) +{ RDI_U32 *result = 0; *n_out = 0; - if (node != 0){ - if (node->match_count == 1){ + if(node != 0) + { + if(node->match_count == 1) + { result = &node->match_idx_or_idx_run_first; *n_out = 1; } - else{ - result = rdi_idx_run_from_first_count(p, node->match_idx_or_idx_run_first, - node->match_count, n_out); + else + { + result = rdi_idx_run_from_first_count(p, node->match_idx_or_idx_run_first, node->match_count, n_out); } } - return(result); + return result; } -//- common helpers +//- procedures RDI_PROC RDI_U64 -rdi_first_voff_from_proc(RDI_Parsed *p, RDI_U32 proc_id){ +rdi_first_voff_from_proc(RDI_Parsed *p, RDI_U32 proc_id) +{ RDI_U64 result = 0; - if (0 < proc_id && proc_id < p->procedures_count){ + if(0 < proc_id && proc_id < p->procedures_count) + { RDI_Procedure *proc = p->procedures + proc_id; RDI_U32 scope_id = proc->root_scope_idx; - if (0 < scope_id && scope_id < p->scopes_count){ + if(0 < scope_id && scope_id < p->scopes_count) + { RDI_Scope *scope = p->scopes + scope_id; - if (scope->voff_range_first < scope->voff_range_opl && - scope->voff_range_first < p->scope_voffs_count){ + if(scope->voff_range_first < scope->voff_range_opl && scope->voff_range_first < p->scope_voffs_count) + { result = p->scope_voffs[scope->voff_range_first]; } } } - return(result); + return result; } //////////////////////////////// -//~ RADDBG Parsing Helpers +//~ Parser Helpers RDI_PROC void* -rdi_data_from_dsec(RDI_Parsed *parsed, RDI_U32 idx, RDI_U32 item_size, - RDI_DataSectionTag expected_tag, - RDI_U64 *count_out) +rdi_data_from_dsec(RDI_Parsed *parsed, RDI_U32 idx, RDI_U32 item_size, RDI_DataSectionTag expected_tag, RDI_U64 *count_out) { void *result = 0; RDI_U32 count_result = 0; @@ -566,5 +583,5 @@ rdi_data_from_dsec(RDI_Parsed *parsed, RDI_U32 idx, RDI_U32 item_size, } } *count_out = count_result; - return(result); + return result; } diff --git a/src/lib_rdi_format/rdi_format_parse.h b/src/lib_rdi_format/rdi_format_parse.h index 66b29019..44e69fc8 100644 --- a/src/lib_rdi_format/rdi_format_parse.h +++ b/src/lib_rdi_format/rdi_format_parse.h @@ -1,23 +1,41 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -#ifndef RDI_PARSE_H -#define RDI_PARSE_H +//////////////////////////////////////////////////////////////// +//~ RAD Debug Info, (R)AD(D)BG(I) Format Parsing Library +// +// Defines helper types and functions for extracting data from +// RDI files. -//////////////////////////////// -//~ RADDBG Parsing Helpers +#ifndef RDI_FORMAT_PARSE_H +#define RDI_FORMAT_PARSE_H -typedef struct RDI_Parsed{ - // raw data & data sections (part 1) +//////////////////////////////////////////////////////////////// +//~ Parsed Information Types + +typedef enum RDI_ParseStatus +{ + RDI_ParseStatus_Good = 0, + RDI_ParseStatus_HeaderDoesNotMatch = 1, + RDI_ParseStatus_UnsupportedVersionNumber = 2, + RDI_ParseStatus_InvalidDataSecionLayout = 3, + RDI_ParseStatus_MissingStringDataSection = 4, + RDI_ParseStatus_MissingStringTableSection = 5, + RDI_ParseStatus_MissingIndexRunSection = 6, +} +RDI_ParseStatus; + +typedef struct RDI_Parsed RDI_Parsed; +struct RDI_Parsed +{ + // raw data & primary data sections RDI_U8 *raw_data; RDI_U64 raw_data_size; RDI_DataSection *dsecs; RDI_U64 dsec_count; RDI_U32 dsec_idx[RDI_DataSectionTag_PRIMARY_COUNT]; - // primary data structures (part 2) - - // handled by helper APIs + // parsed universal data structures (strings, index runs) RDI_U8* string_data; RDI_U64 string_data_size; RDI_U32* string_offs; @@ -25,16 +43,22 @@ typedef struct RDI_Parsed{ RDI_U32* idx_run_data; RDI_U32 idx_run_count; - // directly readable by users - // (any of these may be empty and null even in a successful parse) - RDI_TopLevelInfo* top_level_info; - + // extracted info & tables (any of these may be empty or null, even with a successful parse) + RDI_TopLevelInfo* top_level_info; RDI_BinarySection* binary_sections; RDI_U64 binary_sections_count; RDI_FilePathNode* file_paths; RDI_U64 file_paths_count; RDI_SourceFile* source_files; RDI_U64 source_files_count; + RDI_LineTable* line_tables; + RDI_U64 line_tables_count; + RDI_U64* line_info_voffs; + RDI_U64 line_info_voffs_count; + RDI_Line* line_info_lines; + RDI_U64 line_info_lines_count; + RDI_Column* line_info_columns; + RDI_U64 line_info_columns_count; RDI_Unit* units; RDI_U64 units_count; RDI_VMapEntry* unit_vmap; @@ -69,37 +93,26 @@ typedef struct RDI_Parsed{ RDI_U64 location_data_size; RDI_NameMap* name_maps; RDI_U64 name_maps_count; - - // other helpers - RDI_NameMap* name_maps_by_kind[RDI_NameMapKind_COUNT]; - -} RDI_Parsed; +}; -typedef enum{ - RDI_ParseStatus_Good = 0, - RDI_ParseStatus_HeaderDoesNotMatch = 1, - RDI_ParseStatus_UnsupportedVersionNumber = 2, - RDI_ParseStatus_InvalidDataSecionLayout = 3, - RDI_ParseStatus_MissingStringDataSection = 4, - RDI_ParseStatus_MissingStringTableSection = 5, - RDI_ParseStatus_MissingIndexRunSection = 6, -} RDI_ParseStatus; - -typedef struct RDI_ParsedLineInfo{ +typedef struct RDI_ParsedLineTable RDI_ParsedLineTable; +struct RDI_ParsedLineTable +{ // NOTE: Mapping VOFF -> LINE_INFO // // * [ voff[i], voff[i + 1] ) forms the voff range // * for the line info at lines[i] (and cols[i] if i < col_count) - RDI_U64* voffs; // [count + 1] sorted RDI_Line* lines; // [count] RDI_Column* cols; // [col_count] RDI_U64 count; RDI_U64 col_count; -} RDI_ParsedLineInfo; +}; -typedef struct RDI_ParsedLineMap{ +typedef struct RDI_ParsedLineMap RDI_ParsedLineMap; +struct RDI_ParsedLineMap +{ // NOTE: Mapping LINE_NUMBER -> VOFFs // // * nums[i] gives a line number @@ -108,21 +121,21 @@ typedef struct RDI_ParsedLineMap{ // * to find all associated voffs for the line number nums[i] : // * let k span over the range [ ranges[i], ranges[i + 1] ) // * voffs[k] gives the associated voffs - RDI_U32* nums; // [count] sorted RDI_U32* ranges; // [count + 1] RDI_U64* voffs; // [voff_count] RDI_U64 count; RDI_U64 voff_count; -} RDI_ParsedLineMap; +}; - -typedef struct RDI_ParsedNameMap{ +typedef struct RDI_ParsedNameMap RDI_ParsedNameMap; +struct RDI_ParsedNameMap +{ RDI_NameMapBucket *buckets; RDI_NameMapNode *nodes; RDI_U64 bucket_count; RDI_U64 node_count; -} RDI_ParsedNameMap; +}; //////////////////////////////// //~ Global Nils @@ -132,6 +145,9 @@ 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}; +static RDI_LineTable rdi_line_table_nil = {0}; +static RDI_Line rdi_line_nil = {0}; +static RDI_Column rdi_column_nil = {0}; static RDI_Unit rdi_unit_nil = {0}; static RDI_VMapEntry rdi_vmap_entry_nil = {0}; static RDI_TypeNode rdi_type_node_nil = {0}; @@ -148,76 +164,50 @@ static RDI_Local rdi_local_nil = {0}; #endif //////////////////////////////// -//~ RADDBG Parse API - -RDI_PROC RDI_ParseStatus -rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out); - -RDI_PROC RDI_U64 -rdi_decompressed_size_from_parsed(RDI_Parsed *rdi); - -RDI_PROC RDI_U8* -rdi_string_from_idx(RDI_Parsed *parsed, RDI_U32 idx, RDI_U64 *len_out); - -RDI_PROC RDI_U32* -rdi_idx_run_from_first_count(RDI_Parsed *parsed, RDI_U32 first, RDI_U32 raw_count, - RDI_U32 *n_out); - -//- table lookups -#define rdi_element_from_idx(parsed, name, idx) ((0 <= (idx) && (idx) < (parsed)->name##_count) ? &(parsed)->name[idx] : (parsed)->name ? &(parsed)->name[0] : 0) - -//- line info -RDI_PROC void -rdi_line_info_from_unit(RDI_Parsed *p, RDI_Unit *unit, RDI_ParsedLineInfo *out); - -RDI_PROC RDI_U64 -rdi_line_info_idx_from_voff(RDI_ParsedLineInfo *line_info, RDI_U64 voff); - -RDI_PROC void -rdi_line_map_from_source_file(RDI_Parsed *p, RDI_SourceFile *srcfile, - RDI_ParsedLineMap *out); - -RDI_PROC RDI_U64* -rdi_line_voffs_from_num(RDI_ParsedLineMap *map, RDI_U32 linenum, RDI_U32 *n_out); - - -//- vmaps -RDI_PROC RDI_U64 -rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U32 vmap_count, RDI_U64 voff); - - -//- name maps -RDI_PROC RDI_NameMap* -rdi_name_map_from_kind(RDI_Parsed *p, RDI_NameMapKind kind); - -RDI_PROC void -rdi_name_map_parse(RDI_Parsed* p, RDI_NameMap *mapptr, RDI_ParsedNameMap *out); - -RDI_PROC RDI_NameMapNode* -rdi_name_map_lookup(RDI_Parsed *p, RDI_ParsedNameMap *map, - RDI_U8 *str, RDI_U64 len); - -RDI_PROC RDI_U32* -rdi_matches_from_map_node(RDI_Parsed *p, RDI_NameMapNode *node, RDI_U32 *n_out); - - -//- common helpers -RDI_PROC RDI_U64 -rdi_first_voff_from_proc(RDI_Parsed *p, RDI_U32 proc_id); - +//~ Top-Level Parsing API +RDI_PROC RDI_ParseStatus rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out); //////////////////////////////// -//~ RADDBG Parsing Helpers +//~ Parsed Info Extraction Helpers +//- element extractor +#define rdi_element_from_idx(parsed, name, idx) ((0 <= (idx) && (idx) < (parsed)->name##_count) ? &(parsed)->name[idx] : (parsed)->name ? &(parsed)->name[0] : 0) + +//- top-level info +RDI_PROC RDI_U64 rdi_decompressed_size_from_parsed(RDI_Parsed *rdi); + +//- strings +RDI_PROC RDI_U8 *rdi_string_from_idx(RDI_Parsed *parsed, RDI_U32 idx, RDI_U64 *len_out); + +//- index runs +RDI_PROC RDI_U32 *rdi_idx_run_from_first_count(RDI_Parsed *parsed, RDI_U32 first, RDI_U32 raw_count, RDI_U32 *n_out); + +//- line info +RDI_PROC void rdi_parsed_from_line_table(RDI_Parsed *p, RDI_LineTable *line_table, RDI_ParsedLineTable *out); +RDI_PROC RDI_U64 rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff); +RDI_PROC void rdi_line_map_from_source_file(RDI_Parsed *p, RDI_SourceFile *srcfile, RDI_ParsedLineMap *out); +RDI_PROC RDI_U64 *rdi_line_voffs_from_num(RDI_ParsedLineMap *map, RDI_U32 linenum, RDI_U32 *n_out); + +//- vmap lookups +RDI_PROC RDI_U64 rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U32 vmap_count, RDI_U64 voff); + +//- name maps +RDI_PROC RDI_NameMap *rdi_name_map_from_kind(RDI_Parsed *p, RDI_NameMapKind kind); +RDI_PROC void rdi_name_map_parse(RDI_Parsed* p, RDI_NameMap *mapptr, RDI_ParsedNameMap *out); +RDI_PROC RDI_NameMapNode *rdi_name_map_lookup(RDI_Parsed *p, RDI_ParsedNameMap *map, RDI_U8 *str, RDI_U64 len); +RDI_PROC RDI_U32 *rdi_matches_from_map_node(RDI_Parsed *p, RDI_NameMapNode *node, RDI_U32 *n_out); + +//- procedures +RDI_PROC RDI_U64 rdi_first_voff_from_proc(RDI_Parsed *p, RDI_U32 proc_id); + +//////////////////////////////// +//~ Parser Helpers + +#define rdi_parse__min(a,b) (((a)<(b))?(a):(b)) #define rdi_parse__extract_primary(p,outptr,outn,pritag) \ ( (*(void**)&(outptr)) = \ rdi_data_from_dsec((p),(p)->dsec_idx[pritag],sizeof(*(outptr)),(pritag),(outn)) ) +RDI_PROC void *rdi_data_from_dsec(RDI_Parsed *p, RDI_U32 idx, RDI_U32 item_size, RDI_DataSectionTag expected_tag, RDI_U64 *n_out); -RDI_PROC void* -rdi_data_from_dsec(RDI_Parsed *p, RDI_U32 idx, RDI_U32 item_size, - RDI_DataSectionTag expected_tag, RDI_U64 *n_out); - -#define rdi_parse__min(a,b) (((a)<(b))?(a):(b)) - -#endif // RDI_PARSE_H +#endif // RDI_FORMAT_PARSE_H diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index ba144524..63ef3e88 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -514,6 +514,81 @@ rdim_src_file_push_line_sequence(RDIM_Arena *arena, RDIM_SrcFileChunkList *src_f RDIM_SLLQueuePush(src_file->first_line_map_fragment, src_file->last_line_map_fragment, fragment); } +//////////////////////////////// +//~ rjf: [Building] Line Info Building + +RDI_PROC RDIM_LineTable * +rdim_line_table_chunk_list_push(RDIM_Arena *arena, RDIM_LineTableChunkList *list, RDI_U64 cap) +{ + RDIM_LineTableChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_LineTableChunkNode, 1); + n->cap = cap; + n->base_idx = list->total_count; + n->v = rdim_push_array(arena, RDIM_LineTable, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_LineTable *line_table = &n->v[n->count]; + line_table->chunk = n; + n->count += 1; + list->total_count += 1; + return line_table; +} + +RDI_PROC RDI_U64 +rdim_idx_from_line_table(RDIM_LineTable *line_table) +{ + RDI_U64 idx = 0; + if(line_table != 0 && line_table->chunk != 0) + { + idx = line_table->chunk->base_idx + (line_table - line_table->chunk->v) + 1; + } + return idx; +} + +RDI_PROC void +rdim_line_table_chunk_list_concat_in_place(RDIM_LineTableChunkList *dst, RDIM_LineTableChunkList *to_push) +{ + for(RDIM_LineTableChunkNode *n = to_push->first; n != 0; n = n->next) + { + n->base_idx += dst->total_count; + } + if(dst->last != 0 && to_push->first != 0) + { + dst->last->next = to_push->first; + dst->last = to_push->last; + dst->chunk_count += to_push->chunk_count; + dst->total_count += to_push->total_count; + dst->total_line_count += to_push->total_line_count; + } + else if(dst->first == 0) + { + rdim_memcpy_struct(dst, to_push); + } + rdim_memzero_struct(to_push); +} + +RDI_PROC RDIM_LineSequence * +rdim_line_table_push_sequence(RDIM_Arena *arena, RDIM_LineTableChunkList *line_tables, RDIM_LineTable *line_table, RDIM_SrcFile *src_file, RDI_U64 *voffs, RDI_U32 *line_nums, RDI_U16 *col_nums, RDI_U64 line_count) +{ + RDIM_LineSequenceNode *n = push_array(arena, RDIM_LineSequenceNode, 1); + n->v.src_file = src_file; + n->v.voffs = voffs; + n->v.line_nums = line_nums; + n->v.col_nums = col_nums; + n->v.line_count = line_count; + SLLQueuePush(line_table->first_seq, line_table->last_seq, n); + line_table->seq_count += 1; + line_table->line_count += line_count; + line_table->col_count += line_count*2*(col_nums != 0); + line_tables->total_seq_count += 1; + line_tables->total_line_count += line_count; + line_tables->total_col_count += line_count*2*(col_nums != 0); + return &n->v; +} + //////////////////////////////// //~ rjf: [Building] Unit List Building @@ -569,15 +644,6 @@ rdim_unit_chunk_list_concat_in_place(RDIM_UnitChunkList *dst, RDIM_UnitChunkList rdim_memzero_struct(to_push); } -RDI_PROC RDIM_LineSequence * -rdim_line_sequence_list_push(RDIM_Arena *arena, RDIM_LineSequenceList *list) -{ - RDIM_LineSequenceNode *n = rdim_push_array(arena, RDIM_LineSequenceNode, 1); - RDIM_SLLQueuePush(list->first, list->last, n); - list->count += 1; - return &n->v; -} - //////////////////////////////// //~ rjf: [Building] Type Info Building @@ -992,9 +1058,6 @@ rdim_bake_section_count_from_params(RDIM_BakeParams *params) RDI_U64 section_count = 0; { section_count += RDI_DataSectionTag_PRIMARY_COUNT; - section_count += params->units.total_count; // PER-UNIT line info voffs - section_count += params->units.total_count; // PER-UNIT line info data - section_count += params->units.total_count; // PER-UNIT line info columns section_count += params->src_files.total_count; // PER-SOURCE-FILE line map numbers section_count += params->src_files.total_count; // PER-SOURCE-FILE line map ranges section_count += params->src_files.total_count; // PER-SOURCE-FILE line map voffs @@ -1016,50 +1079,33 @@ rdim_bake_section_idx_from_params_tag_idx(RDIM_BakeParams *params, RDI_DataSecti { default:{}break; - //- rjf: per-unit sections - case (RDI_U32)RDI_DataSectionTag_LineInfoVoffs: - if(idx != 0) - { - result = RDI_DataSectionTag_PRIMARY_COUNT + 0*params->units.total_count + (idx-1)%params->units.total_count; - }break; - case (RDI_U32)RDI_DataSectionTag_LineInfoData: - if(idx != 0) - { - result = RDI_DataSectionTag_PRIMARY_COUNT + 1*params->units.total_count + (idx-1)%params->units.total_count; - }break; - case (RDI_U32)RDI_DataSectionTag_LineInfoColumns: - if(idx != 0) - { - result = RDI_DataSectionTag_PRIMARY_COUNT + 2*params->units.total_count + (idx-1)%params->units.total_count; - }break; - //- rjf: per-source-file sections case (RDI_U32)RDI_DataSectionTag_LineMapNumbers: if(idx != 0) { - result = RDI_DataSectionTag_PRIMARY_COUNT + 3*params->units.total_count + 0*params->src_files.total_count + (idx-1)%params->src_files.total_count; + result = RDI_DataSectionTag_PRIMARY_COUNT + 0*params->src_files.total_count + (idx-1)%params->src_files.total_count; }break; case (RDI_U32)RDI_DataSectionTag_LineMapRanges: if(idx != 0) { - result = RDI_DataSectionTag_PRIMARY_COUNT + 3*params->units.total_count + 1*params->src_files.total_count + (idx-1)%params->src_files.total_count; + result = RDI_DataSectionTag_PRIMARY_COUNT + 1*params->src_files.total_count + (idx-1)%params->src_files.total_count; }break; case (RDI_U32)RDI_DataSectionTag_LineMapVoffs: if(idx != 0) { - result = RDI_DataSectionTag_PRIMARY_COUNT + 3*params->units.total_count + 2*params->src_files.total_count + (idx-1)%params->src_files.total_count; + result = RDI_DataSectionTag_PRIMARY_COUNT + 2*params->src_files.total_count + (idx-1)%params->src_files.total_count; }break; //- rjf: per-name-map sections case (RDI_U32)RDI_DataSectionTag_NameMapBuckets: if(idx != 0) { - result = RDI_DataSectionTag_PRIMARY_COUNT + 3*params->units.total_count + 3*params->src_files.total_count + 0*(RDI_NameMapKind_COUNT-1) + (idx-1)%(RDI_NameMapKind_COUNT-1); + result = RDI_DataSectionTag_PRIMARY_COUNT + 3*params->src_files.total_count + 0*(RDI_NameMapKind_COUNT-1) + (idx-1)%(RDI_NameMapKind_COUNT-1); }break; case (RDI_U32)RDI_DataSectionTag_NameMapNodes: if(idx != 0) { - result = RDI_DataSectionTag_PRIMARY_COUNT + 3*params->units.total_count + 3*params->src_files.total_count + 1*(RDI_NameMapKind_COUNT-1) + (idx-1)%(RDI_NameMapKind_COUNT-1); + result = RDI_DataSectionTag_PRIMARY_COUNT + 3*params->src_files.total_count + 1*(RDI_NameMapKind_COUNT-1) + (idx-1)%(RDI_NameMapKind_COUNT-1); }break; } return result; @@ -1437,17 +1483,20 @@ rdim_bake_string_map_tight_from_loose(RDIM_Arena *arena, RDIM_BakeStringMapTopol RDI_PROC RDI_U64 rdim_bake_idx_from_string(RDIM_BakeStringMapTight *map, RDIM_String8 string) { - RDI_U64 hash = rdi_hash(string.RDIM_String8_BaseMember, string.RDIM_String8_SizeMember); - RDI_U64 slot_idx = hash%map->slots_count; RDI_U64 idx = 0; - for(RDIM_BakeStringChunkNode *n = map->slots[slot_idx].first; n != 0; n = n->next) + if(string.RDIM_String8_SizeMember != 0) { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) + RDI_U64 hash = rdi_hash(string.RDIM_String8_BaseMember, string.RDIM_String8_SizeMember); + RDI_U64 slot_idx = hash%map->slots_count; + for(RDIM_BakeStringChunkNode *n = map->slots[slot_idx].first; n != 0; n = n->next) { - if(n->v[chunk_idx].hash == hash && rdim_str8_match(n->v[chunk_idx].string, string, 0)) + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) { - idx = map->slots_base_idxs[slot_idx] + n->base_idx + chunk_idx; - break; + if(n->v[chunk_idx].hash == hash && rdim_str8_match(n->v[chunk_idx].string, string, 0)) + { + idx = map->slots_base_idxs[slot_idx] + n->base_idx + chunk_idx + 1; + break; + } } } } @@ -2174,6 +2223,34 @@ rdim_bake_binary_section_section_list_from_params(RDIM_Arena *arena, RDIM_BakeSt //- rjf: units +RDI_PROC RDIM_BakeSectionList +rdim_bake_unit_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params) +{ + RDIM_BakeSectionList sections = {0}; + RDI_Unit *dst_base = rdim_push_array(arena, RDI_Unit, params->units.total_count+1); + RDI_U64 dst_idx = 1; + for(RDIM_UnitChunkNode *src_n = params->units.first; src_n != 0; src_n = src_n->next) + { + for(RDI_U64 src_chunk_idx = 0; src_chunk_idx < src_n->count; src_chunk_idx += 1, dst_idx += 1) + { + RDIM_Unit *src = &src_n->v[src_chunk_idx]; + RDI_Unit *dst = &dst_base[dst_idx]; + dst->unit_name_string_idx = (RDI_U32)rdim_bake_idx_from_string(strings, src->unit_name); // TODO(rjf): @u64_to_u32 + dst->compiler_name_string_idx = (RDI_U32)rdim_bake_idx_from_string(strings, src->compiler_name); // TODO(rjf): @u64_to_u32 + dst->source_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->source_file); + dst->object_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->object_file); + dst->archive_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->archive_file); + dst->build_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->build_path); + dst->language = src->language; + dst->line_table_idx = (RDI_U32)rdim_idx_from_line_table(src->line_table); // TODO(rjf): @u64_to_u32 + } + } + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_base, sizeof(*dst_base)*dst_idx, RDI_DataSectionTag_Units, 0); + return sections; +} + +#if 0 // TODO(rjf): @inline_sites + RDI_PROC RDIM_BakeSectionList rdim_bake_section_list_from_unit(RDIM_Arena *arena, RDIM_Unit *unit) { @@ -2445,6 +2522,8 @@ rdim_bake_unit_top_level_section_list_from_params(RDIM_Arena *arena, RDIM_BakeSt return sections; } +#endif + //- rjf: unit vmap RDI_PROC RDIM_BakeSectionList @@ -2706,6 +2785,159 @@ rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMa return sections; } +//- rjf: line tables + +RDI_PROC RDIM_BakeSectionList +rdim_bake_line_table_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params) +{ + // + // TODO(rjf): + // 1. section for all line tables + // 2. section for all line info voff ranges + // 3. section for all line info lines + // 4. section for all line info columns + // + // the entire line info voffs/lines/columns tables are not sorted together; only sub-sections, belonging to + // specific line tables, are sorted as one. so it is known up-front which line table maps to which index + // range into the collated line info sections. + // + //- rjf: build all combined line info + RDI_LineTable *dst_line_tables = push_array(arena, RDI_LineTable, params->line_tables.total_count+1); + RDI_U64 *dst_line_voffs = push_array(arena, RDI_U64, params->line_tables.total_line_count + params->line_tables.total_seq_count); + RDI_Line *dst_lines = push_array(arena, RDI_Line, params->line_tables.total_line_count); + RDI_Column *dst_cols = push_array(arena, RDI_Column, params->line_tables.total_col_count); + { + RDI_U64 dst_table_idx = 1; + RDI_U64 dst_voff_idx = 0; + RDI_U64 dst_line_idx = 0; + RDI_U64 dst_col_idx = 0; + for(RDIM_LineTableChunkNode *src_n = params->line_tables.first; src_n != 0; src_n = src_n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < src_n->count; chunk_idx += 1) + { + RDIM_LineTable *src_line_table = &src_n->v[chunk_idx]; + RDI_LineTable *dst_line_table = &dst_line_tables[dst_table_idx]; + + //- rjf: fill combined line table info + { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + //- rjf: gather up all line info into two arrays: + // + // [1] keys: sortable array; pairs voffs with line info records; null records are sequence enders + // [2] recs: contains all the source coordinates for a range of voffs + // + typedef struct RDIM_LineRec RDIM_LineRec; + struct RDIM_LineRec + { + RDI_U32 file_id; + RDI_U32 line_num; + RDI_U16 col_first; + RDI_U16 col_opl; + }; + RDI_U64 line_count = 0; + RDI_U64 seq_count = 0; + for(RDIM_LineSequenceNode *seq_n = src_line_table->first_seq; seq_n != 0; seq_n = seq_n->next) + { + seq_count += 1; + line_count += seq_n->v.line_count; + } + RDI_U64 key_count = line_count + seq_count; + RDIM_SortKey *line_keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, key_count); + RDIM_LineRec *line_recs = rdim_push_array_no_zero(scratch.arena, RDIM_LineRec, line_count); + { + RDIM_SortKey *key_ptr = line_keys; + RDIM_LineRec *rec_ptr = line_recs; + for(RDIM_LineSequenceNode *seq_n = src_line_table->first_seq; seq_n != 0; seq_n = seq_n->next) + { + RDIM_LineSequence *seq = &seq_n->v; + for(RDI_U64 line_idx = 0; line_idx < seq->line_count; line_idx += 1) + { + key_ptr->key = seq->voffs[line_idx]; + key_ptr->val = rec_ptr; + key_ptr += 1; + rec_ptr->file_id = (RDI_U32)rdim_idx_from_src_file(seq->src_file); // TODO(rjf): @u64_to_u32 + rec_ptr->line_num = seq->line_nums[line_idx]; + if(seq->col_nums != 0) + { + rec_ptr->col_first = seq->col_nums[line_idx*2]; + rec_ptr->col_opl = seq->col_nums[line_idx*2 + 1]; + } + rec_ptr += 1; + } + key_ptr->key = seq->voffs[seq->line_count]; + key_ptr->val = 0; + key_ptr += 1; + } + } + + //- rjf: sort + RDIM_SortKey *sorted_line_keys = 0; + RDIM_ProfScope("sort") + { + sorted_line_keys = rdim_sort_key_array(scratch.arena, line_keys, key_count); + } + + // TODO(rjf): do a pass over sorted keys to make sure duplicate keys + // are sorted with null record first, and no more than one null + // record and one non-null record + + //- rjf: arrange output + RDI_U64 *arranged_voffs = dst_line_voffs + dst_voff_idx; + RDI_Line *arranged_lines = dst_lines + dst_line_idx; + RDIM_ProfScope("arrange output") + { + for(RDI_U64 i = 0; i < key_count; i += 1) + { + arranged_voffs[i] = sorted_line_keys[i].key; + } + arranged_voffs[key_count] = ~0ull; + for(RDI_U64 i = 0; i < key_count; i += 1) + { + RDIM_LineRec *rec = (RDIM_LineRec*)sorted_line_keys[i].val; + if(rec != 0) + { + arranged_lines[i].file_idx = rec->file_id; + arranged_lines[i].line_num = rec->line_num; + } + else + { + arranged_lines[i].file_idx = 0; + arranged_lines[i].line_num = 0; + } + } + } + + rdim_scratch_end(scratch); + } + + //- rjf: fill destination table + dst_line_table->voffs_base_idx = (RDI_U32)dst_voff_idx; // TODO(rjf): @u64_to_u32 + dst_line_table->lines_base_idx = (RDI_U32)dst_line_idx; // TODO(rjf): @u64_to_u32 + dst_line_table->cols_base_idx = (RDI_U32)dst_col_idx; // TODO(rjf): @u64_to_u32 + dst_line_table->lines_count = (RDI_U32)src_line_table->line_count; // TODO(rjf): @u64_to_u32 + dst_line_table->cols_count = (RDI_U32)src_line_table->col_count; // TODO(rjf): @u64_to_u32 + + //- rjf: increment + dst_table_idx += 1; + dst_voff_idx += src_line_table->line_count + src_line_table->seq_count; + dst_line_idx += src_line_table->line_count; + dst_col_idx += src_line_table->col_count; + } + } + } + + //- rjf: produce sections + RDIM_BakeSectionList sections = {0}; + { + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_line_tables, sizeof(RDI_LineTable)*params->line_tables.total_count, RDI_DataSectionTag_LineTables, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_line_voffs, sizeof(RDI_U64) * (params->line_tables.total_line_count + params->line_tables.total_seq_count), RDI_DataSectionTag_LineInfoVoffs, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_lines, sizeof(RDI_Line) * params->line_tables.total_line_count, RDI_DataSectionTag_LineInfoLines, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_cols, sizeof(RDI_Column) * params->line_tables.total_col_count, RDI_DataSectionTag_LineInfoColumns, 0); + } + return sections; +} + //- rjf: type nodes RDI_PROC RDIM_BakeSectionList @@ -3487,8 +3719,8 @@ rdim_bake_string_section_list_from_string_map(RDIM_Arena *arena, RDIM_BakeString for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) { RDIM_BakeString *bake_string = &n->v[chunk_idx]; - off_cursor += bake_string->string.size; *off_ptr = off_cursor; + off_cursor += bake_string->string.size; off_ptr += 1; } } diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index c12c2a0e..bb993079 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -487,7 +487,7 @@ struct RDIM_SrcFileChunkList }; //////////////////////////////// -//~ rjf: Per-Compilation-Unit Info Types +//~ rjf: Line Info Types typedef struct RDIM_LineSequence RDIM_LineSequence; struct RDIM_LineSequence @@ -506,14 +506,42 @@ struct RDIM_LineSequenceNode RDIM_LineSequence v; }; -typedef struct RDIM_LineSequenceList RDIM_LineSequenceList; -struct RDIM_LineSequenceList +typedef struct RDIM_LineTable RDIM_LineTable; +struct RDIM_LineTable { - RDIM_LineSequenceNode *first; - RDIM_LineSequenceNode *last; - RDI_U64 count; + struct RDIM_LineTableChunkNode *chunk; + RDIM_LineSequenceNode *first_seq; + RDIM_LineSequenceNode *last_seq; + RDI_U64 seq_count; + RDI_U64 line_count; + RDI_U64 col_count; }; +typedef struct RDIM_LineTableChunkNode RDIM_LineTableChunkNode; +struct RDIM_LineTableChunkNode +{ + RDIM_LineTableChunkNode *next; + RDIM_LineTable *v; + RDI_U64 count; + RDI_U64 cap; + RDI_U64 base_idx; +}; + +typedef struct RDIM_LineTableChunkList RDIM_LineTableChunkList; +struct RDIM_LineTableChunkList +{ + RDIM_LineTableChunkNode *first; + RDIM_LineTableChunkNode *last; + RDI_U64 chunk_count; + RDI_U64 total_count; + RDI_U64 total_seq_count; + RDI_U64 total_line_count; + RDI_U64 total_col_count; +}; + +//////////////////////////////// +//~ rjf: Per-Compilation-Unit Info Types + typedef struct RDIM_Unit RDIM_Unit; struct RDIM_Unit { @@ -525,7 +553,7 @@ struct RDIM_Unit RDIM_String8 archive_file; RDIM_String8 build_path; RDI_Language language; - RDIM_LineSequenceList line_sequences; + RDIM_LineTable *line_table; RDIM_Rng1U64List voff_ranges; }; @@ -735,6 +763,41 @@ struct RDIM_SymbolChunkList RDI_U64 total_count; }; +//////////////////////////////// +//~ rjf: Inline Site Info Types + +typedef struct RDIM_InlineSite RDIM_InlineSite; +struct RDIM_InlineSite +{ + struct RDIM_InlineSiteChunkNode *chunk; + RDIM_String8 name; + RDIM_SrcFile *call_src_file; + RDI_U32 call_line_num; + RDI_U32 call_col_num; + RDIM_Type *type; + RDIM_Type *owner; + RDIM_LineTable *line_info; +}; + +typedef struct RDIM_InlineSiteChunkNode RDIM_InlineSiteChunkNode; +struct RDIM_InlineSiteChunkNode +{ + RDIM_InlineSiteChunkNode *next; + RDIM_InlineSite *v; + RDI_U64 count; + RDI_U64 cap; + RDI_U64 base_idx; +}; + +typedef struct RDIM_InlineSiteChunkList RDIM_InlineSiteChunkList; +struct RDIM_InlineSiteChunkList +{ + RDIM_InlineSiteChunkNode *first; + RDIM_InlineSiteChunkNode *last; + RDI_U64 chunk_count; + RDI_U64 total_count; +}; + //////////////////////////////// //~ rjf: Scope Info Types @@ -799,10 +862,12 @@ struct RDIM_BakeParams RDIM_TypeChunkList types; RDIM_UDTChunkList udts; RDIM_SrcFileChunkList src_files; + RDIM_LineTableChunkList line_tables; RDIM_SymbolChunkList global_variables; RDIM_SymbolChunkList thread_variables; RDIM_SymbolChunkList procedures; RDIM_ScopeChunkList scopes; + RDIM_InlineSiteChunkList inline_sites; }; //- rjf: data sections @@ -1056,13 +1121,20 @@ RDI_PROC RDI_U64 rdim_idx_from_src_file(RDIM_SrcFile *src_file); RDI_PROC void rdim_src_file_chunk_list_concat_in_place(RDIM_SrcFileChunkList *dst, RDIM_SrcFileChunkList *to_push); RDI_PROC void rdim_src_file_push_line_sequence(RDIM_Arena *arena, RDIM_SrcFileChunkList *src_files, RDIM_SrcFile *src_file, RDIM_LineSequence *seq); +//////////////////////////////// +//~ rjf: [Building] Line Info Building + +RDI_PROC RDIM_LineTable *rdim_line_table_chunk_list_push(RDIM_Arena *arena, RDIM_LineTableChunkList *list, RDI_U64 cap); +RDI_PROC RDI_U64 rdim_idx_from_line_table(RDIM_LineTable *line_table); +RDI_PROC void rdim_line_table_chunk_list_concat_in_place(RDIM_LineTableChunkList *dst, RDIM_LineTableChunkList *to_push); +RDI_PROC RDIM_LineSequence *rdim_line_table_push_sequence(RDIM_Arena *arena, RDIM_LineTableChunkList *line_tables, RDIM_LineTable *line_table, RDIM_SrcFile *src_file, RDI_U64 *voffs, RDI_U32 *line_nums, RDI_U16 *col_nums, RDI_U64 line_count); + //////////////////////////////// //~ rjf: [Building] Unit Info Building RDI_PROC RDIM_Unit *rdim_unit_chunk_list_push(RDIM_Arena *arena, RDIM_UnitChunkList *list, RDI_U64 cap); RDI_PROC RDI_U64 rdim_idx_from_unit(RDIM_Unit *unit); RDI_PROC void rdim_unit_chunk_list_concat_in_place(RDIM_UnitChunkList *dst, RDIM_UnitChunkList *to_push); -RDI_PROC RDIM_LineSequence *rdim_line_sequence_list_push(RDIM_Arena *arena, RDIM_LineSequenceList *list); //////////////////////////////// //~ rjf: [Building] Type Info & UDT Building @@ -1201,8 +1273,11 @@ RDI_PROC RDIM_BakeSectionList rdim_bake_top_level_info_section_list_from_params( RDI_PROC RDIM_BakeSectionList rdim_bake_binary_section_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); //- rjf: units +RDI_PROC RDIM_BakeSectionList rdim_bake_unit_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params); +#if 0 // TODO(rjf): @inline_sites RDI_PROC RDIM_BakeSectionList rdim_bake_section_list_from_unit(RDIM_Arena *arena, RDIM_Unit *unit); RDI_PROC RDIM_BakeSectionList rdim_bake_unit_top_level_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params); +#endif //- rjf: unit vmap RDI_PROC RDIM_BakeSectionList rdim_bake_unit_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params); @@ -1210,6 +1285,9 @@ RDI_PROC RDIM_BakeSectionList rdim_bake_unit_vmap_section_list_from_params(RDIM_ //- rjf: source files RDI_PROC RDIM_BakeSectionList rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params); +//- rjf: line tables +RDI_PROC RDIM_BakeSectionList rdim_bake_line_table_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params); + //- rjf: type nodes RDI_PROC RDIM_BakeSectionList rdim_bake_type_node_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeParams *params); diff --git a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c index 26d043cd..227a72e0 100644 --- a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c +++ b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c @@ -162,7 +162,7 @@ internal TS_TASK_FUNCTION_DEF(p2b_dump_proc_chunk_task__entry_point) { // rjf: unpack unit line info P2B_BakeUnitOut *bake_unit_out = in->bake_units_out[unit_idx]; - RDI_ParsedLineInfo line_info = {bake_unit_out->unit_line_voffs, bake_unit_out->unit_lines, 0, bake_unit_out->unit_line_count, 0}; + RDI_ParsedLineTable line_info = {bake_unit_out->unit_line_voffs, bake_unit_out->unit_lines, 0, bake_unit_out->unit_line_count, 0}; for(U64 voff = voff_range.min, last_voff = 0; voff < voff_range.max && voff > last_voff;) { diff --git a/src/rdi_dump/rdi_dump.c b/src/rdi_dump/rdi_dump.c index efa88363..bad5b231 100644 --- a/src/rdi_dump/rdi_dump.c +++ b/src/rdi_dump/rdi_dump.c @@ -92,61 +92,40 @@ rdi_string_from_local_kind(RDI_LocalKind v) //~ rjf: RDI Flags -> String Functions 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 ")); - } +rdi_stringize_binary_section_flags(Arena *arena, String8List *out, RDI_BinarySectionFlags flags) +{ + if(flags == 0) { str8_list_push(arena, out, str8_lit("0")); } +#define X(name) if(flags & RDI_BinarySectionFlag_##name) { str8_list_push(arena, out, str8_lit(#name " ")); } + RDI_BinarySectionFlags_XList; +#undef X } 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 ")); - } + RDI_TypeModifierFlags flags) +{ + if(flags == 0) { str8_list_push(arena, out, str8_lit("0")); } +#define X(name) if(flags & RDI_TypeModifierFlag_##name) { str8_list_push(arena, out, str8_lit(#name " ")); } + RDI_TypeModifierFlags_XList; +#undef X } internal void -rdi_stringize_udt_flags(Arena *arena, String8List *out, - RDI_UDTFlags flags){ - if (flags == 0){ - str8_list_push(arena, out, str8_lit("0")); - } - if (flags & RDI_UDTFlag_EnumMembers){ - str8_list_push(arena, out, str8_lit("EnumMembers ")); - } +rdi_stringize_udt_flags(Arena *arena, String8List *out, RDI_UDTFlags flags) +{ + if(flags == 0) { str8_list_push(arena, out, str8_lit("0")); } +#define X(name) if(flags & RDI_UDTFlag_##name) { str8_list_push(arena, out, str8_lit(#name " ")); } + RDI_UDTFlags_XList; +#undef X } 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 ")); - } +rdi_stringize_link_flags(Arena *arena, String8List *out, RDI_LinkFlags flags) +{ + if(flags == 0) { str8_list_push(arena, out, str8_lit("0")); } +#define X(name) if(flags & RDI_LinkFlag_##name) { str8_list_push(arena, out, str8_lit(#name " ")); } + RDI_LinkFlags_XList; +#undef X } //////////////////////////////// @@ -155,11 +134,12 @@ rdi_stringize_link_flags(Arena *arena, String8List *out, RDI_LinkFlags flags){ global char rdi_stringize_spaces[] = " "; internal void -rdi_stringize_data_sections(Arena *arena, String8List *out, RDI_Parsed *parsed, - U32 indent_level){ +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){ + 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, @@ -168,64 +148,54 @@ rdi_stringize_data_sections(Arena *arena, String8List *out, RDI_Parsed *parsed, } internal void -rdi_stringize_top_level_info(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_TopLevelInfo *tli, U32 indent_level){ +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->arch); 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, "%.*sarch=%.*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); + str8_list_pushf(arena, out, "%.*sarch=%.*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){ +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, "%.*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); + 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){ +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){ + 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{ + 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;){ + for(U32 child = file_path->first_child; child != 0;) + { // get node for child RDI_FilePathNode *child_node = 0; if (child < bundle->file_path_count){ @@ -244,8 +214,8 @@ rdi_stringize_file_path(Arena *arena, String8List *out, RDI_Parsed *parsed, } internal void -rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_SourceFile *source_file, U32 indent_level){ +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); @@ -258,32 +228,37 @@ rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *parsed, // 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){ + 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){ + if(line_num > 0) + { U32 x = line_num; - for (;;){ + for(;;) + { x /= 10; - if (x == 0){ + if(x == 0) + { break; } digit_count += 1; } } - str8_list_pushf(arena, out, "%.*s %u: ", - indent_level, rdi_stringize_spaces, line_num); + 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){ + for(U32 j = first; j < opl; j += 1) + { + if(j == first) + { str8_list_pushf(arena, out, "0x%08x\n", line_map.voffs[j]); } - else{ + else + { str8_list_pushf(arena, out, "%.*s0x%08x\n", indent_level + digit_count + 3, rdi_stringize_spaces, line_map.voffs[j]); @@ -293,55 +268,32 @@ rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *parsed, } 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); +rdi_stringize_line_table(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_LineTable *line_table, U32 indent_level) +{ + // rjf: parse line table + RDI_ParsedLineTable parsed_line_table = {0}; + rdi_parsed_from_line_table(parsed, line_table, &parsed_line_table); - 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 + // rjf: stringize lines 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; + for(U32 i = 0; i < parsed_line_table.count; i += 1) + { + U64 first = parsed_line_table.voffs[i]; + U64 opl = parsed_line_table.voffs[i + 1]; + RDI_Line *line = parsed_line_table.lines + i; RDI_Column *col = 0; - if (i < line_info.col_count){ - col = line_info.cols + i; + if(i < parsed_line_table.col_count) + { + col = parsed_line_table.cols + i; } - - if (col == 0){ + 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{ + 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, @@ -350,6 +302,28 @@ rdi_stringize_unit(Arena *arena, String8List *out, RDI_Parsed *parsed, } } +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)); + + str8_list_pushf(arena, out, "%.*sline_table_idx=%u\n", indent_level, rdi_stringize_spaces, unit->line_table_idx); +} + internal void rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_TypeNode *type, U32 indent_level){ diff --git a/src/rdi_dump/rdi_dump.h b/src/rdi_dump/rdi_dump.h index 69eb49d3..76ce1d25 100644 --- a/src/rdi_dump/rdi_dump.h +++ b/src/rdi_dump/rdi_dump.h @@ -64,6 +64,7 @@ internal void rdi_stringize_top_level_info(Arena *arena, String8List *out, RDI_P 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_line_table(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_LineTable *line_table, 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); diff --git a/src/rdi_dump/rdi_dump_main.c b/src/rdi_dump/rdi_dump_main.c index 20f77361..1b87b572 100644 --- a/src/rdi_dump/rdi_dump_main.c +++ b/src/rdi_dump/rdi_dump_main.c @@ -53,18 +53,19 @@ entry_point(CmdLine *cmd_line) 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), - DumpFlag_Strings = (1<<16), + DumpFlag_LineTables = (1<<5), + DumpFlag_Units = (1<<6), + DumpFlag_UnitVMap = (1<<7), + DumpFlag_TypeNodes = (1<<8), + DumpFlag_UDTs = (1<<9), + DumpFlag_GlobalVariables = (1<<10), + DumpFlag_GlobalVMap = (1<<11), + DumpFlag_ThreadVariables = (1<<12), + DumpFlag_Procedures = (1<<13), + DumpFlag_Scopes = (1<<14), + DumpFlag_ScopeVMap = (1<<15), + DumpFlag_NameMaps = (1<<16), + DumpFlag_Strings = (1<<17), }; String8 input_name = {0}; DumpFlags dump_flags = (U32)0xffffffff; @@ -86,6 +87,7 @@ entry_point(CmdLine *cmd_line) 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("line_tables"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_LineTables; } 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; } @@ -222,6 +224,20 @@ entry_point(CmdLine *cmd_line) str8_list_push(arena, &dump, str8_lit("\n")); } + //- rjf: LINE TABLES + if(dump_flags & DumpFlag_LineTables) + { + str8_list_pushf(arena, &dump, "# LINE TABLES\n"); + RDI_LineTable *ptr = rdi->line_tables; + for(U32 i = 0; i < rdi->line_tables_count; i += 1, ptr += 1) + { + str8_list_pushf(arena, &dump, " line_table[%u]:\n", i); + rdi_stringize_line_table(arena, &dump, rdi, 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) { diff --git a/src/rdi_format/rdi_format.mdesk b/src/rdi_format/rdi_format.mdesk index 578b5a93..6543da59 100644 --- a/src/rdi_format/rdi_format.mdesk +++ b/src/rdi_format/rdi_format.mdesk @@ -55,7 +55,7 @@ ""; "// \"raddbg\0\0\""; "#define RDI_MAGIC_CONSTANT 0x0000676264646172"; - "#define RDI_ENCODING_VERSION 1"; + "#define RDI_ENCODING_VERSION 2"; ""; "////////////////////////////////////////////////////////////////"; "//~ Format Types & Functions"; @@ -97,6 +97,11 @@ RDI_HeaderMemberTable: {data_section_count RDI_U32 ""} } +@xlist RDI_Header_XList: +{ + @expand(RDI_HeaderMemberTable a) `$(a.type), $(a.name)` +} + @struct RDI_Header: { @expand(RDI_HeaderMemberTable a) `$(a.type) $(a.name)` @@ -105,8 +110,6 @@ RDI_HeaderMemberTable: //////////////////////////////// //~ rjf: Format Data Section Tables -@constant RDI_DataSectionTag_SECONDARY: 0x80000000 - @table(name value desc) RDI_DataSectionTable: { @@ -118,33 +121,35 @@ RDI_DataSectionTable: {BinarySections 0x0005 ""} {FilePathNodes 0x0006 ""} {SourceFiles 0x0007 ""} - {Units 0x0008 ""} - {UnitVmap 0x0009 ""} - {TypeNodes 0x000A ""} - {UDTs 0x000B ""} - {Members 0x000C ""} - {EnumMembers 0x000D ""} - {GlobalVariables 0x000E ""} - {GlobalVmap 0x000F ""} - {ThreadVariables 0x0010 ""} - {Procedures 0x0011 ""} - {Scopes 0x0012 ""} - {ScopeVoffData 0x0013 ""} - {ScopeVmap 0x0014 ""} - {Locals 0x0015 ""} - {LocationBlocks 0x0016 ""} - {LocationData 0x0017 ""} - {NameMaps 0x0018 ""} - {PRIMARY_COUNT 0x0019 ""} + {LineTables 0x0008 ""} + {LineInfoVoffs 0x0009 ""} + {LineInfoLines 0x000A ""} + {LineInfoColumns 0x000B ""} + {Units 0x000C ""} + {UnitVmap 0x000D ""} + {TypeNodes 0x000E ""} + {UDTs 0x000F ""} + {Members 0x0010 ""} + {EnumMembers 0x0011 ""} + {GlobalVariables 0x0012 ""} + {GlobalVmap 0x0013 ""} + {ThreadVariables 0x0014 ""} + {Procedures 0x0015 ""} + {Scopes 0x0016 ""} + {ScopeVoffData 0x0017 ""} + {ScopeVmap 0x0018 ""} + {InlineSites 0x0019 ""} + {Locals 0x001A ""} + {LocationBlocks 0x001B ""} + {LocationData 0x001C ""} + {NameMaps 0x001D ""} + {PRIMARY_COUNT 0x001E ""} {SECONDARY 0x80000000 ""} - {LineInfoVoffs `RDI_DataSectionTag_SECONDARY|0x0001` ""} - {LineInfoData `RDI_DataSectionTag_SECONDARY|0x0002` ""} - {LineInfoColumns `RDI_DataSectionTag_SECONDARY|0x0003` ""} - {LineMapNumbers `RDI_DataSectionTag_SECONDARY|0x0004` ""} - {LineMapRanges `RDI_DataSectionTag_SECONDARY|0x0005` ""} - {LineMapVoffs `RDI_DataSectionTag_SECONDARY|0x0006` ""} - {NameMapBuckets `RDI_DataSectionTag_SECONDARY|0x0007` ""} - {NameMapNodes `RDI_DataSectionTag_SECONDARY|0x0008` ""} + {LineMapNumbers `RDI_DataSectionTag_SECONDARY|0x0001` ""} + {LineMapRanges `RDI_DataSectionTag_SECONDARY|0x0002` ""} + {LineMapVoffs `RDI_DataSectionTag_SECONDARY|0x0003` ""} + {NameMapBuckets `RDI_DataSectionTag_SECONDARY|0x0004` ""} + {NameMapNodes `RDI_DataSectionTag_SECONDARY|0x0005` ""} } @table(name value) @@ -184,6 +189,11 @@ RDI_DataSectionMemberTable: @expand(RDI_DataSectionEncodingTable a) `$(a.name)`; } +@xlist RDI_DataSection_XList: +{ + @expand(RDI_DataSectionMemberTable a) `$(a.type), $(a.name)` +} + @struct RDI_DataSection: { @expand(RDI_DataSectionMemberTable a) `$(a.type) $(a.name)` @@ -199,6 +209,11 @@ RDI_VMapEntryMemberTable: {idx RDI_U64 ""} } +@xlist RDI_VMapEntry_XList: +{ + @expand(RDI_VMapEntryMemberTable a) `$(a.type), $(a.name)` +} + @struct RDI_VMapEntry: { @expand(RDI_VMapEntryMemberTable a) `$(a.type) $(a.name)` @@ -397,6 +412,11 @@ RDI_TopLevelInfoMemberTable: {voff_max RDI_U64 ""} } +@xlist RDI_TopLevelInfo_XList: +{ + @expand(RDI_TopLevelInfoMemberTable a) `$(a.type), $(a.name)` +} + @struct RDI_TopLevelInfo: { @expand(RDI_TopLevelInfoMemberTable a) `$(a.type) $(a.name)` @@ -431,7 +451,12 @@ RDI_BinarySectionMemberTable: @xlist RDI_BinarySectionFlags_XList: { - @expand(RDI_ArchTable a) `$(a.name)`; + @expand(RDI_BinarySectionFlagTable a) `$(a.name)`; +} + +@xlist RDI_BinarySection_XList: +{ + @expand(RDI_BinarySectionMemberTable a) `$(a.type), $(a.name)` } @struct RDI_BinarySection: @@ -467,6 +492,16 @@ RDI_SourceFileMemberTable: {line_map_voff_data_idx RDI_U32 ""} // U64[...] (idx by line_map_range_data) } +@xlist RDI_FilePathNode_XList: +{ + @expand(RDI_FilePathNodeMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_SourceFile_XList: +{ + @expand(RDI_SourceFileMemberTable a) `$(a.type), $(a.name)` +} + @struct RDI_FilePathNode: { @expand(RDI_FilePathNodeMemberTable a) `$(a.type) $(a.name)` @@ -490,13 +525,22 @@ RDI_UnitMemberTable: {archive_file_path_node RDI_U32 ""} {build_path_node RDI_U32 ""} {language RDI_Language ""} - // usage of line info to go from voff to file & line number: - // (line_info_voffs * voff) -> (nil + index) - // (line_info_data * index) -> (RDI_Line = (file_idx * line_number)) - {line_info_voffs_data_idx RDI_U32 ""} // U64[line_info_count + 1] (sorted ranges) - {line_info_data_idx RDI_U32 ""} // RDI_Line[line_info_count] - {line_info_col_data_idx RDI_U32 ""} // RDI_Col[line_info_count] - {line_info_count RDI_U32 ""} + {line_table_idx RDI_U32 ""} +} + +/* // TODO(rjf): @inline_sites +// usage of line info to go from voff to file & line number: +// (line_info_voffs * voff) -> (nil + index) +// (line_info_data * index) -> (RDI_Line = (file_idx * line_number)) +{line_info_voffs_data_idx RDI_U32 ""} // U64[line_info_count + 1] (sorted ranges) +{line_info_data_idx RDI_U32 ""} // RDI_Line[line_info_count] +{line_info_col_data_idx RDI_U32 ""} // RDI_Col[line_info_count] +{line_info_count RDI_U32 ""} +*/ + +@xlist RDI_Unit_XList: +{ + @expand(RDI_UnitMemberTable a) `$(a.type), $(a.name)` } @struct RDI_Unit: @@ -531,6 +575,21 @@ RDI_ColumnMemberTable: {col_opl RDI_U16 ""} } +@xlist RDI_LineTable_XList: +{ + @expand(RDI_LineTableMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_Line_XList: +{ + @expand(RDI_LineMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_Column_XList: +{ + @expand(RDI_ColumnMemberTable a) `$(a.type), $(a.name)` +} + @struct RDI_LineTable: { @expand(RDI_LineTableMemberTable a) `$(a.type) $(a.name)` @@ -722,6 +781,11 @@ RDI_EnumMemberTable: @expand(RDI_TypeModifierFlagTable a) `$(a.name)`; } +@xlist RDI_TypeNode_XList: +{ + @expand(RDI_TypeNodeMemberTable a) `$(a.type_lhs), $(a.name)` +} + @struct RDI_TypeNode: { @expand(RDI_TypeNodeMemberTable a) `$(a.type_lhs) $(a.name)$(a.type_rhs)` @@ -771,11 +835,16 @@ RDI_EnumMemberTable: @expand(RDI_UDTFlagTable a) `$(a.name .. =>20) = $(a.value)` } -@xlist RDI_UDTFlag_XList: +@xlist RDI_UDTFlags_XList: { @expand(RDI_UDTFlagTable a) `$(a.name)`; } +@xlist RDI_UDT_XList: +{ + @expand(RDI_UDTMemberTable a) `$(a.type), $(a.name)` +} + @struct RDI_UDT: { @expand(RDI_UDTMemberTable a) `$(a.type) $(a.name)` @@ -791,6 +860,16 @@ RDI_EnumMemberTable: @expand(RDI_MemberKindTable a) `$(a.name)`; } +@xlist RDI_Member_XList: +{ + @expand(RDI_MemberMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_EnumMember_XList: +{ + @expand(RDI_EnumMemberTable a) `$(a.type), $(a.name)` +} + @struct RDI_Member: { @expand(RDI_MemberMemberTable a) `$(a.type) $(a.name)` @@ -804,6 +883,8 @@ RDI_EnumMemberTable: //////////////////////////////// //~ rjf: Symbol Info Tables +//- rjf: tables + @table(name value) RDI_LinkFlagTable: { @@ -930,6 +1011,8 @@ RDI_LocationRegMemberTable: {reg_code RDI_RegCode } } +//- rjf: enums + @enum(RDI_U32) RDI_LinkFlags: { @expand(RDI_LinkFlagTable a) `$(a.name .. =>20) = $(a.value)` @@ -945,6 +1028,8 @@ RDI_LocationRegMemberTable: @expand(RDI_LocationKindTable a) `$(a.name .. =>20) = $(a.value)` } +//- rjf: xlists + @xlist RDI_LinkFlags_XList: { @expand(RDI_LinkFlagTable a) `$(a.name)`; @@ -960,6 +1045,58 @@ RDI_LocationRegMemberTable: @expand(RDI_LocationKindTable a) `$(a.name)`; } +@xlist RDI_GlobalVariable_XList: +{ + @expand(RDI_GlobalVariableMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_ThreadVariable_XList: +{ + @expand(RDI_ThreadVariableMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_Procedure_XList: +{ + @expand(RDI_ProcedureMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_Scope_XList: +{ + @expand(RDI_ScopeMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_InlineSite_XList: +{ + @expand(RDI_InlineSiteMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_Local_XList: +{ + @expand(RDI_LocalMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_LocationBlock_XList: +{ + @expand(RDI_LocationBlockMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_LocationBytecodeStream_XList: +{ + @expand(RDI_LocationBytecodeStreamMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_LocationRegPlusU16_XList: +{ + @expand(RDI_LocationRegPlusU16MemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_LocationReg_XList: +{ + @expand(RDI_LocationRegMemberTable a) `$(a.type), $(a.name)` +} + +//- rjf: structs + @struct RDI_GlobalVariable: { @expand(RDI_GlobalVariableMemberTable a) `$(a.type) $(a.name)` @@ -1194,6 +1331,21 @@ RDI_NameMapNodeMemberTable: @expand(RDI_NameMapKindTable a) `$(a.name)`; } +@xlist RDI_NameMap_XList: +{ + @expand(RDI_NameMapMemberTable a) `$(a.type), $(a.val)` +} + +@xlist RDI_NameMapBucket_XList: +{ + @expand(RDI_NameMapBucketMemberTable a) `$(a.type), $(a.val)` +} + +@xlist RDI_NameMapNode_XList: +{ + @expand(RDI_NameMapNodeMemberTable a) `$(a.type), $(a.val)` +} + @struct RDI_NameMap: { @expand(RDI_NameMapMemberTable a) `$(a.type) $(a.val)` diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index 9c5632b4..4321dd20 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -580,7 +580,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) src_file_map.slots_count = 65536; src_file_map.slots = push_array(scratch.arena, P2R_SrcFileNode *, src_file_map.slots_count); - //- rjf: pass 1: fill basic per-unit info & line info + //- rjf: pass 1: build per-unit info & per-unit line tables for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) { PDB_CompUnit *pdb_unit = in->comp_units->units[comp_unit_idx]; @@ -606,6 +606,61 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) MemoryZeroStruct(&obj_name); } + //- rjf: build this unit's line table + RDIM_LineTable *line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 256); + if(pdb_unit_c13->first_sub_section != 0) + { + for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; + node != 0; + node = node->next) + { + if(node->kind == CV_C13_SubSectionKind_Lines) + { + for(CV_C13LinesParsedNode *lines_n = node->lines_first; + lines_n != 0; + lines_n = lines_n->next) + { + CV_C13LinesParsed *lines = &lines_n->v; + + // rjf: file name -> normalized file path + String8 file_path = lines->file_name; + String8 file_path_normalized = lower_from_str8(scratch.arena, str8_skip_chop_whitespace(file_path)); + for(U64 idx = 0; idx < file_path_normalized.size; idx += 1) + { + if(file_path_normalized.str[idx] == '\\') + { + file_path_normalized.str[idx] = '/'; + } + } + + // rjf: normalized file path -> source file node + U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); + U64 src_file_slot = file_path_normalized_hash%src_file_map.slots_count; + P2R_SrcFileNode *src_file_node = 0; + for(P2R_SrcFileNode *n = src_file_map.slots[src_file_slot]; n != 0; n = n->next) + { + if(str8_match(n->src_file->normal_full_path, file_path_normalized, 0)) + { + src_file_node = n; + break; + } + } + if(src_file_node == 0) + { + src_file_node = push_array(scratch.arena, P2R_SrcFileNode, 1); + SLLStackPush(src_file_map.slots[src_file_slot], src_file_node); + src_file_node->src_file = rdim_src_file_chunk_list_push(arena, &out->src_files, 4096); + src_file_node->src_file->normal_full_path = push_str8_copy(arena, file_path_normalized); + } + + // rjf: push sequence into both line table & source file's line map + RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, lines->voffs, lines->line_nums, lines->col_nums, lines->line_count); + rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); + } + } + } + } + //- rjf: build unit RDIM_Unit *dst_unit = rdim_unit_chunk_list_push(arena, &out->units, units_chunk_cap); dst_unit->unit_name = unit_name; @@ -613,62 +668,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) dst_unit->object_file = obj_name; dst_unit->archive_file = pdb_unit->group_name; dst_unit->language = p2r_rdi_language_from_cv_language(pdb_unit_sym->info.language); - - //- rjf: fill unit line info - for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; - node != 0; - node = node->next) - { - if(node->kind == CV_C13_SubSectionKind_Lines) - { - for(CV_C13LinesParsedNode *lines_n = node->lines_first; - lines_n != 0; - lines_n = lines_n->next) - { - CV_C13LinesParsed *lines = &lines_n->v; - - // rjf: file name -> normalized file path - String8 file_path = lines->file_name; - String8 file_path_normalized = lower_from_str8(scratch.arena, str8_skip_chop_whitespace(file_path)); - for(U64 idx = 0; idx < file_path_normalized.size; idx += 1) - { - if(file_path_normalized.str[idx] == '\\') - { - file_path_normalized.str[idx] = '/'; - } - } - - // rjf: normalized file path -> source file node - U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); - U64 src_file_slot = file_path_normalized_hash%src_file_map.slots_count; - P2R_SrcFileNode *src_file_node = 0; - for(P2R_SrcFileNode *n = src_file_map.slots[src_file_slot]; n != 0; n = n->next) - { - if(str8_match(n->src_file->normal_full_path, file_path_normalized, 0)) - { - src_file_node = n; - break; - } - } - if(src_file_node == 0) - { - src_file_node = push_array(scratch.arena, P2R_SrcFileNode, 1); - SLLStackPush(src_file_map.slots[src_file_slot], src_file_node); - src_file_node->src_file = rdim_src_file_chunk_list_push(arena, &out->src_files, 4096); - src_file_node->src_file->normal_full_path = push_str8_copy(arena, file_path_normalized); - } - - // rjf: build sequence - RDIM_LineSequence *seq = rdim_line_sequence_list_push(arena, &dst_unit->line_sequences); - rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); - seq->src_file = src_file_node->src_file; - seq->voffs = lines->voffs; - seq->line_nums = lines->line_nums; - seq->col_nums = lines->col_nums; - seq->line_count = lines->line_count; - } - } - } + dst_unit->line_table = line_table; } //- rjf: pass 2: build per-unit voff ranges from comp unit contributions table @@ -3498,15 +3498,17 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) } ////////////////////////////////////////////////////////////// - //- rjf: join unit conversion & src file tasks + //- rjf: join unit conversion & src file & line table tasks // RDIM_UnitChunkList all_units = {0}; RDIM_SrcFileChunkList all_src_files = {0}; + RDIM_LineTableChunkList all_line_tables = {0}; ProfScope("join unit conversion & src file tasks") { P2R_UnitConvertOut *out = ts_join_struct(unit_convert_ticket, max_U64, P2R_UnitConvertOut); all_units = out->units; all_src_files = out->src_files; + all_line_tables = out->line_tables; } ////////////////////////////////////////////////////////////// @@ -3530,6 +3532,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) out->bake_params.types = all_types; out->bake_params.udts = all_udts; out->bake_params.src_files = all_src_files; + out->bake_params.line_tables = all_line_tables; out->bake_params.global_variables = all_global_variables; out->bake_params.thread_variables = all_thread_variables; out->bake_params.procedures = all_procedures; @@ -3619,6 +3622,14 @@ internal TS_TASK_FUNCTION_DEF(p2r_bake_scopes_strings_task__entry_point) return 0; } +internal TS_TASK_FUNCTION_DEF(p2r_bake_line_tables_task__entry_point) +{ + P2R_BakeLineTablesIn *in = (P2R_BakeLineTablesIn *)p; + RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); + ProfScope("bake line tables") *s = rdim_bake_line_table_section_list_from_params(arena, in->params); + return s; +} + #undef p2r_make_string_map_if_needed //- rjf: bake string map joining @@ -3688,19 +3699,11 @@ internal TS_TASK_FUNCTION_DEF(p2r_build_bake_name_map_task__entry_point) //- rjf: pass 2: string-map-dependent debug info stream builds -internal TS_TASK_FUNCTION_DEF(p2r_bake_units_top_level_task__entry_point) +internal TS_TASK_FUNCTION_DEF(p2r_bake_units_task__entry_point) { P2R_BakeUnitsTopLevelIn *in = (P2R_BakeUnitsTopLevelIn *)p; RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake units") *s = rdim_bake_unit_top_level_section_list_from_params(arena, in->strings, in->path_tree, in->params); - return s; -} - -internal TS_TASK_FUNCTION_DEF(p2r_bake_unit_task__entry_point) -{ - P2R_BakeUnitIn *in = (P2R_BakeUnitIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake unit") *s = rdim_bake_section_list_from_unit(arena, in->unit); + ProfScope("bake units") *s = rdim_bake_unit_section_list_from_params(arena, in->strings, in->path_tree, in->params); return s; } @@ -3828,6 +3831,14 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) RDIM_BakeParams *params = &in->bake_params; RDIM_BakeSectionList sections = {0}; + //- rjf: kick off line tables baking + TS_Ticket bake_line_tables_ticket = {0}; + { + P2R_BakeLineTablesIn *in = push_array(scratch.arena, P2R_BakeLineTablesIn, 1); + in->params = params; + bake_line_tables_ticket = ts_kickoff(p2r_bake_line_tables_task__entry_point, 0, in); + } + //- rjf: build interned path tree RDIM_BakePathTree *path_tree = 0; ProfScope("build interned path tree") @@ -3835,21 +3846,6 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) path_tree = rdim_bake_path_tree_from_params(arena, params); } - //- rjf: kick off per-unit baking tasks - P2R_BakeUnitIn *bake_units_in = push_array(scratch.arena, P2R_BakeUnitIn, params->units.total_count); - TS_Ticket *bake_units_tickets = push_array(scratch.arena, TS_Ticket, params->units.total_count); - { - U64 idx = 0; - for(RDIM_UnitChunkNode *n = params->units.first; n != 0; n = n->next) - { - for(U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, idx += 1) - { - bake_units_in[idx].unit = &n->v[chunk_idx]; - bake_units_tickets[idx] = ts_kickoff(p2r_bake_unit_task__entry_point, 0, &bake_units_in[idx]); - } - } - } - //- rjf: kick off string map building tasks RDIM_BakeStringMapTopology bake_string_map_topology = {(params->procedures.total_count*1 + params->global_variables.total_count*1 + @@ -4070,7 +4066,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) //- rjf: kick off pass 2 tasks P2R_BakeUnitsTopLevelIn bake_units_top_level_in = {&bake_strings, path_tree, params}; - TS_Ticket bake_units_top_level_ticket = ts_kickoff(p2r_bake_units_top_level_task__entry_point, 0, &bake_units_top_level_in); + TS_Ticket bake_units_top_level_ticket = ts_kickoff(p2r_bake_units_task__entry_point, 0, &bake_units_top_level_in); P2R_BakeUnitVMapIn bake_unit_vmap_in = {params}; TS_Ticket bake_unit_vmap_ticket = ts_kickoff(p2r_bake_unit_vmap_task__entry_point, 0, &bake_unit_vmap_in); P2R_BakeSrcFilesIn bake_src_files_in = {&bake_strings, path_tree, params}; @@ -4265,14 +4261,11 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) rdim_bake_section_list_concat_in_place(§ions, s); } - //- rjf: join per-unit bakes - ProfScope("units") + //- rjf: join line tables + ProfScope("line tables") { - for(U64 idx = 0; idx < params->units.total_count; idx += 1) - { - RDIM_BakeSectionList *s = ts_join_struct(bake_units_tickets[idx], max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } + RDIM_BakeSectionList *s = ts_join_struct(bake_line_tables_ticket, max_U64, RDIM_BakeSectionList); + rdim_bake_section_list_concat_in_place(§ions, s); } //- rjf: fill & return diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index 27b9ff39..80f74585 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -178,6 +178,7 @@ struct P2R_UnitConvertOut { RDIM_UnitChunkList units; RDIM_SrcFileChunkList src_files; + RDIM_LineTableChunkList line_tables; }; //- rjf: link name map building tasks @@ -262,6 +263,14 @@ struct P2R_SymbolStreamConvertOut //////////////////////////////// //~ rjf: Baking Task Types +//- rjf: line table baking task types + +typedef struct P2R_BakeLineTablesIn P2R_BakeLineTablesIn; +struct P2R_BakeLineTablesIn +{ + RDIM_BakeParams *params; +}; + //- rjf: string map baking task types typedef struct P2R_BakeSrcFilesStringsIn P2R_BakeSrcFilesStringsIn; @@ -586,6 +595,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_bake_types_strings_task__entry_point); internal TS_TASK_FUNCTION_DEF(p2r_bake_udts_strings_task__entry_point); internal TS_TASK_FUNCTION_DEF(p2r_bake_symbols_strings_task__entry_point); internal TS_TASK_FUNCTION_DEF(p2r_bake_scopes_strings_task__entry_point); +internal TS_TASK_FUNCTION_DEF(p2r_bake_line_tables_task__entry_point); //- rjf: bake string map joining internal TS_TASK_FUNCTION_DEF(p2r_bake_string_map_join_task__entry_point); @@ -597,8 +607,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_bake_string_map_sort_task__entry_point); internal TS_TASK_FUNCTION_DEF(p2r_build_bake_name_map_task__entry_point); //- rjf: pass 2: string-map-dependent debug info stream builds -internal TS_TASK_FUNCTION_DEF(p2r_bake_units_top_level_task__entry_point); -internal TS_TASK_FUNCTION_DEF(p2r_bake_unit_task__entry_point); +internal TS_TASK_FUNCTION_DEF(p2r_bake_units_task__entry_point); internal TS_TASK_FUNCTION_DEF(p2r_bake_unit_vmap_task__entry_point); internal TS_TASK_FUNCTION_DEF(p2r_bake_src_files_task__entry_point); internal TS_TASK_FUNCTION_DEF(p2r_bake_udts_task__entry_point); diff --git a/src/task_system/task_system.c b/src/task_system/task_system.c index 98571094..aefbda47 100644 --- a/src/task_system/task_system.c +++ b/src/task_system/task_system.c @@ -64,7 +64,7 @@ ts_thread_count(void) internal TS_Ticket ts_kickoff(TS_TaskFunctionType *entry_point, Arena **optional_arena_ptr, void *p) { - // rjf: obtain number & slot/stripefor next artifact + // rjf: obtain number & slot/stripe for next artifact U64 artifact_num = ins_atomic_u64_inc_eval(&ts_shared->artifact_num_gen); U64 slot_idx = artifact_num%ts_shared->artifact_slots_count; U64 stripe_idx = slot_idx%ts_shared->artifact_stripes_count; From 063975693dc695ec908c5cfa2515ce6ae6323c81 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 3 Jun 2024 16:25:37 -0700 Subject: [PATCH 05/44] do not broadcast unnecessarily in task system kickoff --- project.4coder | 2 +- src/demon/win32/demon_core_win32.c | 6 ++- src/task_system/task_system.c | 67 +++++++++++++++++------------- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/project.4coder b/project.4coder index a9e4873a..08bf68db 100644 --- a/project.4coder +++ b/project.4coder @@ -74,7 +74,7 @@ commands = }, .rjf_f4 = { - .win = "build rdi_from_pdb release telemetry && pushd build && rdi_from_pdb.exe --exe:UnrealEditorFortnite.exe --pdb:UnrealEditorFortnite.pdb --out:UnrealEditorFortnite.rdi --capture && popd", + .win = "build rdi_from_pdb release telemetry && pushd build && rdi_from_pdb.exe --pdb:mule_main.pdb --out:mule_main.rdi --capture && popd", .linux = "", .out = "*compilation*", .footer_panel = true, diff --git a/src/demon/win32/demon_core_win32.c b/src/demon/win32/demon_core_win32.c index 14bf4c00..95433ebf 100644 --- a/src/demon/win32/demon_core_win32.c +++ b/src/demon/win32/demon_core_win32.c @@ -1588,13 +1588,17 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) } if(resume_good) { - evt_good = !!WaitForDebugEvent(&evt, INFINITE); + evt_good = !!WaitForDebugEvent(&evt, 100); if(evt_good) { dmn_w32_shared->resume_needed = 1; dmn_w32_shared->resume_pid = evt.dwProcessId; dmn_w32_shared->resume_tid = evt.dwThreadId; } + else + { + keep_going = 1; + } ins_atomic_u64_inc_eval(&dmn_w32_shared->run_gen); ins_atomic_u64_inc_eval(&dmn_w32_shared->mem_gen); ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen); diff --git a/src/task_system/task_system.c b/src/task_system/task_system.c index aefbda47..15c38a0a 100644 --- a/src/task_system/task_system.c +++ b/src/task_system/task_system.c @@ -64,6 +64,8 @@ ts_thread_count(void) internal TS_Ticket ts_kickoff(TS_TaskFunctionType *entry_point, Arena **optional_arena_ptr, void *p) { + ProfBeginFunction(); + // rjf: obtain number & slot/stripe for next artifact U64 artifact_num = ins_atomic_u64_inc_eval(&ts_shared->artifact_num_gen); U64 slot_idx = artifact_num%ts_shared->artifact_slots_count; @@ -73,51 +75,58 @@ ts_kickoff(TS_TaskFunctionType *entry_point, Arena **optional_arena_ptr, void *p // rjf: allocate artifact TS_TaskArtifact *artifact = 0; - OS_MutexScopeW(stripe->rw_mutex) + ProfScope("allocate artifact") { - artifact = stripe->free_artifact; - if(artifact != 0) + OS_MutexScopeW(stripe->rw_mutex) { - SLLStackPop(stripe->free_artifact); + artifact = stripe->free_artifact; + if(artifact != 0) + { + SLLStackPop(stripe->free_artifact); + } + else + { + artifact = push_array_no_zero(stripe->arena, TS_TaskArtifact, 1); + } + artifact->num = artifact_num; + artifact->task_is_done = 0; + artifact->result = 0; } - else - { - artifact = push_array_no_zero(stripe->arena, TS_TaskArtifact, 1); - } - artifact->num = artifact_num; - artifact->task_is_done = 0; - artifact->result = 0; } // rjf: form ticket out of artifact info TS_Ticket ticket = {artifact_num, (U64)artifact}; // rjf: push task info to task ring buffer - OS_MutexScope(ts_shared->u2t_ring_mutex) for(;;) + ProfScope("push task info to task ring buffer") { - U64 unconsumed_size = ts_shared->u2t_ring_write_pos - ts_shared->u2t_ring_read_pos; - U64 available_size = ts_shared->u2t_ring_size-unconsumed_size; - if(available_size >= sizeof(entry_point) + sizeof(p) + sizeof(ticket)) + OS_MutexScope(ts_shared->u2t_ring_mutex) for(;;) { - Arena *task_arena = 0; - if(optional_arena_ptr != 0) + U64 unconsumed_size = ts_shared->u2t_ring_write_pos - ts_shared->u2t_ring_read_pos; + U64 available_size = ts_shared->u2t_ring_size-unconsumed_size; + if(available_size >= sizeof(entry_point) + sizeof(p) + sizeof(ticket)) { - task_arena = *optional_arena_ptr; + Arena *task_arena = 0; + if(optional_arena_ptr != 0) + { + task_arena = *optional_arena_ptr; + } + ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &entry_point); + ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &task_arena); + ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &p); + ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &ticket); + if(optional_arena_ptr != 0) + { + *optional_arena_ptr = 0; + } + break; } - ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &entry_point); - ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &task_arena); - ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &p); - ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &ticket); - if(optional_arena_ptr != 0) - { - *optional_arena_ptr = 0; - } - break; + os_condition_variable_wait(ts_shared->u2t_ring_cv, ts_shared->u2t_ring_mutex, max_U64); } - os_condition_variable_wait(ts_shared->u2t_ring_cv, ts_shared->u2t_ring_mutex, max_U64); + os_condition_variable_signal(ts_shared->u2t_ring_cv); } - os_condition_variable_broadcast(ts_shared->u2t_ring_cv); + ProfEnd(); return ticket; } From f7e67a80c9ccbdd4bf085d335af680252312047b Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 3 Jun 2024 16:45:33 -0700 Subject: [PATCH 06/44] eliminate old per-unit line info code --- src/lib_rdi_make/rdi_make.c | 275 -------------------------------- src/lib_rdi_make/rdi_make.h | 4 - src/rdi_format/rdi_format.mdesk | 13 +- 3 files changed, 3 insertions(+), 289 deletions(-) diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index 63ef3e88..7d1e33cc 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -2249,281 +2249,6 @@ rdim_bake_unit_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTig return sections; } -#if 0 // TODO(rjf): @inline_sites - -RDI_PROC RDIM_BakeSectionList -rdim_bake_section_list_from_unit(RDIM_Arena *arena, RDIM_Unit *unit) -{ - RDIM_BakeSectionList sections = {0}; - - //////////////////////// - //- rjf: produce combined unit line info - // - RDI_U64 *unit_voffs = 0; - RDI_Line *unit_lines = 0; - RDI_U16 *unit_cols = 0; - RDI_U32 unit_line_count = 0; - RDIM_ProfScope("produce combined unit line info") - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - //- rjf: gather up all line info into two arrays: - // - // [1] keys: sortable array; pairs voffs with line info records; null records are sequence enders - // [2] recs: contains all the source coordinates for a range of voffs - // - typedef struct RDIM_LineRec RDIM_LineRec; - struct RDIM_LineRec - { - RDI_U32 file_id; - RDI_U32 line_num; - RDI_U16 col_first; - RDI_U16 col_opl; - }; - RDI_U64 line_count = 0; - RDI_U64 seq_count = 0; - for(RDIM_LineSequenceNode *seq_n = unit->line_sequences.first; seq_n != 0; seq_n = seq_n->next) - { - seq_count += 1; - line_count += seq_n->v.line_count; - } - RDI_U64 key_count = line_count + seq_count; - RDIM_SortKey *line_keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, key_count); - RDIM_LineRec *line_recs = rdim_push_array_no_zero(scratch.arena, RDIM_LineRec, line_count); - { - RDIM_SortKey *key_ptr = line_keys; - RDIM_LineRec *rec_ptr = line_recs; - for(RDIM_LineSequenceNode *seq_n = unit->line_sequences.first; seq_n != 0; seq_n = seq_n->next) - { - RDIM_LineSequence *seq = &seq_n->v; - for(RDI_U64 line_idx = 0; line_idx < seq->line_count; line_idx += 1) - { - key_ptr->key = seq->voffs[line_idx]; - key_ptr->val = rec_ptr; - key_ptr += 1; - rec_ptr->file_id = (RDI_U32)rdim_idx_from_src_file(seq->src_file); // TODO(rjf): @u64_to_u32 - rec_ptr->line_num = seq->line_nums[line_idx]; - if(seq->col_nums != 0) - { - rec_ptr->col_first = seq->col_nums[line_idx*2]; - rec_ptr->col_opl = seq->col_nums[line_idx*2 + 1]; - } - rec_ptr += 1; - } - key_ptr->key = seq->voffs[seq->line_count]; - key_ptr->val = 0; - key_ptr += 1; - } - } - - //- rjf: sort - RDIM_SortKey *sorted_line_keys = 0; - RDIM_ProfScope("sort") - { - sorted_line_keys = rdim_sort_key_array(scratch.arena, line_keys, key_count); - } - - // TODO(rjf): do a pass over sorted keys to make sure duplicate keys - // are sorted with null record first, and no more than one null - // record and one non-null record - - //- rjf: arrange output - RDI_U64 *arranged_voffs = rdim_push_array_no_zero(arena, RDI_U64, key_count + 1); - RDI_Line *arranged_lines = rdim_push_array_no_zero(arena, RDI_Line, key_count); - RDIM_ProfScope("arrange output") - { - for(RDI_U64 i = 0; i < key_count; i += 1) - { - arranged_voffs[i] = sorted_line_keys[i].key; - } - arranged_voffs[key_count] = ~0ull; - for(RDI_U64 i = 0; i < key_count; i += 1) - { - RDIM_LineRec *rec = (RDIM_LineRec*)sorted_line_keys[i].val; - if(rec != 0) - { - arranged_lines[i].file_idx = rec->file_id; - arranged_lines[i].line_num = rec->line_num; - } - else - { - arranged_lines[i].file_idx = 0; - arranged_lines[i].line_num = 0; - } - } - } - - //- rjf: fill output - unit_voffs = arranged_voffs; - unit_lines = arranged_lines; - unit_cols = 0; - unit_line_count = key_count; - rdim_scratch_end(scratch); - } - - //////////////////////// - //- rjf: build line info sections - // - U64 unit_idx = rdim_idx_from_unit(unit); - rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_voffs, sizeof(RDI_U64)*(unit_line_count+1), RDI_DataSectionTag_LineInfoVoffs, unit_idx); - rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_lines, sizeof(RDI_Line)*unit_line_count, RDI_DataSectionTag_LineInfoData, unit_idx); - if(unit_cols != 0) - { - rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_cols, sizeof(RDI_Column)*unit_line_count, RDI_DataSectionTag_LineInfoColumns, unit_idx); - } - - return sections; -} - -RDI_PROC RDIM_BakeSectionList -rdim_bake_unit_top_level_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params) -{ - RDIM_BakeSectionList sections = {0}; - RDI_Unit *dst_base = rdim_push_array(arena, RDI_Unit, params->units.total_count+1); - RDI_U64 dst_idx = 1; - for(RDIM_UnitChunkNode *src_n = params->units.first; src_n != 0; src_n = src_n->next) - { - for(RDI_U64 src_chunk_idx = 0; src_chunk_idx < src_n->count; src_chunk_idx += 1, dst_idx += 1) - { - RDIM_Unit *src = &src_n->v[src_chunk_idx]; - RDI_Unit *dst = &dst_base[dst_idx]; - - //////////////////////// - //- rjf: produce combined unit line info - // - RDI_U64 *unit_voffs = 0; - RDI_Line *unit_lines = 0; - RDI_U16 *unit_cols = 0; - RDI_U32 unit_line_count = 0; - RDIM_ProfScope("produce combined unit line info") - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - //- rjf: gather up all line info into two arrays: - // - // [1] keys: sortable array; pairs voffs with line info records; null records are sequence enders - // [2] recs: contains all the source coordinates for a range of voffs - // - typedef struct RDIM_LineRec RDIM_LineRec; - struct RDIM_LineRec - { - RDI_U32 file_id; - RDI_U32 line_num; - RDI_U16 col_first; - RDI_U16 col_opl; - }; - RDI_U64 line_count = 0; - RDI_U64 seq_count = 0; - for(RDIM_LineSequenceNode *seq_n = src->line_sequences.first; seq_n != 0; seq_n = seq_n->next) - { - seq_count += 1; - line_count += seq_n->v.line_count; - } - RDI_U64 key_count = line_count + seq_count; - RDIM_SortKey *line_keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, key_count); - RDIM_LineRec *line_recs = rdim_push_array_no_zero(scratch.arena, RDIM_LineRec, line_count); - { - RDIM_SortKey *key_ptr = line_keys; - RDIM_LineRec *rec_ptr = line_recs; - for(RDIM_LineSequenceNode *seq_n = src->line_sequences.first; seq_n != 0; seq_n = seq_n->next) - { - RDIM_LineSequence *seq = &seq_n->v; - for(RDI_U64 line_idx = 0; line_idx < seq->line_count; line_idx += 1) - { - key_ptr->key = seq->voffs[line_idx]; - key_ptr->val = rec_ptr; - key_ptr += 1; - rec_ptr->file_id = (RDI_U32)rdim_idx_from_src_file(seq->src_file); // TODO(rjf): @u64_to_u32 - rec_ptr->line_num = seq->line_nums[line_idx]; - if(seq->col_nums != 0) - { - rec_ptr->col_first = seq->col_nums[line_idx*2]; - rec_ptr->col_opl = seq->col_nums[line_idx*2 + 1]; - } - rec_ptr += 1; - } - key_ptr->key = seq->voffs[seq->line_count]; - key_ptr->val = 0; - key_ptr += 1; - } - } - - //- rjf: sort - RDIM_SortKey *sorted_line_keys = 0; - RDIM_ProfScope("sort") - { - sorted_line_keys = rdim_sort_key_array(scratch.arena, line_keys, key_count); - } - - // TODO(rjf): do a pass over sorted keys to make sure duplicate keys - // are sorted with null record first, and no more than one null - // record and one non-null record - - //- rjf: arrange output - RDI_U64 *arranged_voffs = rdim_push_array_no_zero(arena, RDI_U64, key_count + 1); - RDI_Line *arranged_lines = rdim_push_array_no_zero(arena, RDI_Line, key_count); - RDIM_ProfScope("arrange output") - { - for(RDI_U64 i = 0; i < key_count; i += 1) - { - arranged_voffs[i] = sorted_line_keys[i].key; - } - arranged_voffs[key_count] = ~0ull; - for(RDI_U64 i = 0; i < key_count; i += 1) - { - RDIM_LineRec *rec = (RDIM_LineRec*)sorted_line_keys[i].val; - if(rec != 0) - { - arranged_lines[i].file_idx = rec->file_id; - arranged_lines[i].line_num = rec->line_num; - } - else - { - arranged_lines[i].file_idx = 0; - arranged_lines[i].line_num = 0; - } - } - } - - //- rjf: fill output - unit_voffs = arranged_voffs; - unit_lines = arranged_lines; - unit_cols = 0; - unit_line_count = key_count; - rdim_scratch_end(scratch); - } - - //////////////////////// - //- rjf: build line info sections - // - rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_voffs, sizeof(RDI_U64)*(unit_line_count+1), RDI_DataSectionTag_LineInfoVoffs, dst_idx); - rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_lines, sizeof(RDI_Line)*unit_line_count, RDI_DataSectionTag_LineInfoData, dst_idx); - if(unit_cols != 0) - { - rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_cols, sizeof(RDI_Column)*unit_line_count, RDI_DataSectionTag_LineInfoColumns, dst_idx); - } - - //////////////////////// - //- rjf: fill output - // - dst->unit_name_string_idx = rdim_bake_idx_from_string(strings, src->unit_name); - dst->compiler_name_string_idx = rdim_bake_idx_from_string(strings, src->compiler_name); - dst->source_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->source_file); - dst->object_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->object_file); - dst->archive_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->archive_file); - dst->build_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->build_path); - dst->language = src->language; - dst->line_info_voffs_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_LineInfoVoffs, dst_idx); // TODO(rjf): @u64_to_u32 - dst->line_info_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_LineInfoData, dst_idx); // TODO(rjf): @u64_to_u32 - dst->line_info_col_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_LineInfoColumns, dst_idx); // TODO(rjf): @u64_to_u32 - } - } - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_base, sizeof(*dst_base)*dst_idx, RDI_DataSectionTag_Units, 0); - return sections; -} - -#endif - //- rjf: unit vmap RDI_PROC RDIM_BakeSectionList diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index bb993079..74178296 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -1274,10 +1274,6 @@ RDI_PROC RDIM_BakeSectionList rdim_bake_binary_section_section_list_from_params( //- rjf: units RDI_PROC RDIM_BakeSectionList rdim_bake_unit_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params); -#if 0 // TODO(rjf): @inline_sites -RDI_PROC RDIM_BakeSectionList rdim_bake_section_list_from_unit(RDIM_Arena *arena, RDIM_Unit *unit); -RDI_PROC RDIM_BakeSectionList rdim_bake_unit_top_level_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params); -#endif //- rjf: unit vmap RDI_PROC RDIM_BakeSectionList rdim_bake_unit_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params); diff --git a/src/rdi_format/rdi_format.mdesk b/src/rdi_format/rdi_format.mdesk index 6543da59..e6ae4983 100644 --- a/src/rdi_format/rdi_format.mdesk +++ b/src/rdi_format/rdi_format.mdesk @@ -528,16 +528,6 @@ RDI_UnitMemberTable: {line_table_idx RDI_U32 ""} } -/* // TODO(rjf): @inline_sites -// usage of line info to go from voff to file & line number: -// (line_info_voffs * voff) -> (nil + index) -// (line_info_data * index) -> (RDI_Line = (file_idx * line_number)) -{line_info_voffs_data_idx RDI_U32 ""} // U64[line_info_count + 1] (sorted ranges) -{line_info_data_idx RDI_U32 ""} // RDI_Line[line_info_count] -{line_info_col_data_idx RDI_U32 ""} // RDI_Col[line_info_count] -{line_info_count RDI_U32 ""} -*/ - @xlist RDI_Unit_XList: { @expand(RDI_UnitMemberTable a) `$(a.type), $(a.name)` @@ -554,6 +544,9 @@ RDI_UnitMemberTable: @table(name type desc) RDI_LineTableMemberTable: { + // usage of line info to go from voff to file & line number: + // (line_info_voffs * voff) -> (nil + index) + // (line_info_data * index) -> (RDI_Line = (file_idx * line_number)) {voffs_base_idx RDI_U32 ""} // U64[lines_count+1] (sorted ranges) {lines_base_idx RDI_U32 ""} // RDI_Line[lines_count] {cols_base_idx RDI_U32 ""} // RDI_Column[cols_count] From ebd5cf9e47c45cbd741f1d691d02cfc574124e79 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 4 Jun 2024 13:33:38 -0700 Subject: [PATCH 07/44] move per-source-file line maps to top-level sections, and move source line -> voff maps to separate top-level info table --- src/ctrl/ctrl_core.c | 5 +- src/dbgi/dbgi.h | 1 + src/df/core/df_core.c | 10 +- src/lib_rdi_format/rdi_format.h | 85 ++++++++------ src/lib_rdi_format/rdi_format_parse.c | 54 +++++---- src/lib_rdi_format/rdi_format_parse.h | 11 +- src/lib_rdi_make/rdi_make.c | 162 +++++++++++++++++--------- src/lib_rdi_make/rdi_make.h | 2 + src/rdi_dump/rdi_dump.c | 84 ++++++------- src/rdi_dump/rdi_dump.h | 1 + src/rdi_dump/rdi_dump_main.c | 49 ++++---- src/rdi_format/rdi_format.mdesk | 106 ++++++++++------- 12 files changed, 338 insertions(+), 232 deletions(-) diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 7296cae6..a9985895 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -2965,8 +2965,9 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_MachineID m // rjf: src_id * pt -> push { RDI_SourceFile *src = rdi_element_from_idx(rdi, source_files, src_id); - RDI_ParsedLineMap line_map = {0}; - rdi_line_map_from_source_file(rdi, src, &line_map); + RDI_SourceLineMap *src_line_map = rdi_element_from_idx(rdi, source_line_maps, src->source_line_map_idx); + RDI_ParsedSourceLineMap line_map = {0}; + rdi_parsed_from_source_line_map(rdi, src_line_map, &line_map); U32 voff_count = 0; U64 *voffs = rdi_line_voffs_from_num(&line_map, pt.line, &voff_count); for(U32 i = 0; i < voff_count; i += 1) diff --git a/src/dbgi/dbgi.h b/src/dbgi/dbgi.h index 0198b1ee..c3590111 100644 --- a/src/dbgi/dbgi.h +++ b/src/dbgi/dbgi.h @@ -210,6 +210,7 @@ global RDI_Parsed di_rdi_parsed_nil = &rdi_file_path_node_nil, 1, &rdi_source_file_nil, 1, &rdi_line_table_nil, 1, + &rdi_source_line_map_nil, 1, &rdi_voff_nil, 1, &rdi_line_nil, 1, &rdi_column_nil, 1, diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index ae40f5e3..d094d4fa 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -3262,8 +3262,9 @@ df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entit if(good_src_id) { RDI_SourceFile *src = rdi->source_files+src_id; - RDI_ParsedLineMap line_map = {0}; - rdi_line_map_from_source_file(rdi, src, &line_map); + RDI_SourceLineMap *src_line_map = rdi_element_from_idx(rdi, source_line_maps, src->source_line_map_idx); + RDI_ParsedSourceLineMap line_map = {0}; + rdi_parsed_from_source_line_map(rdi, src_line_map, &line_map); U64 line_idx = 0; for(S64 line_num = line_num_range.min; line_num <= line_num_range.max; @@ -3950,8 +3951,9 @@ df_eval_parse_ctx_from_src_loc(DI_Scope *scope, DF_Entity *file, TxtPt pt) if(good_src_id) { RDI_SourceFile *src = rdi->source_files+src_id; - RDI_ParsedLineMap line_map = {0}; - rdi_line_map_from_source_file(rdi, src, &line_map); + RDI_SourceLineMap *src_line_map = rdi_element_from_idx(rdi, source_line_maps, src->source_line_map_idx); + RDI_ParsedSourceLineMap line_map = {0}; + rdi_parsed_from_source_line_map(rdi, src_line_map, &line_map); U32 voff_count = 0; U64 *voffs = rdi_line_voffs_from_num(&line_map, (U32)pt.line, &voff_count); for(U64 idx = 0; idx < voff_count; idx += 1) diff --git a/src/lib_rdi_format/rdi_format.h b/src/lib_rdi_format/rdi_format.h index 9ef88fcc..298a54c5 100644 --- a/src/lib_rdi_format/rdi_format.h +++ b/src/lib_rdi_format/rdi_format.h @@ -45,7 +45,7 @@ typedef int64_t RDI_S64; // \"raddbg\0\0\" #define RDI_MAGIC_CONSTANT 0x0000676264646172 -#define RDI_ENCODING_VERSION 2 +#define RDI_ENCODING_VERSION 3 //////////////////////////////////////////////////////////////// //~ Format Types & Functions @@ -65,31 +65,32 @@ RDI_DataSectionTag_LineTables = 0x0008, RDI_DataSectionTag_LineInfoVoffs = 0x0009, RDI_DataSectionTag_LineInfoLines = 0x000A, RDI_DataSectionTag_LineInfoColumns = 0x000B, -RDI_DataSectionTag_Units = 0x000C, -RDI_DataSectionTag_UnitVmap = 0x000D, -RDI_DataSectionTag_TypeNodes = 0x000E, -RDI_DataSectionTag_UDTs = 0x000F, -RDI_DataSectionTag_Members = 0x0010, -RDI_DataSectionTag_EnumMembers = 0x0011, -RDI_DataSectionTag_GlobalVariables = 0x0012, -RDI_DataSectionTag_GlobalVmap = 0x0013, -RDI_DataSectionTag_ThreadVariables = 0x0014, -RDI_DataSectionTag_Procedures = 0x0015, -RDI_DataSectionTag_Scopes = 0x0016, -RDI_DataSectionTag_ScopeVoffData = 0x0017, -RDI_DataSectionTag_ScopeVmap = 0x0018, -RDI_DataSectionTag_InlineSites = 0x0019, -RDI_DataSectionTag_Locals = 0x001A, -RDI_DataSectionTag_LocationBlocks = 0x001B, -RDI_DataSectionTag_LocationData = 0x001C, -RDI_DataSectionTag_NameMaps = 0x001D, -RDI_DataSectionTag_PRIMARY_COUNT = 0x001E, +RDI_DataSectionTag_SourceLineMaps = 0x000C, +RDI_DataSectionTag_SourceLineMapNumbers = 0x000D, +RDI_DataSectionTag_SourceLineMapRanges = 0x000E, +RDI_DataSectionTag_SourceLineMapVOffs = 0x000F, +RDI_DataSectionTag_Units = 0x0010, +RDI_DataSectionTag_UnitVmap = 0x0011, +RDI_DataSectionTag_TypeNodes = 0x0012, +RDI_DataSectionTag_UDTs = 0x0013, +RDI_DataSectionTag_Members = 0x0014, +RDI_DataSectionTag_EnumMembers = 0x0015, +RDI_DataSectionTag_GlobalVariables = 0x0016, +RDI_DataSectionTag_GlobalVmap = 0x0017, +RDI_DataSectionTag_ThreadVariables = 0x0018, +RDI_DataSectionTag_Procedures = 0x0019, +RDI_DataSectionTag_Scopes = 0x001A, +RDI_DataSectionTag_ScopeVoffData = 0x001B, +RDI_DataSectionTag_ScopeVmap = 0x001C, +RDI_DataSectionTag_InlineSites = 0x001D, +RDI_DataSectionTag_Locals = 0x001E, +RDI_DataSectionTag_LocationBlocks = 0x001F, +RDI_DataSectionTag_LocationData = 0x0020, +RDI_DataSectionTag_NameMaps = 0x0021, +RDI_DataSectionTag_PRIMARY_COUNT = 0x0022, RDI_DataSectionTag_SECONDARY = 0x80000000, -RDI_DataSectionTag_LineMapNumbers = RDI_DataSectionTag_SECONDARY|0x0001, -RDI_DataSectionTag_LineMapRanges = RDI_DataSectionTag_SECONDARY|0x0002, -RDI_DataSectionTag_LineMapVoffs = RDI_DataSectionTag_SECONDARY|0x0003, -RDI_DataSectionTag_NameMapBuckets = RDI_DataSectionTag_SECONDARY|0x0004, -RDI_DataSectionTag_NameMapNodes = RDI_DataSectionTag_SECONDARY|0x0005, +RDI_DataSectionTag_NameMapBuckets = RDI_DataSectionTag_SECONDARY|0x0001, +RDI_DataSectionTag_NameMapNodes = RDI_DataSectionTag_SECONDARY|0x0002, } RDI_DataSectionTagEnum; typedef RDI_U32 RDI_DataSectionEncoding; @@ -506,6 +507,10 @@ X(LineTables)\ X(LineInfoVoffs)\ X(LineInfoLines)\ X(LineInfoColumns)\ +X(SourceLineMaps)\ +X(SourceLineMapNumbers)\ +X(SourceLineMapRanges)\ +X(SourceLineMapVOffs)\ X(Units)\ X(UnitVmap)\ X(TypeNodes)\ @@ -526,9 +531,6 @@ X(LocationData)\ X(NameMaps)\ X(PRIMARY_COUNT)\ X(SECONDARY)\ -X(LineMapNumbers)\ -X(LineMapRanges)\ -X(LineMapVoffs)\ X(NameMapBuckets)\ X(NameMapNodes)\ @@ -581,10 +583,7 @@ X(RDI_U32, source_file_idx)\ #define RDI_SourceFile_XList \ X(RDI_U32, file_path_node_idx)\ X(RDI_U32, normal_full_path_string_idx)\ -X(RDI_U32, line_map_count)\ -X(RDI_U32, line_map_nums_data_idx)\ -X(RDI_U32, line_map_range_data_idx)\ -X(RDI_U32, line_map_voff_data_idx)\ +X(RDI_U32, source_line_map_idx)\ #define RDI_Unit_XList \ X(RDI_U32, unit_name_string_idx)\ @@ -611,6 +610,13 @@ X(RDI_U32, line_num)\ X(RDI_U16, col_first)\ X(RDI_U16, col_opl)\ +#define RDI_SourceLineMapMemberTable \ +X(RDI_U32, line_count)\ +X(RDI_U32, voff_count)\ +X(RDI_U32, line_map_nums_base_idx)\ +X(RDI_U32, line_map_range_base_idx)\ +X(RDI_U32, line_map_voff_base_idx)\ + #define RDI_Language_XList \ X(NULL)\ X(C)\ @@ -958,10 +964,7 @@ struct RDI_SourceFile { RDI_U32 file_path_node_idx; RDI_U32 normal_full_path_string_idx; -RDI_U32 line_map_count; -RDI_U32 line_map_nums_data_idx; -RDI_U32 line_map_range_data_idx; -RDI_U32 line_map_voff_data_idx; +RDI_U32 source_line_map_idx; }; typedef struct RDI_Unit RDI_Unit; @@ -1001,6 +1004,16 @@ RDI_U16 col_first; RDI_U16 col_opl; }; +typedef struct RDI_SourceLineMap RDI_SourceLineMap; +struct RDI_SourceLineMap +{ +RDI_U32 line_count; +RDI_U32 voff_count; +RDI_U32 line_map_nums_base_idx; +RDI_U32 line_map_range_base_idx; +RDI_U32 line_map_voff_base_idx; +}; + typedef struct RDI_TypeNode RDI_TypeNode; struct RDI_TypeNode { diff --git a/src/lib_rdi_format/rdi_format_parse.c b/src/lib_rdi_format/rdi_format_parse.c index 63b6e5f1..a61de07b 100644 --- a/src/lib_rdi_format/rdi_format_parse.c +++ b/src/lib_rdi_format/rdi_format_parse.c @@ -145,6 +145,7 @@ rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out) rdi_parse__extract_primary(out, out->file_paths, &out->file_paths_count, RDI_DataSectionTag_FilePathNodes); rdi_parse__extract_primary(out, out->source_files, &out->source_files_count, RDI_DataSectionTag_SourceFiles); rdi_parse__extract_primary(out, out->line_tables, &out->line_tables_count, RDI_DataSectionTag_LineTables); + rdi_parse__extract_primary(out, out->source_line_maps, &out->source_line_maps_count, RDI_DataSectionTag_SourceLineMaps); rdi_parse__extract_primary(out, out->line_info_voffs, &out->line_info_voffs_count, RDI_DataSectionTag_LineInfoVoffs); rdi_parse__extract_primary(out, out->line_info_lines, &out->line_info_lines_count, RDI_DataSectionTag_LineInfoLines); rdi_parse__extract_primary(out, out->line_info_columns, &out->line_info_columns_count, RDI_DataSectionTag_LineInfoColumns); @@ -185,6 +186,8 @@ rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out) 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->line_tables == 0) { out->line_tables = &rdi_line_table_nil; out->line_tables_count = 1; } + if(out->source_line_maps == 0) { out->source_line_maps = &rdi_source_line_map_nil; out->source_line_maps_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; } @@ -329,36 +332,39 @@ rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff) } RDI_PROC void -rdi_line_map_from_source_file(RDI_Parsed *p, RDI_SourceFile *srcfile, RDI_ParsedLineMap *out) +rdi_parsed_from_source_line_map(RDI_Parsed *p, RDI_SourceLineMap *map, RDI_ParsedSourceLineMap *out) { - RDI_U64 num_count = 0; - RDI_U32 *nums = (RDI_U32*)rdi_data_from_dsec(p, srcfile->line_map_nums_data_idx, sizeof(RDI_U32), - RDI_DataSectionTag_LineMapNumbers, - &num_count); + //- rjf: extract top-level line info tables + RDI_U64 all_nums_count = 0; + RDI_U32 *all_nums = (RDI_U32 *)rdi_data_from_dsec(p, p->dsec_idx[RDI_DataSectionTag_SourceLineMapNumbers], sizeof(RDI_U32), RDI_DataSectionTag_SourceLineMapNumbers, &all_nums_count); + RDI_U32 *all_nums_opl = all_nums + all_nums_count; + RDI_U64 all_rngs_count = 0; + RDI_U32 *all_rngs = (RDI_U32 *)rdi_data_from_dsec(p, p->dsec_idx[RDI_DataSectionTag_SourceLineMapRanges], sizeof(RDI_U32), RDI_DataSectionTag_SourceLineMapRanges, &all_rngs_count); + RDI_U32 *all_rngs_opl = all_rngs + all_rngs_count; + RDI_U64 all_voffs_count = 0; + RDI_U64 *all_voffs = (RDI_U64 *)rdi_data_from_dsec(p, p->dsec_idx[RDI_DataSectionTag_SourceLineMapVOffs], sizeof(RDI_U64), RDI_DataSectionTag_SourceLineMapVOffs, &all_voffs_count); + RDI_U64 *all_voffs_opl = all_voffs + all_voffs_count; - RDI_U64 range_count = 0; - RDI_U32 *ranges = (RDI_U32*)rdi_data_from_dsec(p, srcfile->line_map_range_data_idx, sizeof(RDI_U32), - RDI_DataSectionTag_LineMapRanges, - &range_count); + //- rjf: extract ranges of top-level tables belonging to this line map + RDI_U32 *map_nums = all_nums + map->line_map_nums_base_idx; + RDI_U32 *map_rngs = all_rngs + map->line_map_range_base_idx; + RDI_U64 *map_voffs= all_voffs+ map->line_map_voff_base_idx; + RDI_U64 lines_count = (RDI_U64)map->line_count; + RDI_U64 voffs_count = (RDI_U64)map->voff_count; + if(map_nums >= all_nums_opl) {map_nums = all_nums; lines_count = 0;} + if(map_rngs >= all_rngs_opl) {map_rngs = all_rngs; lines_count = 0;} + if(map_voffs>= all_voffs_opl){map_voffs= all_voffs;voffs_count = 0;} - RDI_U64 voff_count = 0; - RDI_U64 *voffs = (RDI_U64*)rdi_data_from_dsec(p, srcfile->line_map_voff_data_idx, sizeof(RDI_U64), - RDI_DataSectionTag_LineMapVoffs, - &voff_count); - - RDI_U32 count_a = (range_count > 0)?(range_count - 1):0; - RDI_U32 count_b = rdi_parse__min(count_a, num_count); - RDI_U32 count = rdi_parse__min(count_b, srcfile->line_map_count); - - out->nums = nums; - out->ranges = ranges; - out->voffs = voffs; - out->count = count; - out->voff_count = voff_count; + //- rjf: fill result + out->nums = map_nums; + out->ranges = map_rngs; + out->voffs = map_voffs; + out->count = lines_count; + out->voff_count = voffs_count; } RDI_PROC RDI_U64* -rdi_line_voffs_from_num(RDI_ParsedLineMap *map, RDI_U32 linenum, RDI_U32 *n_out) +rdi_line_voffs_from_num(RDI_ParsedSourceLineMap *map, RDI_U32 linenum, RDI_U32 *n_out) { RDI_U64 *result = 0; *n_out = 0; diff --git a/src/lib_rdi_format/rdi_format_parse.h b/src/lib_rdi_format/rdi_format_parse.h index 44e69fc8..c280f008 100644 --- a/src/lib_rdi_format/rdi_format_parse.h +++ b/src/lib_rdi_format/rdi_format_parse.h @@ -53,6 +53,8 @@ struct RDI_Parsed RDI_U64 source_files_count; RDI_LineTable* line_tables; RDI_U64 line_tables_count; + RDI_SourceLineMap* source_line_maps; + RDI_U64 source_line_maps_count; RDI_U64* line_info_voffs; RDI_U64 line_info_voffs_count; RDI_Line* line_info_lines; @@ -110,8 +112,8 @@ struct RDI_ParsedLineTable RDI_U64 col_count; }; -typedef struct RDI_ParsedLineMap RDI_ParsedLineMap; -struct RDI_ParsedLineMap +typedef struct RDI_ParsedSourceLineMap RDI_ParsedSourceLineMap; +struct RDI_ParsedSourceLineMap { // NOTE: Mapping LINE_NUMBER -> VOFFs // @@ -146,6 +148,7 @@ 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}; static RDI_LineTable rdi_line_table_nil = {0}; +static RDI_SourceLineMap rdi_source_line_map_nil = {0}; static RDI_Line rdi_line_nil = {0}; static RDI_Column rdi_column_nil = {0}; static RDI_Unit rdi_unit_nil = {0}; @@ -186,8 +189,8 @@ RDI_PROC RDI_U32 *rdi_idx_run_from_first_count(RDI_Parsed *parsed, RDI_U32 first //- line info RDI_PROC void rdi_parsed_from_line_table(RDI_Parsed *p, RDI_LineTable *line_table, RDI_ParsedLineTable *out); RDI_PROC RDI_U64 rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff); -RDI_PROC void rdi_line_map_from_source_file(RDI_Parsed *p, RDI_SourceFile *srcfile, RDI_ParsedLineMap *out); -RDI_PROC RDI_U64 *rdi_line_voffs_from_num(RDI_ParsedLineMap *map, RDI_U32 linenum, RDI_U32 *n_out); +RDI_PROC void rdi_parsed_from_source_line_map(RDI_Parsed *p, RDI_SourceLineMap *map, RDI_ParsedSourceLineMap *out); +RDI_PROC RDI_U64 *rdi_line_voffs_from_num(RDI_ParsedSourceLineMap *map, RDI_U32 linenum, RDI_U32 *n_out); //- vmap lookups RDI_PROC RDI_U64 rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U32 vmap_count, RDI_U64 voff); diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index 7d1e33cc..0f908b0a 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -509,9 +509,14 @@ rdim_src_file_chunk_list_concat_in_place(RDIM_SrcFileChunkList *dst, RDIM_SrcFil RDI_PROC void rdim_src_file_push_line_sequence(RDIM_Arena *arena, RDIM_SrcFileChunkList *src_files, RDIM_SrcFile *src_file, RDIM_LineSequence *seq) { + if(src_file->first_line_map_fragment == 0) + { + src_files->source_line_map_count += 1; + } RDIM_SrcFileLineMapFragment *fragment = rdim_push_array(arena, RDIM_SrcFileLineMapFragment, 1); fragment->seq = seq; RDIM_SLLQueuePush(src_file->first_line_map_fragment, src_file->last_line_map_fragment, fragment); + src_files->total_line_count += seq->line_count; } //////////////////////////////// @@ -1058,9 +1063,6 @@ rdim_bake_section_count_from_params(RDIM_BakeParams *params) RDI_U64 section_count = 0; { section_count += RDI_DataSectionTag_PRIMARY_COUNT; - section_count += params->src_files.total_count; // PER-SOURCE-FILE line map numbers - section_count += params->src_files.total_count; // PER-SOURCE-FILE line map ranges - section_count += params->src_files.total_count; // PER-SOURCE-FILE line map voffs section_count += RDI_NameMapKind_COUNT-1; // PER-NAME-MAP buckets section section_count += RDI_NameMapKind_COUNT-1; // PER-NAME-MAP nodes section } @@ -1079,33 +1081,16 @@ rdim_bake_section_idx_from_params_tag_idx(RDIM_BakeParams *params, RDI_DataSecti { default:{}break; - //- rjf: per-source-file sections - case (RDI_U32)RDI_DataSectionTag_LineMapNumbers: - if(idx != 0) - { - result = RDI_DataSectionTag_PRIMARY_COUNT + 0*params->src_files.total_count + (idx-1)%params->src_files.total_count; - }break; - case (RDI_U32)RDI_DataSectionTag_LineMapRanges: - if(idx != 0) - { - result = RDI_DataSectionTag_PRIMARY_COUNT + 1*params->src_files.total_count + (idx-1)%params->src_files.total_count; - }break; - case (RDI_U32)RDI_DataSectionTag_LineMapVoffs: - if(idx != 0) - { - result = RDI_DataSectionTag_PRIMARY_COUNT + 2*params->src_files.total_count + (idx-1)%params->src_files.total_count; - }break; - //- rjf: per-name-map sections case (RDI_U32)RDI_DataSectionTag_NameMapBuckets: if(idx != 0) { - result = RDI_DataSectionTag_PRIMARY_COUNT + 3*params->src_files.total_count + 0*(RDI_NameMapKind_COUNT-1) + (idx-1)%(RDI_NameMapKind_COUNT-1); + result = RDI_DataSectionTag_PRIMARY_COUNT + 0*(RDI_NameMapKind_COUNT-1) + (idx-1)%(RDI_NameMapKind_COUNT-1); }break; case (RDI_U32)RDI_DataSectionTag_NameMapNodes: if(idx != 0) { - result = RDI_DataSectionTag_PRIMARY_COUNT + 3*params->src_files.total_count + 1*(RDI_NameMapKind_COUNT-1) + (idx-1)%(RDI_NameMapKind_COUNT-1); + result = RDI_DataSectionTag_PRIMARY_COUNT + 1*(RDI_NameMapKind_COUNT-1) + (idx-1)%(RDI_NameMapKind_COUNT-1); }break; } return result; @@ -2329,14 +2314,34 @@ rdim_bake_unit_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams RDI_PROC RDIM_BakeSectionList rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params) { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); RDIM_BakeSectionList sections = {0}; //////////////////////////// - //- rjf: iterate all source files, fill serialized version, build sections for line info + //- rjf: iterate all source files, fill serialized version, fill line maps, fill line map tables // + typedef struct RDIM_DataNode RDIM_DataNode; + struct RDIM_DataNode + { + RDIM_DataNode *next; + void *data; + RDI_U64 size; + }; RDI_U32 dst_files_count = params->src_files.total_count + 1; + RDI_U32 dst_maps_count = params->src_files.source_line_map_count + 1; RDI_SourceFile *dst_files = rdim_push_array(arena, RDI_SourceFile, dst_files_count); + RDI_SourceLineMap *dst_maps = rdim_push_array(arena, RDI_SourceLineMap, dst_maps_count); + RDIM_DataNode *first_dst_nums_node = 0; + RDIM_DataNode *last_dst_nums_node = 0; + RDIM_DataNode *first_dst_rngs_node = 0; + RDIM_DataNode *last_dst_rngs_node = 0; + RDIM_DataNode *first_dst_voffs_node = 0; + RDIM_DataNode *last_dst_voffs_node = 0; + RDI_U64 dst_nums_idx = 0; + RDI_U64 dst_rngs_idx = 0; + RDI_U64 dst_voffs_idx = 0; RDI_U32 dst_file_idx = 1; + RDI_U32 dst_map_idx = 1; for(RDIM_SrcFileChunkNode *chunk_n = params->src_files.first; chunk_n != 0; chunk_n = chunk_n->next) @@ -2346,12 +2351,6 @@ rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMa RDIM_SrcFile *src_file = &chunk_n->v[idx]; RDI_SourceFile *dst_file = &dst_files[dst_file_idx]; - //////////////////////// - //- rjf: fill basics - // - dst_file->file_path_node_idx = rdim_bake_path_node_idx_from_string(path_tree, src_file->normal_full_path); - dst_file->normal_full_path_string_idx = rdim_bake_idx_from_string(strings, src_file->normal_full_path); - //////////////////////// //- rjf: produce combined source file line info // @@ -2361,8 +2360,6 @@ rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMa RDI_U32 src_file_line_count = 0; RDI_U32 src_file_voff_count = 0; { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - //- rjf: gather line number map typedef struct RDIM_SrcLineMapVoffBlock RDIM_SrcLineMapVoffBlock; struct RDIM_SrcLineMapVoffBlock @@ -2458,9 +2455,9 @@ rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMa RDIM_SortKey *sorted_keys = rdim_sort_key_array(scratch.arena, keys, line_count); //- rjf: bake result - RDI_U32 *line_nums = rdim_push_array_no_zero(arena, RDI_U32, line_count); - RDI_U32 *line_ranges = rdim_push_array_no_zero(arena, RDI_U32, line_count + 1); - RDI_U64 *voffs = rdim_push_array_no_zero(arena, RDI_U64, voff_count); + RDI_U32 *line_nums = rdim_push_array_no_zero(scratch.arena, RDI_U32, line_count); + RDI_U32 *line_ranges = rdim_push_array_no_zero(scratch.arena, RDI_U32, line_count + 1); + RDI_U64 *voffs = rdim_push_array_no_zero(scratch.arena, RDI_U64, voff_count); { RDI_U64 *voff_ptr = voffs; for(RDI_U32 i = 0; i < line_count; i += 1) @@ -2483,30 +2480,90 @@ rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMa src_file_line_count = line_count; src_file_voffs = voffs; src_file_voff_count = voff_count; - rdim_scratch_end(scratch); } - ////////////////////////// - //- rjf: produce data sections for this source file's line info tables + //////////////////////// + //- rjf: grab & fill the next line map, if this file has one // - if(src_file_line_count != 0) + RDI_SourceLineMap *dst_map = 0; + if(src_file->first_line_map_fragment != 0) { - dst_file->line_map_count = src_file_line_count; - dst_file->line_map_nums_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_LineMapNumbers, dst_file_idx); // TODO(rjf): @u64_to_u32 - dst_file->line_map_range_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_LineMapRanges, dst_file_idx); // TODO(rjf): @u64_to_u32 - dst_file->line_map_voff_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_LineMapVoffs, dst_file_idx); // TODO(rjf): @u64_to_u32 - rdim_bake_section_list_push_new_unpacked(arena, §ions, src_file_line_nums, sizeof(*src_file_line_nums)*src_file_line_count, RDI_DataSectionTag_LineMapNumbers, dst_file_idx); - rdim_bake_section_list_push_new_unpacked(arena, §ions, src_file_line_ranges, sizeof(*src_file_line_ranges)*(src_file_line_count + 1), RDI_DataSectionTag_LineMapRanges, dst_file_idx); - rdim_bake_section_list_push_new_unpacked(arena, §ions, src_file_voffs, sizeof(*src_file_voffs)*src_file_voff_count, RDI_DataSectionTag_LineMapVoffs, dst_file_idx); + dst_map = &dst_maps[dst_map_idx]; + dst_map_idx += 1; + dst_map->line_count = (RDI_U32)src_file_line_count; // TODO(rjf): @u64_to_u32 + dst_map->voff_count = (RDI_U32)src_file_voff_count; // TODO(rjf): @u64_to_u32 + dst_map->line_map_nums_base_idx = (RDI_U32)dst_nums_idx; // TODO(rjf): @u64_to_u32 + dst_map->line_map_range_base_idx = (RDI_U32)dst_rngs_idx; // TODO(rjf): @u64_to_u32 + dst_map->line_map_voff_base_idx = (RDI_U32)dst_voffs_idx; // TODO(rjf): @u64_to_u32 } + + //////////////////////// + //- rjf: gather line map data chunks for later collation & storage into their own top-level sections + // + { + RDIM_DataNode *dst_num_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); + RDIM_SLLQueuePush(first_dst_nums_node, last_dst_nums_node, dst_num_node); + dst_num_node->data = src_file_line_nums; + dst_num_node->size = sizeof(RDI_U32)*src_file_line_count; + RDIM_DataNode *dst_rng_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); + RDIM_SLLQueuePush(first_dst_rngs_node, last_dst_rngs_node, dst_rng_node); + dst_rng_node->data = src_file_line_ranges; + dst_rng_node->size = sizeof(RDI_U32)*(src_file_line_count+1); + RDIM_DataNode *dst_voff_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); + RDIM_SLLQueuePush(first_dst_voffs_node, last_dst_voffs_node, dst_voff_node); + dst_voff_node->data = src_file_voffs; + dst_voff_node->size = sizeof(RDI_U64)*(src_file_voff_count); + dst_nums_idx += src_file_line_count; + dst_rngs_idx += src_file_line_count+1; + dst_voffs_idx+= src_file_voff_count; + } + + //////////////////////// + //- rjf: fill file info + // + dst_file->file_path_node_idx = rdim_bake_path_node_idx_from_string(path_tree, src_file->normal_full_path); + dst_file->normal_full_path_string_idx = rdim_bake_idx_from_string(strings, src_file->normal_full_path); + dst_file->source_line_map_idx = (RDI_U32)(dst_map ? (dst_map - dst_maps) : 0); } } //////////////////////////// - //- rjf: build section for all source files + //- rjf: coalesce source line map data blobs // - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_files, sizeof(RDI_SourceFile)*dst_files_count, RDI_DataSectionTag_SourceFiles, 0); + RDI_U32 *source_line_map_nums = rdim_push_array_no_zero(arena, RDI_U32, dst_nums_idx); + RDI_U32 *source_line_map_rngs = rdim_push_array_no_zero(arena, RDI_U32, dst_rngs_idx); + RDI_U64 *source_line_map_voffs= rdim_push_array_no_zero(arena, RDI_U64, dst_voffs_idx); + { + RDI_U64 num_idx = 0; + RDI_U64 rng_idx = 0; + RDI_U64 voff_idx= 0; + for(RDIM_DataNode *num_n = first_dst_nums_node; num_n != 0; num_n = num_n->next) + { + rdim_memcpy(source_line_map_nums+num_idx, num_n->data, num_n->size); + num_idx += num_n->size/sizeof(RDI_U32); + } + for(RDIM_DataNode *rng_n = first_dst_rngs_node; rng_n != 0; rng_n = rng_n->next) + { + rdim_memcpy(source_line_map_rngs+rng_idx, rng_n->data, rng_n->size); + rng_idx += rng_n->size/sizeof(RDI_U32); + } + for(RDIM_DataNode *voff_n = first_dst_voffs_node; voff_n != 0; voff_n = voff_n->next) + { + rdim_memcpy(source_line_map_voffs+voff_idx, voff_n->data, voff_n->size); + voff_idx += voff_n->size/sizeof(RDI_U64); + } + } + //////////////////////////// + //- rjf: build sections + // + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_files, sizeof(RDI_SourceFile)*dst_files_count, RDI_DataSectionTag_SourceFiles, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_maps, sizeof(RDI_SourceLineMap)*dst_maps_count, RDI_DataSectionTag_SourceLineMaps, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, source_line_map_nums, sizeof(RDI_U32)*dst_nums_idx, RDI_DataSectionTag_SourceLineMapNumbers, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, source_line_map_rngs, sizeof(RDI_U32)*dst_rngs_idx, RDI_DataSectionTag_SourceLineMapRanges, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, source_line_map_voffs,sizeof(RDI_U64)*dst_voffs_idx, RDI_DataSectionTag_SourceLineMapVOffs, 0); + + rdim_scratch_end(scratch); return sections; } @@ -2515,17 +2572,6 @@ rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMa RDI_PROC RDIM_BakeSectionList rdim_bake_line_table_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params) { - // - // TODO(rjf): - // 1. section for all line tables - // 2. section for all line info voff ranges - // 3. section for all line info lines - // 4. section for all line info columns - // - // the entire line info voffs/lines/columns tables are not sorted together; only sub-sections, belonging to - // specific line tables, are sorted as one. so it is known up-front which line table maps to which index - // range into the collated line info sections. - // //- rjf: build all combined line info RDI_LineTable *dst_line_tables = push_array(arena, RDI_LineTable, params->line_tables.total_count+1); RDI_U64 *dst_line_voffs = push_array(arena, RDI_U64, params->line_tables.total_line_count + params->line_tables.total_seq_count); diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index 74178296..8306aa37 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -484,6 +484,8 @@ struct RDIM_SrcFileChunkList RDIM_SrcFileChunkNode *last; RDI_U64 chunk_count; RDI_U64 total_count; + RDI_U64 source_line_map_count; + RDI_U64 total_line_count; }; //////////////////////////////// diff --git a/src/rdi_dump/rdi_dump.c b/src/rdi_dump/rdi_dump.c index bad5b231..c1647c20 100644 --- a/src/rdi_dump/rdi_dump.c +++ b/src/rdi_dump/rdi_dump.c @@ -216,16 +216,55 @@ rdi_stringize_file_path(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_ 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); - // normal source path String8 path = {0}; path.str = rdi_string_from_idx(parsed, source_file->normal_full_path_string_idx, &path.size); str8_list_pushf(arena, out, "%.*spath: \"%S\"\n", indent_level, rdi_stringize_spaces, path); - // stringize line map data + // rjf: source line map idx + str8_list_pushf(arena, out, "%.*ssource_line_map: %u\n", indent_level, rdi_stringize_spaces, source_file->source_line_map_idx); +} + +internal void +rdi_stringize_line_table(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_LineTable *line_table, U32 indent_level) +{ + // rjf: parse line table + RDI_ParsedLineTable parsed_line_table = {0}; + rdi_parsed_from_line_table(parsed, line_table, &parsed_line_table); + + // rjf: stringize lines + str8_list_pushf(arena, out, "%.*slines:\n", indent_level, rdi_stringize_spaces); + for(U32 i = 0; i < parsed_line_table.count; i += 1) + { + U64 first = parsed_line_table.voffs[i]; + U64 opl = parsed_line_table.voffs[i + 1]; + RDI_Line *line = parsed_line_table.lines + i; + RDI_Column *col = 0; + if(i < parsed_line_table.col_count) + { + col = parsed_line_table.cols + i; + } + if(col == 0) + { + 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_source_line_map(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_SourceLineMap *map, U32 indent_level) +{ + RDI_ParsedSourceLineMap line_map = {0}; + rdi_parsed_from_source_line_map(parsed, map, &line_map); str8_list_pushf(arena, out, "%.*slines:\n", indent_level, rdi_stringize_spaces); for(U32 i = 0; i < line_map.count; i += 1) @@ -267,41 +306,6 @@ rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *parsed, RD } } -internal void -rdi_stringize_line_table(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_LineTable *line_table, U32 indent_level) -{ - // rjf: parse line table - RDI_ParsedLineTable parsed_line_table = {0}; - rdi_parsed_from_line_table(parsed, line_table, &parsed_line_table); - - // rjf: stringize lines - str8_list_pushf(arena, out, "%.*slines:\n", indent_level, rdi_stringize_spaces); - for(U32 i = 0; i < parsed_line_table.count; i += 1) - { - U64 first = parsed_line_table.voffs[i]; - U64 opl = parsed_line_table.voffs[i + 1]; - RDI_Line *line = parsed_line_table.lines + i; - RDI_Column *col = 0; - if(i < parsed_line_table.col_count) - { - col = parsed_line_table.cols + i; - } - if(col == 0) - { - 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_unit(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_Unit *unit, U32 indent_level) { diff --git a/src/rdi_dump/rdi_dump.h b/src/rdi_dump/rdi_dump.h index 76ce1d25..18534566 100644 --- a/src/rdi_dump/rdi_dump.h +++ b/src/rdi_dump/rdi_dump.h @@ -65,6 +65,7 @@ internal void rdi_stringize_binary_section(Arena *arena, String8List *out, RDI_P 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_line_table(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_LineTable *line_table, U32 indent_level); +internal void rdi_stringize_source_line_map(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_SourceLineMap *map, 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); diff --git a/src/rdi_dump/rdi_dump_main.c b/src/rdi_dump/rdi_dump_main.c index 1b87b572..7bd37ec2 100644 --- a/src/rdi_dump/rdi_dump_main.c +++ b/src/rdi_dump/rdi_dump_main.c @@ -54,18 +54,19 @@ entry_point(CmdLine *cmd_line) DumpFlag_FilePaths = (1<<3), DumpFlag_SourceFiles = (1<<4), DumpFlag_LineTables = (1<<5), - DumpFlag_Units = (1<<6), - DumpFlag_UnitVMap = (1<<7), - DumpFlag_TypeNodes = (1<<8), - DumpFlag_UDTs = (1<<9), - DumpFlag_GlobalVariables = (1<<10), - DumpFlag_GlobalVMap = (1<<11), - DumpFlag_ThreadVariables = (1<<12), - DumpFlag_Procedures = (1<<13), - DumpFlag_Scopes = (1<<14), - DumpFlag_ScopeVMap = (1<<15), - DumpFlag_NameMaps = (1<<16), - DumpFlag_Strings = (1<<17), + DumpFlag_SourceLineMaps = (1<<6), + DumpFlag_Units = (1<<7), + DumpFlag_UnitVMap = (1<<8), + DumpFlag_TypeNodes = (1<<9), + DumpFlag_UDTs = (1<<10), + DumpFlag_GlobalVariables = (1<<11), + DumpFlag_GlobalVMap = (1<<12), + DumpFlag_ThreadVariables = (1<<13), + DumpFlag_Procedures = (1<<14), + DumpFlag_Scopes = (1<<15), + DumpFlag_ScopeVMap = (1<<16), + DumpFlag_NameMaps = (1<<17), + DumpFlag_Strings = (1<<18), }; String8 input_name = {0}; DumpFlags dump_flags = (U32)0xffffffff; @@ -88,6 +89,7 @@ entry_point(CmdLine *cmd_line) 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("line_tables"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_LineTables; } + else if(str8_match(n->string, str8_lit("source_line_maps"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_SourceLineMaps; } 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; } @@ -185,7 +187,6 @@ entry_point(CmdLine *cmd_line) { str8_list_pushf(arena, &dump, " section[%u]:\n", i); rdi_stringize_binary_section(arena, &dump, rdi, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -219,7 +220,6 @@ entry_point(CmdLine *cmd_line) { str8_list_pushf(arena, &dump, " source_file[%u]:\n", i); rdi_stringize_source_file(arena, &dump, rdi, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -233,7 +233,19 @@ entry_point(CmdLine *cmd_line) { str8_list_pushf(arena, &dump, " line_table[%u]:\n", i); rdi_stringize_line_table(arena, &dump, rdi, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: SOURCE LINE MAPS + if(dump_flags & DumpFlag_SourceLineMaps) + { + str8_list_pushf(arena, &dump, "# SOURCE LINE MAPS\n"); + RDI_SourceLineMap *ptr = rdi->source_line_maps; + for(U32 i = 0; i < rdi->source_line_maps_count; i += 1, ptr += 1) + { + str8_list_pushf(arena, &dump, " source_line_map[%u]:\n", i); + rdi_stringize_source_line_map(arena, &dump, rdi, ptr, 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -247,7 +259,6 @@ entry_point(CmdLine *cmd_line) { str8_list_pushf(arena, &dump, " unit[%u]:\n", i); rdi_stringize_unit(arena, &dump, rdi, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -273,7 +284,6 @@ entry_point(CmdLine *cmd_line) { str8_list_pushf(arena, &dump, " type[%u]:\n", i); rdi_stringize_type_node(arena, &dump, rdi, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -294,7 +304,6 @@ entry_point(CmdLine *cmd_line) { str8_list_pushf(arena, &dump, " udt[%u]:\n", i); rdi_stringize_udt(arena, &dump, rdi, &member_bundle, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -308,7 +317,6 @@ entry_point(CmdLine *cmd_line) { str8_list_pushf(arena, &dump, " global_variable[%u]:\n", i); rdi_stringize_global_variable(arena, &dump, rdi, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -334,7 +342,6 @@ entry_point(CmdLine *cmd_line) { str8_list_pushf(arena, &dump, " thread_variable[%u]:\n", i); rdi_stringize_thread_variable(arena, &dump, rdi, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -348,7 +355,6 @@ entry_point(CmdLine *cmd_line) { str8_list_pushf(arena, &dump, " procedure[%u]:\n", i); rdi_stringize_procedure(arena, &dump, rdi, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -376,7 +382,6 @@ entry_point(CmdLine *cmd_line) if(ptr->parent_scope_idx == 0) { rdi_stringize_scope(arena, &dump, rdi, &scope_bundle, ptr, 1); - str8_list_push(arena, &dump, str8_lit("\n")); } } str8_list_push(arena, &dump, str8_lit("\n")); diff --git a/src/rdi_format/rdi_format.mdesk b/src/rdi_format/rdi_format.mdesk index e6ae4983..7ef0a47f 100644 --- a/src/rdi_format/rdi_format.mdesk +++ b/src/rdi_format/rdi_format.mdesk @@ -55,7 +55,7 @@ ""; "// \"raddbg\0\0\""; "#define RDI_MAGIC_CONSTANT 0x0000676264646172"; - "#define RDI_ENCODING_VERSION 2"; + "#define RDI_ENCODING_VERSION 3"; ""; "////////////////////////////////////////////////////////////////"; "//~ Format Types & Functions"; @@ -113,43 +113,44 @@ RDI_HeaderMemberTable: @table(name value desc) RDI_DataSectionTable: { - {NULL 0x0000 ""} - {TopLevelInfo 0x0001 ""} - {StringData 0x0002 ""} - {StringTable 0x0003 ""} - {IndexRuns 0x0004 ""} - {BinarySections 0x0005 ""} - {FilePathNodes 0x0006 ""} - {SourceFiles 0x0007 ""} - {LineTables 0x0008 ""} - {LineInfoVoffs 0x0009 ""} - {LineInfoLines 0x000A ""} - {LineInfoColumns 0x000B ""} - {Units 0x000C ""} - {UnitVmap 0x000D ""} - {TypeNodes 0x000E ""} - {UDTs 0x000F ""} - {Members 0x0010 ""} - {EnumMembers 0x0011 ""} - {GlobalVariables 0x0012 ""} - {GlobalVmap 0x0013 ""} - {ThreadVariables 0x0014 ""} - {Procedures 0x0015 ""} - {Scopes 0x0016 ""} - {ScopeVoffData 0x0017 ""} - {ScopeVmap 0x0018 ""} - {InlineSites 0x0019 ""} - {Locals 0x001A ""} - {LocationBlocks 0x001B ""} - {LocationData 0x001C ""} - {NameMaps 0x001D ""} - {PRIMARY_COUNT 0x001E ""} - {SECONDARY 0x80000000 ""} - {LineMapNumbers `RDI_DataSectionTag_SECONDARY|0x0001` ""} - {LineMapRanges `RDI_DataSectionTag_SECONDARY|0x0002` ""} - {LineMapVoffs `RDI_DataSectionTag_SECONDARY|0x0003` ""} - {NameMapBuckets `RDI_DataSectionTag_SECONDARY|0x0004` ""} - {NameMapNodes `RDI_DataSectionTag_SECONDARY|0x0005` ""} + {NULL 0x0000 ""} + {TopLevelInfo 0x0001 ""} + {StringData 0x0002 ""} + {StringTable 0x0003 ""} + {IndexRuns 0x0004 ""} + {BinarySections 0x0005 ""} + {FilePathNodes 0x0006 ""} + {SourceFiles 0x0007 ""} + {LineTables 0x0008 ""} + {LineInfoVoffs 0x0009 ""} + {LineInfoLines 0x000A ""} + {LineInfoColumns 0x000B ""} + {SourceLineMaps 0x000C ""} + {SourceLineMapNumbers 0x000D ""} + {SourceLineMapRanges 0x000E ""} + {SourceLineMapVOffs 0x000F ""} + {Units 0x0010 ""} + {UnitVmap 0x0011 ""} + {TypeNodes 0x0012 ""} + {UDTs 0x0013 ""} + {Members 0x0014 ""} + {EnumMembers 0x0015 ""} + {GlobalVariables 0x0016 ""} + {GlobalVmap 0x0017 ""} + {ThreadVariables 0x0018 ""} + {Procedures 0x0019 ""} + {Scopes 0x001A ""} + {ScopeVoffData 0x001B ""} + {ScopeVmap 0x001C ""} + {InlineSites 0x001D ""} + {Locals 0x001E ""} + {LocationBlocks 0x001F ""} + {LocationData 0x0020 ""} + {NameMaps 0x0021 ""} + {PRIMARY_COUNT 0x0022 ""} + {SECONDARY 0x80000000 ""} + {NameMapBuckets `RDI_DataSectionTag_SECONDARY|0x0001` ""} + {NameMapNodes `RDI_DataSectionTag_SECONDARY|0x0002` ""} } @table(name value) @@ -486,10 +487,7 @@ RDI_SourceFileMemberTable: // (line_map_nums * line_number) -> (nil | index) // (line_map_data * index) -> (range) // (line_map_voff_data * range) -> (array(voff)) - {line_map_count RDI_U32 ""} - {line_map_nums_data_idx RDI_U32 ""} // U32[line_map_count] (sorted - not closed ranges) - {line_map_range_data_idx RDI_U32 ""} // U32[line_map_count + 1] (pairs form ranges) - {line_map_voff_data_idx RDI_U32 ""} // U64[...] (idx by line_map_range_data) + {source_line_map_idx RDI_U32 ""} } @xlist RDI_FilePathNode_XList: @@ -568,6 +566,20 @@ RDI_ColumnMemberTable: {col_opl RDI_U16 ""} } +@table(name type desc) +RDI_SourceLineMapMemberTable: +{ + // usage of line map to go from a line number to an array of voffs + // (line_map_nums * line_number) -> (nil | index) + // (line_map_data * index) -> (range) + // (line_map_voff_data * range) -> (array(voff)) + {line_count RDI_U32 ""} + {voff_count RDI_U32 ""} + {line_map_nums_base_idx RDI_U32 ""} // U32[line_count] (sorted - not closed ranges) + {line_map_range_base_idx RDI_U32 ""} // U32[line_count + 1] (pairs form ranges) + {line_map_voff_base_idx RDI_U32 ""} // U64[voff_count] (idx by line_map_range_data) +} + @xlist RDI_LineTable_XList: { @expand(RDI_LineTableMemberTable a) `$(a.type), $(a.name)` @@ -583,6 +595,11 @@ RDI_ColumnMemberTable: @expand(RDI_ColumnMemberTable a) `$(a.type), $(a.name)` } +@xlist RDI_SourceLineMapMemberTable: +{ + @expand(RDI_SourceLineMapMemberTable a) `$(a.type), $(a.name)` +} + @struct RDI_LineTable: { @expand(RDI_LineTableMemberTable a) `$(a.type) $(a.name)` @@ -598,6 +615,11 @@ RDI_ColumnMemberTable: @expand(RDI_ColumnMemberTable a) `$(a.type) $(a.name)` } +@struct RDI_SourceLineMap: +{ + @expand(RDI_SourceLineMapMemberTable a) `$(a.type) $(a.name)` +} + //////////////////////////////// //~ rjf: Language Info Tables From 3f50169feeb5ef2bbd75378636f789f90f7534d3 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 4 Jun 2024 15:46:51 -0700 Subject: [PATCH 08/44] fix baking of joined line tables --- src/lib_rdi_make/rdi_make.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index 0f908b0a..02724bbf 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -2574,9 +2574,9 @@ rdim_bake_line_table_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams { //- rjf: build all combined line info RDI_LineTable *dst_line_tables = push_array(arena, RDI_LineTable, params->line_tables.total_count+1); - RDI_U64 *dst_line_voffs = push_array(arena, RDI_U64, params->line_tables.total_line_count + params->line_tables.total_seq_count); - RDI_Line *dst_lines = push_array(arena, RDI_Line, params->line_tables.total_line_count); - RDI_Column *dst_cols = push_array(arena, RDI_Column, params->line_tables.total_col_count); + RDI_U64 *dst_line_voffs = push_array(arena, RDI_U64, params->line_tables.total_line_count + 2*params->line_tables.total_seq_count); + RDI_Line *dst_lines = push_array(arena, RDI_Line, params->line_tables.total_line_count + params->line_tables.total_seq_count); + RDI_Column *dst_cols = push_array(arena, RDI_Column, 1); { RDI_U64 dst_table_idx = 1; RDI_U64 dst_voff_idx = 0; @@ -2606,13 +2606,8 @@ rdim_bake_line_table_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams RDI_U16 col_first; RDI_U16 col_opl; }; - RDI_U64 line_count = 0; - RDI_U64 seq_count = 0; - for(RDIM_LineSequenceNode *seq_n = src_line_table->first_seq; seq_n != 0; seq_n = seq_n->next) - { - seq_count += 1; - line_count += seq_n->v.line_count; - } + RDI_U64 line_count = src_line_table->line_count; + RDI_U64 seq_count = src_line_table->seq_count; RDI_U64 key_count = line_count + seq_count; RDIM_SortKey *line_keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, key_count); RDIM_LineRec *line_recs = rdim_push_array_no_zero(scratch.arena, RDIM_LineRec, line_count); @@ -2686,14 +2681,12 @@ rdim_bake_line_table_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams dst_line_table->voffs_base_idx = (RDI_U32)dst_voff_idx; // TODO(rjf): @u64_to_u32 dst_line_table->lines_base_idx = (RDI_U32)dst_line_idx; // TODO(rjf): @u64_to_u32 dst_line_table->cols_base_idx = (RDI_U32)dst_col_idx; // TODO(rjf): @u64_to_u32 - dst_line_table->lines_count = (RDI_U32)src_line_table->line_count; // TODO(rjf): @u64_to_u32 - dst_line_table->cols_count = (RDI_U32)src_line_table->col_count; // TODO(rjf): @u64_to_u32 + dst_line_table->lines_count = (RDI_U32)src_line_table->line_count + src_line_table->seq_count; // TODO(rjf): @u64_to_u32 //- rjf: increment dst_table_idx += 1; - dst_voff_idx += src_line_table->line_count + src_line_table->seq_count; - dst_line_idx += src_line_table->line_count; - dst_col_idx += src_line_table->col_count; + dst_voff_idx += src_line_table->line_count + 2*src_line_table->seq_count; + dst_line_idx += src_line_table->line_count + src_line_table->seq_count; } } } @@ -2703,7 +2696,7 @@ rdim_bake_line_table_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams { rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_line_tables, sizeof(RDI_LineTable)*params->line_tables.total_count, RDI_DataSectionTag_LineTables, 0); rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_line_voffs, sizeof(RDI_U64) * (params->line_tables.total_line_count + params->line_tables.total_seq_count), RDI_DataSectionTag_LineInfoVoffs, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_lines, sizeof(RDI_Line) * params->line_tables.total_line_count, RDI_DataSectionTag_LineInfoLines, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_lines, sizeof(RDI_Line) * (params->line_tables.total_line_count + params->line_tables.total_seq_count), RDI_DataSectionTag_LineInfoLines, 0); rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_cols, sizeof(RDI_Column) * params->line_tables.total_col_count, RDI_DataSectionTag_LineInfoColumns, 0); } return sections; From 0b35224cf84b7c404d7f8f3d9386ba221b512921 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Tue, 4 Jun 2024 17:04:53 -0700 Subject: [PATCH 09/44] set up inline site info building scaffolding --- project.4coder | 2 +- src/lib_rdi_make/rdi_make.c | 55 +++++++++++++++++++++++++++++++++ src/lib_rdi_make/rdi_make.h | 9 +++++- src/rdi_from_pdb/rdi_from_pdb.c | 31 ++++++++++--------- src/rdi_from_pdb/rdi_from_pdb.h | 1 + 5 files changed, 82 insertions(+), 16 deletions(-) diff --git a/project.4coder b/project.4coder index 08bf68db..5c0032f8 100644 --- a/project.4coder +++ b/project.4coder @@ -74,7 +74,7 @@ commands = }, .rjf_f4 = { - .win = "build rdi_from_pdb release telemetry && pushd build && rdi_from_pdb.exe --pdb:mule_main.pdb --out:mule_main.rdi --capture && popd", + .win = "build rdi_from_pdb release telemetry && pushd build && rdi_from_pdb.exe --pdb:UnrealEditorFortnite.pdb --out:profile.rdi --capture && popd", .linux = "", .out = "*compilation*", .footer_panel = true, diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index 02724bbf..23ce17e9 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -833,6 +833,61 @@ rdim_symbol_chunk_list_concat_in_place(RDIM_SymbolChunkList *dst, RDIM_SymbolChu rdim_memzero_struct(to_push); } +//////////////////////////////// +//~ rjf: [Building] Inline Site Info Building + +RDI_PROC RDIM_InlineSite * +rdim_inline_site_chunk_list_push(RDIM_Arena *arena, RDIM_InlineSiteChunkList *list, RDI_U64 cap) +{ + RDIM_InlineSiteChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_InlineSiteChunkNode, 1); + n->cap = cap; + n->base_idx = list->total_count; + n->v = rdim_push_array(arena, RDIM_InlineSite, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_InlineSite *result = &n->v[n->count]; + result->chunk = n; + n->count += 1; + list->total_count += 1; + return result; +} + +RDI_PROC RDI_U64 +rdim_idx_from_inline_site(RDIM_InlineSite *inline_site) +{ + RDI_U64 idx = 0; + if(inline_site != 0 && inline_site->chunk != 0) + { + idx = inline_site->chunk->base_idx + (inline_site - inline_site->chunk->v) + 1; + } + return idx; +} + +RDI_PROC void +rdim_inline_site_chunk_list_concat_in_place(RDIM_InlineSiteChunkList *dst, RDIM_InlineSiteChunkList *to_push) +{ + for(RDIM_InlineSiteChunkNode *n = to_push->first; n != 0; n = n->next) + { + n->base_idx += dst->total_count; + } + if(dst->last != 0 && to_push->first != 0) + { + dst->last->next = to_push->first; + dst->last = to_push->last; + dst->chunk_count += to_push->chunk_count; + dst->total_count += to_push->total_count; + } + else if(dst->first == 0) + { + rdim_memcpy_struct(dst, to_push); + } + rdim_memzero_struct(to_push); +} + //////////////////////////////// //~ rjf: [Building] Scope Info Building diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index 8306aa37..ce8330fb 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -778,7 +778,7 @@ struct RDIM_InlineSite RDI_U32 call_col_num; RDIM_Type *type; RDIM_Type *owner; - RDIM_LineTable *line_info; + RDIM_LineTable *line_table; }; typedef struct RDIM_InlineSiteChunkNode RDIM_InlineSiteChunkNode; @@ -1157,6 +1157,13 @@ RDI_PROC RDIM_Symbol *rdim_symbol_chunk_list_push(RDIM_Arena *arena, RDIM_Symbol RDI_PROC RDI_U64 rdim_idx_from_symbol(RDIM_Symbol *symbol); RDI_PROC void rdim_symbol_chunk_list_concat_in_place(RDIM_SymbolChunkList *dst, RDIM_SymbolChunkList *to_push); +//////////////////////////////// +//~ rjf: [Building] Inline Site Info Building + +RDI_PROC RDIM_InlineSite *rdim_inline_site_chunk_list_push(RDIM_Arena *arena, RDIM_InlineSiteChunkList *list, RDI_U64 cap); +RDI_PROC RDI_U64 rdim_idx_from_inline_site(RDIM_InlineSite *inline_site); +RDI_PROC void rdim_inline_site_chunk_list_concat_in_place(RDIM_InlineSiteChunkList *dst, RDIM_InlineSiteChunkList *to_push); + //////////////////////////////// //~ rjf: [Building] Scope Info Building diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index 4321dd20..9ed9b2b4 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -3436,6 +3436,20 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) link_name_map = &link_name_map__in_progress; } + ////////////////////////////////////////////////////////////// + //- rjf: join unit conversion & src file & line table tasks + // + RDIM_UnitChunkList all_units = {0}; + RDIM_SrcFileChunkList all_src_files = {0}; + RDIM_LineTableChunkList all_line_tables = {0}; + ProfScope("join unit conversion & src file tasks") + { + P2R_UnitConvertOut *out = ts_join_struct(unit_convert_ticket, max_U64, P2R_UnitConvertOut); + all_units = out->units; + all_src_files = out->src_files; + all_line_tables = out->line_tables; + } + ////////////////////////////////////////////////////////////// //- rjf: produce symbols from all streams // @@ -3443,6 +3457,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) RDIM_SymbolChunkList all_global_variables = {0}; RDIM_SymbolChunkList all_thread_variables = {0}; RDIM_ScopeChunkList all_scopes = {0}; + RDIM_InlineSiteChunkList all_inline_sites = {0}; ProfScope("produce symbols from all streams") { //////////////////////////// @@ -3493,24 +3508,11 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) rdim_symbol_chunk_list_concat_in_place(&all_global_variables, &out->global_variables); rdim_symbol_chunk_list_concat_in_place(&all_thread_variables, &out->thread_variables); rdim_scope_chunk_list_concat_in_place(&all_scopes, &out->scopes); + rdim_inline_site_chunk_list_concat_in_place(&all_inline_sites,&out->inline_sites); } } } - ////////////////////////////////////////////////////////////// - //- rjf: join unit conversion & src file & line table tasks - // - RDIM_UnitChunkList all_units = {0}; - RDIM_SrcFileChunkList all_src_files = {0}; - RDIM_LineTableChunkList all_line_tables = {0}; - ProfScope("join unit conversion & src file tasks") - { - P2R_UnitConvertOut *out = ts_join_struct(unit_convert_ticket, max_U64, P2R_UnitConvertOut); - all_units = out->units; - all_src_files = out->src_files; - all_line_tables = out->line_tables; - } - ////////////////////////////////////////////////////////////// //- rjf: types pass 5: join UDT build tasks // @@ -3537,6 +3539,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) out->bake_params.thread_variables = all_thread_variables; out->bake_params.procedures = all_procedures; out->bake_params.scopes = all_scopes; + out->bake_params.inline_sites = all_inline_sites; } scratch_end(scratch); diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index 80f74585..a16bce83 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -258,6 +258,7 @@ struct P2R_SymbolStreamConvertOut RDIM_SymbolChunkList global_variables; RDIM_SymbolChunkList thread_variables; RDIM_ScopeChunkList scopes; + RDIM_InlineSiteChunkList inline_sites; }; //////////////////////////////// From 14034c8bea62a47f965b24080de2b33c09023be9 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 6 Jun 2024 14:03:29 -0700 Subject: [PATCH 10/44] rdi: first pass of eliminating remainder of non-top-level sections; simplification/cleanup of rdi parsing layer --- src/ctrl/ctrl_core.c | 59 ++- src/dasm_cache/dasm_cache.c | 16 +- src/dbgi/dbgi.h | 41 +- src/df/core/df_core.c | 113 +++--- src/df/gfx/df_views.c | 36 +- src/eval/eval_parser.c | 270 ++++++------- src/fuzzy_search/fuzzy_search.c | 37 +- src/lib_rdi_format/rdi_format.c | 82 ++++ src/lib_rdi_format/rdi_format.h | 321 +++++++++++----- src/lib_rdi_format/rdi_format_parse.c | 359 +++++++----------- src/lib_rdi_format/rdi_format_parse.h | 151 +++----- src/lib_rdi_make/rdi_make.c | 178 ++++----- src/lib_rdi_make/rdi_make.h | 14 +- .../rdi_breakpad_from_pdb_main.c | 6 +- src/rdi_dump/rdi_dump.c | 88 ++--- src/rdi_dump/rdi_dump.h | 32 +- src/rdi_dump/rdi_dump_main.c | 189 +++++---- src/rdi_format/rdi_format.mdesk | 348 +++++++++-------- src/rdi_format/rdi_format_local.c | 24 +- src/rdi_from_pdb/rdi_from_pdb.c | 4 +- src/type_graph/type_graph.c | 57 ++- 21 files changed, 1196 insertions(+), 1229 deletions(-) diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index a9985895..5cf42018 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -2944,11 +2944,11 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_MachineID m // rjf: filename -> src_id U32 src_id = 0; { - RDI_NameMap *mapptr = rdi_name_map_from_kind(rdi, RDI_NameMapKind_NormalSourcePaths); + RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); if(mapptr != 0) { RDI_ParsedNameMap map = {0}; - rdi_name_map_parse(rdi, mapptr, &map); + rdi_parsed_from_name_map(rdi, mapptr, &map); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, filename_normalized.str, filename_normalized.size); if(node != 0) { @@ -2964,8 +2964,8 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_MachineID m // rjf: src_id * pt -> push { - RDI_SourceFile *src = rdi_element_from_idx(rdi, source_files, src_id); - RDI_SourceLineMap *src_line_map = rdi_element_from_idx(rdi, source_line_maps, src->source_line_map_idx); + RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id); + RDI_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx); RDI_ParsedSourceLineMap line_map = {0}; rdi_parsed_from_source_line_map(rdi, src_line_map, &line_map); U32 voff_count = 0; @@ -2984,26 +2984,20 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_MachineID m { String8 symbol_name = bp->string; U64 voff = bp->u64; - if(rdi != 0 && rdi->procedures != 0) + RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures); + RDI_ParsedNameMap map = {0}; + rdi_parsed_from_name_map(rdi, mapptr, &map); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, symbol_name.str, symbol_name.size); + if(node != 0) { - RDI_NameMap *mapptr = rdi_name_map_from_kind(rdi, RDI_NameMapKind_Procedures); - if(mapptr != 0) + U32 id_count = 0; + U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); + for(U32 match_i = 0; match_i < id_count; match_i += 1) { - RDI_ParsedNameMap map = {0}; - rdi_name_map_parse(rdi, mapptr, &map); - RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, symbol_name.str, symbol_name.size); - if(node != 0) - { - U32 id_count = 0; - U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); - for(U32 match_i = 0; match_i < id_count; match_i += 1) - { - U64 proc_voff = rdi_first_voff_from_proc(rdi, ids[match_i]); - U64 proc_vaddr = proc_voff + base_vaddr; - DMN_Trap trap = {process, proc_vaddr + voff, (U64)bp}; - dmn_trap_chunk_list_push(arena, traps_out, 256, &trap); - } - } + U64 proc_voff = rdi_first_voff_from_proc_idx(rdi, ids[match_i]); + U64 proc_vaddr = proc_voff + base_vaddr; + DMN_Trap trap = {process, proc_vaddr + voff, (U64)bp}; + dmn_trap_chunk_list_push(arena, traps_out, 256, &trap); } } }break; @@ -3446,11 +3440,10 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, CTRL_Entity *dbg_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath); DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp}; RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, max_U64); - RDI_NameMap *unparsed_map = rdi_name_map_from_kind(rdi, RDI_NameMapKind_GlobalVariables); - if(rdi->global_variables != 0 && unparsed_map != 0) + RDI_NameMap *unparsed_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_GlobalVariables); { RDI_ParsedNameMap map = {0}; - rdi_name_map_parse(rdi, unparsed_map, &map); + rdi_parsed_from_name_map(rdi, unparsed_map, &map); String8 name = str8_lit("__asan_shadow_memory_dynamic_address"); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, name.str, name.size); if(node != 0) @@ -3459,7 +3452,7 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); if(id_count > 0) { - RDI_GlobalVariable *global_var = rdi_element_from_idx(rdi, global_variables, ids[0]); + RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, ids[0]); U64 global_var_voff = global_var->voff; U64 global_var_vaddr = global_var->voff + module->vaddr_range.min; Architecture arch = process->arch; @@ -4248,9 +4241,9 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) CTRL_Entity *dbg_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath); DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp}; RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, max_U64); - RDI_NameMap *unparsed_map = rdi_name_map_from_kind(rdi, RDI_NameMapKind_Procedures); + RDI_NameMap *unparsed_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures); RDI_ParsedNameMap map = {0}; - rdi_name_map_parse(rdi, unparsed_map, &map); + rdi_parsed_from_name_map(rdi, unparsed_map, &map); //- rjf: add traps for user-specified entry points on this message, if specified B32 entries_found = 0; @@ -4269,7 +4262,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) procedure_id = ids[0]; } } - U64 voff = rdi_first_voff_from_proc(rdi, procedure_id); + U64 voff = rdi_first_voff_from_proc_idx(rdi, procedure_id); if(voff != 0) { entries_found = 1; @@ -4297,7 +4290,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) procedure_id = ids[0]; } } - U64 voff = rdi_first_voff_from_proc(rdi, procedure_id); + U64 voff = rdi_first_voff_from_proc_idx(rdi, procedure_id); if(voff != 0) { entries_found = 1; @@ -4324,7 +4317,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) procedure_id = ids[0]; } } - U64 voff = rdi_first_voff_from_proc(rdi, procedure_id); + U64 voff = rdi_first_voff_from_proc_idx(rdi, procedure_id); if(voff != 0) { DMN_Trap trap = {process->handle, module_base_vaddr + voff}; @@ -4357,7 +4350,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) procedure_id = ids[0]; } } - U64 voff = rdi_first_voff_from_proc(rdi, procedure_id); + U64 voff = rdi_first_voff_from_proc_idx(rdi, procedure_id); if(voff != 0) { entries_found = 1; @@ -4401,7 +4394,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) procedure_id = ids[0]; } } - U64 voff = rdi_first_voff_from_proc(rdi, procedure_id); + U64 voff = rdi_first_voff_from_proc_idx(rdi, procedure_id); if(voff != 0) { entries_found = 1; diff --git a/src/dasm_cache/dasm_cache.c b/src/dasm_cache/dasm_cache.c index dc10bed7..2b255e6a 100644 --- a/src/dasm_cache/dasm_cache.c +++ b/src/dasm_cache/dasm_cache.c @@ -433,7 +433,7 @@ dasm_parse_thread__entry_point(void *p) ud_set_syntax(&udc, params.syntax == DASM_Syntax_Intel ? UD_SYN_INTEL : UD_SYN_ATT); // rjf: disassemble - RDI_SourceFile *last_file = &rdi_source_file_nil; + RDI_SourceFile *last_file = &rdi_nil_element_union.source_file; RDI_Line *last_line = 0; for(U64 off = 0; off < data.size;) { @@ -455,16 +455,16 @@ dasm_parse_thread__entry_point(void *p) if(rdi != &di_rdi_parsed_nil) { U64 voff = (params.vaddr+off) - params.base_vaddr; - U32 unit_idx = rdi_vmap_idx_from_voff(rdi->unit_vmap, rdi->unit_vmap_count, voff); - RDI_Unit *unit = rdi_element_from_idx(rdi, units, unit_idx); - RDI_LineTable *line_table = rdi_element_from_idx(rdi, line_tables, unit->line_table_idx); + U32 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, voff); + RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); + RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); RDI_ParsedLineTable unit_line_info = {0}; rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff); if(line_info_idx < unit_line_info.count) { RDI_Line *line = &unit_line_info.lines[line_info_idx]; - RDI_SourceFile *file = rdi_element_from_idx(rdi, source_files, line->file_idx); + RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx); String8 file_normalized_full_path = {0}; file_normalized_full_path.str = rdi_string_from_idx(rdi, file->normal_full_path_string_idx, &file_normalized_full_path.size); if(file != last_file) @@ -552,12 +552,12 @@ dasm_parse_thread__entry_point(void *p) String8 symbol_part = {0}; if(jump_dst_vaddr != 0 && rdi != &di_rdi_parsed_nil && params.style_flags & DASM_StyleFlag_SymbolNames) { - RDI_U32 scope_idx = rdi_vmap_idx_from_voff(rdi->scope_vmap, rdi->scope_vmap_count, jump_dst_vaddr-params.base_vaddr); + RDI_U32 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, jump_dst_vaddr-params.base_vaddr); if(scope_idx != 0) { - RDI_Scope *scope = rdi_element_from_idx(rdi, scopes, scope_idx); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); RDI_U32 procedure_idx = scope->proc_idx; - RDI_Procedure *procedure = rdi_element_from_idx(rdi, procedures, procedure_idx); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_idx); String8 procedure_name = {0}; procedure_name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &procedure_name.size); if(procedure_name.size != 0) diff --git a/src/dbgi/dbgi.h b/src/dbgi/dbgi.h index c3590111..80e84c73 100644 --- a/src/dbgi/dbgi.h +++ b/src/dbgi/dbgi.h @@ -192,46 +192,7 @@ struct DI_Shared global DI_Shared *di_shared = 0; thread_static DI_TCTX *di_tctx = 0; -global RDI_Parsed di_rdi_parsed_nil = -{ - 0, - 0, - 0, - 0, - {0}, - 0, - 0, - 0, - 0, - 0, - 0, - &rdi_top_level_info_nil, - &rdi_binary_section_nil, 1, - &rdi_file_path_node_nil, 1, - &rdi_source_file_nil, 1, - &rdi_line_table_nil, 1, - &rdi_source_line_map_nil, 1, - &rdi_voff_nil, 1, - &rdi_line_nil, 1, - &rdi_column_nil, 1, - &rdi_unit_nil, 1, - &rdi_vmap_entry_nil, 1, - &rdi_type_node_nil, 1, - &rdi_udt_nil, 1, - &rdi_member_nil, 1, - &rdi_enum_member_nil, 1, - &rdi_global_variable_nil, 1, - &rdi_vmap_entry_nil, 1, - &rdi_thread_variable_nil, 1, - &rdi_procedure_nil, 1, - &rdi_scope_nil, 1, - &rdi_voff_nil, 1, - &rdi_vmap_entry_nil, 1, - &rdi_local_nil, 1, - &rdi_location_block_nil, 1, - 0, 0, - 0, 0, -}; +global RDI_Parsed di_rdi_parsed_nil = {0}; //////////////////////////////// //~ rjf: Basic Helpers diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index d094d4fa..cf59414c 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -3168,20 +3168,20 @@ df_symbol_name_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff) Temp scratch = scratch_begin(&arena, 1); DI_Scope *scope = di_scope_open(); RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 0); - if(result.size == 0 && rdi->scope_vmap != 0) + if(result.size == 0) { - U64 scope_idx = rdi_vmap_idx_from_voff(rdi->scope_vmap, rdi->scope_vmap_count, voff); - RDI_Scope *scope = rdi_element_from_idx(rdi, scopes, scope_idx); + U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); U64 proc_idx = scope->proc_idx; - RDI_Procedure *procedure = &rdi->procedures[proc_idx]; + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx); U64 name_size = 0; U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); result = push_str8_copy(arena, str8(name_ptr, name_size)); } - if(result.size == 0 && rdi->global_vmap != 0) + if(result.size == 0) { - U64 global_idx = rdi_vmap_idx_from_voff(rdi->global_vmap, rdi->global_vmap_count, voff); - RDI_GlobalVariable *global_var = rdi_element_from_idx(rdi, global_variables, global_idx); + U64 global_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_GlobalVMap, voff); + RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, global_idx); U64 name_size = 0; U8 *name_ptr = rdi_string_from_idx(rdi, global_var->name_string_idx, &name_size); result = push_str8_copy(arena, str8(name_ptr, name_size)); @@ -3239,21 +3239,18 @@ df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entit U32 src_id = 0; if(rdi != &di_rdi_parsed_nil) { - RDI_NameMap *mapptr = rdi_name_map_from_kind(rdi, RDI_NameMapKind_NormalSourcePaths); - if(mapptr != 0) + RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); + RDI_ParsedNameMap map = {0}; + rdi_parsed_from_name_map(rdi, mapptr, &map); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, file_path_normalized.str, file_path_normalized.size); + if(node != 0) { - RDI_ParsedNameMap map = {0}; - rdi_name_map_parse(rdi, mapptr, &map); - RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, file_path_normalized.str, file_path_normalized.size); - if(node != 0) + U32 id_count = 0; + U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); + if(id_count > 0) { - U32 id_count = 0; - U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); - if(id_count > 0) - { - good_src_id = 1; - src_id = ids[0]; - } + good_src_id = 1; + src_id = ids[0]; } } } @@ -3261,8 +3258,8 @@ df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entit // rjf: good src-id -> look up line info for visible range if(good_src_id) { - RDI_SourceFile *src = rdi->source_files+src_id; - RDI_SourceLineMap *src_line_map = rdi_element_from_idx(rdi, source_line_maps, src->source_line_map_idx); + RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id); + RDI_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx); RDI_ParsedSourceLineMap line_map = {0}; rdi_parsed_from_source_line_map(rdi, src_line_map, &line_map); U64 line_idx = 0; @@ -3276,9 +3273,9 @@ df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entit for(U64 idx = 0; idx < voff_count; idx += 1) { U64 base_voff = voffs[idx]; - U64 unit_idx = rdi_vmap_idx_from_voff(rdi->unit_vmap, rdi->unit_vmap_count, base_voff); - RDI_Unit *unit = rdi_element_from_idx(rdi, units, unit_idx); - RDI_LineTable *line_table = rdi_element_from_idx(rdi, line_tables, unit->line_table_idx); + U64 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, base_voff); + RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); + RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); RDI_ParsedLineTable unit_line_info = {0}; rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff); @@ -3319,11 +3316,10 @@ df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff) RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 0); DF_TextLineDasm2SrcInfo result = {0}; result.file = &df_g_nil_entity; - if(rdi->unit_vmap != 0 && rdi->units != 0 && rdi->source_files != 0) { - U64 unit_idx = rdi_vmap_idx_from_voff(rdi->unit_vmap, rdi->unit_vmap_count, voff); - RDI_Unit *unit = rdi_element_from_idx(rdi, units, unit_idx); - RDI_LineTable *line_table = rdi_element_from_idx(rdi, line_tables, unit->line_table_idx); + U64 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, voff); + RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); + RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); RDI_ParsedLineTable unit_line_info = {0}; rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff); @@ -3331,7 +3327,7 @@ df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff) { RDI_Line *line = &unit_line_info.lines[line_info_idx]; RDI_Column *column = (line_info_idx < unit_line_info.col_count) ? &unit_line_info.cols[line_info_idx] : 0; - RDI_SourceFile *file = rdi_element_from_idx(rdi, source_files, line->file_idx); + RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx); String8 file_normalized_full_path = {0}; file_normalized_full_path.str = rdi_string_from_idx(rdi, file->normal_full_path_string_idx, &file_normalized_full_path.size); MemoryCopyStruct(&result.dbgi_key, dbgi_key); @@ -3371,9 +3367,9 @@ df_voff_from_dbgi_key_symbol_name(DI_Key *dbgi_key, String8 symbol_name) name_map_kind_idx += 1) { RDI_NameMapKind name_map_kind = name_map_kinds[name_map_kind_idx]; - RDI_NameMap *name_map = rdi_name_map_from_kind(rdi, name_map_kind); + RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, name_map_kind); RDI_ParsedNameMap parsed_name_map = {0}; - rdi_name_map_parse(rdi, name_map, &parsed_name_map); + rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, symbol_name.str, symbol_name.size); // rjf: node -> num @@ -3405,14 +3401,14 @@ df_voff_from_dbgi_key_symbol_name(DI_Key *dbgi_key, String8 symbol_name) default:{}break; case RDI_NameMapKind_GlobalVariables: { - RDI_GlobalVariable *global_var = rdi_element_from_idx(rdi, global_variables, entity_num-1); + RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, entity_num-1); voff = global_var->voff; }break; case RDI_NameMapKind_Procedures: { - RDI_Procedure *procedure = rdi_element_from_idx(rdi, procedures, entity_num-1); - RDI_Scope *scope = rdi_element_from_idx(rdi, scopes, procedure->root_scope_idx); - voff = rdi->scope_voffs[scope->voff_range_first]; + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, entity_num-1); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx); + voff = *rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_first); }break; } @@ -3439,9 +3435,9 @@ df_type_num_from_dbgi_key_name(DI_Key *dbgi_key, String8 name) U64 result = 0; { RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 0); - RDI_NameMap *name_map = rdi_name_map_from_kind(rdi, RDI_NameMapKind_Types); + RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Types); RDI_ParsedNameMap parsed_name_map = {0}; - rdi_name_map_parse(rdi, name_map, &parsed_name_map); + rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, name.str, name.size); U64 entity_num = 0; if(node != 0) @@ -3928,21 +3924,18 @@ df_eval_parse_ctx_from_src_loc(DI_Scope *scope, DF_Entity *file, TxtPt pt) B32 good_src_id = 0; U32 src_id = 0; { - RDI_NameMap *mapptr = rdi_name_map_from_kind(rdi, RDI_NameMapKind_NormalSourcePaths); - if(mapptr != 0) + RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); + RDI_ParsedNameMap map = {0}; + rdi_parsed_from_name_map(rdi, mapptr, &map); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, file_path_normalized.str, file_path_normalized.size); + if(node != 0) { - RDI_ParsedNameMap map = {0}; - rdi_name_map_parse(rdi, mapptr, &map); - RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, file_path_normalized.str, file_path_normalized.size); - if(node != 0) + U32 id_count = 0; + U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); + if(id_count > 0) { - U32 id_count = 0; - U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); - if(id_count > 0) - { - good_src_id = 1; - src_id = ids[0]; - } + good_src_id = 1; + src_id = ids[0]; } } } @@ -3950,8 +3943,8 @@ df_eval_parse_ctx_from_src_loc(DI_Scope *scope, DF_Entity *file, TxtPt pt) // rjf: good src-id -> look up line info for visible range if(good_src_id) { - RDI_SourceFile *src = rdi->source_files+src_id; - RDI_SourceLineMap *src_line_map = rdi_element_from_idx(rdi, source_line_maps, src->source_line_map_idx); + RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id); + RDI_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx); RDI_ParsedSourceLineMap line_map = {0}; rdi_parsed_from_source_line_map(rdi, src_line_map, &line_map); U32 voff_count = 0; @@ -3959,9 +3952,9 @@ df_eval_parse_ctx_from_src_loc(DI_Scope *scope, DF_Entity *file, TxtPt pt) for(U64 idx = 0; idx < voff_count; idx += 1) { U64 base_voff = voffs[idx]; - U64 unit_idx = rdi_vmap_idx_from_voff(rdi->unit_vmap, rdi->unit_vmap_count, base_voff); - RDI_Unit *unit = rdi_element_from_idx(rdi, units, unit_idx); - RDI_LineTable *line_table = rdi_element_from_idx(rdi, line_tables, unit->line_table_idx); + U64 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, base_voff); + RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); + RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); RDI_ParsedLineTable unit_line_info = {0}; rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff); @@ -4270,12 +4263,12 @@ df_dynamically_typed_eval_from_eval(TG_Graph *graph, RDI_Parsed *rdi, DF_CtrlCtx U64 vtable_vaddr = 0; MemoryCopy(&vtable_vaddr, vtable_base_ptr_memory.str, addr_size); U64 vtable_voff = df_voff_from_vaddr(module, vtable_vaddr); - U64 global_idx = rdi_vmap_idx_from_voff(rdi->global_vmap, rdi->global_vmap_count, vtable_voff); - RDI_GlobalVariable *global_var = rdi_element_from_idx(rdi, global_variables, global_idx); + U64 global_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_GlobalVMap, vtable_voff); + RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, global_idx); if(global_var->link_flags & RDI_LinkFlag_TypeScoped) { - RDI_UDT *udt = rdi_element_from_idx(rdi, udts, global_var->container_idx); - RDI_TypeNode *type = rdi_element_from_idx(rdi, type_nodes, udt->self_type_idx); + RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, global_var->container_idx); + RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); TG_Key derived_type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type->kind), (U64)udt->self_type_idx); TG_Key ptr_to_derived_type_key = tg_cons_type_make(graph, TG_Kind_Ptr, derived_type_key, 0); eval.type_key = ptr_to_derived_type_key; diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 4ddcd837..c8870701 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -3272,8 +3272,10 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister) { for(U64 idx = 0; idx < rdis_count; idx += 1) { - rdis[idx] = di_rdi_from_key(di_scope, &dbgi_keys.v[idx], endt_us); - graphs[idx] = tg_graph_begin(rdi_addr_size_from_arch(rdis[idx]->top_level_info->arch), 256); + RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_keys.v[idx], endt_us); + RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); + rdis[idx] = rdi; + graphs[idx] = tg_graph_begin(rdi_addr_size_from_arch(tli->arch), 256); } } @@ -3302,9 +3304,11 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister) for(U64 rdi_idx = 0; rdi_idx < rdis_count; rdi_idx += 1) { RDI_Parsed *rdi = rdis[rdi_idx]; - if(base_idx <= item->idx && item->idx < base_idx + rdi->procedures_count) + U64 rdi_procedures_count = 0; + rdi_section_raw_table_from_kind(rdi, RDI_SectionKind_Procedures, &rdi_procedures_count); + if(base_idx <= item->idx && item->idx < base_idx + rdi_procedures_count) { - RDI_Procedure *procedure = rdi_element_from_idx(rdi, procedures, item->idx-base_idx); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, item->idx-base_idx); U64 name_size = 0; U8 *name_base = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); String8 name = str8(name_base, name_size); @@ -3317,7 +3321,7 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister) } break; } - base_idx += rdi->procedures_count; + base_idx += rdi_procedures_count; } } @@ -3360,23 +3364,25 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister) { for(U64 rdi_idx = 0; rdi_idx < rdis_count; rdi_idx += 1) { - if(base_idx <= item->idx && item->idx < base_idx + rdis[rdi_idx]->procedures_count) + U64 procedures_count = 0; + rdi_section_raw_table_from_kind(rdis[rdi_idx], RDI_SectionKind_Procedures, &procedures_count); + if(base_idx <= item->idx && item->idx < base_idx + procedures_count) { dbgi_key = dbgi_keys.v[rdi_idx]; rdi = rdis[rdi_idx]; graph = graphs[rdi_idx]; break; } - base_idx += rdis[rdi_idx]->procedures_count; + base_idx += procedures_count; } } //- rjf: unpack this item's info - RDI_Procedure *procedure = rdi_element_from_idx(rdi, procedures, item->idx-base_idx); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, item->idx-base_idx); U64 name_size = 0; U8 *name_base = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); String8 name = str8(name_base, name_size); - RDI_TypeNode *type_node = rdi_element_from_idx(rdi, type_nodes, procedure->type_idx); + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, procedure->type_idx); TG_Key type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), procedure->type_idx); //- rjf: build item button @@ -4926,17 +4932,17 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); String8 symbol_name = {0}; String8 symbol_type_string = {0}; - if(rdi->scope_vmap != 0) { - U64 scope_idx = rdi_vmap_idx_from_voff(rdi->scope_vmap, rdi->scope_vmap_count, rip_voff); - RDI_Scope *scope = rdi_element_from_idx(rdi, scopes, scope_idx); + U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, rip_voff); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); U64 proc_idx = scope->proc_idx; - RDI_Procedure *procedure = &rdi->procedures[proc_idx]; - RDI_TypeNode *type_node = rdi_element_from_idx(rdi, type_nodes, procedure->type_idx); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx); + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, procedure->type_idx); TG_Key type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), procedure->type_idx); U64 name_size = 0; U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); - TG_Graph *graph = tg_graph_begin(rdi_addr_size_from_arch(rdi->top_level_info->arch), 256); + RDI_TopLevelInfo *top_level_info = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); + TG_Graph *graph = tg_graph_begin(rdi_addr_size_from_arch(top_level_info->arch), 256); symbol_name = str8(name_ptr, name_size); symbol_type_string = tg_string_from_key(scratch.arena, graph, rdi, type_key); } diff --git a/src/eval/eval_parser.c b/src/eval/eval_parser.c index bbfeca81..81f70d33 100644 --- a/src/eval/eval_parser.c +++ b/src/eval/eval_parser.c @@ -73,10 +73,9 @@ eval_push_locals_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff) //- rjf: voff -> tightest scope RDI_Scope *tightest_scope = 0; - if(rdi->scope_vmap != 0 && rdi->scopes != 0) { - U64 scope_idx = rdi_vmap_idx_from_voff(rdi->scope_vmap, rdi->scope_vmap_count, voff); - RDI_Scope *scope = &rdi->scopes[scope_idx]; + U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); Task *task = push_array(scratch.arena, Task, 1); task->scope = scope; SLLQueuePush(first_task, last_task, task); @@ -84,10 +83,10 @@ eval_push_locals_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff) } //- rjf: voff-1 -> scope - if(voff > 0 && rdi->scope_vmap != 0 && rdi->scopes != 0) + if(voff > 0) { - U64 scope_idx = rdi_vmap_idx_from_voff(rdi->scope_vmap, rdi->scope_vmap_count, voff-1); - RDI_Scope *scope = &rdi->scopes[scope_idx]; + U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff-1); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); if(scope != tightest_scope) { Task *task = push_array(scratch.arena, Task, 1); @@ -99,9 +98,10 @@ eval_push_locals_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff) //- rjf: tightest scope -> walk up the tree & build tasks for each parent scope if(tightest_scope != 0) { - for(RDI_Scope *scope = &rdi->scopes[tightest_scope->parent_scope_idx]; - scope != 0 && scope != &rdi->scopes[0]; - scope = &rdi->scopes[scope->parent_scope_idx]) + RDI_Scope *nil_scope = rdi_element_from_name_idx(rdi, Scopes, 0); + for(RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, tightest_scope->parent_scope_idx); + scope != 0 && scope != nil_scope; + scope = rdi_element_from_name_idx(rdi, Scopes, scope->parent_scope_idx)) { Task *task = push_array(scratch.arena, Task, 1); task->scope = scope; @@ -122,7 +122,7 @@ eval_push_locals_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff) U32 local_opl_idx = scope->local_first + scope->local_count; for(U32 local_idx = scope->local_first; local_idx < local_opl_idx; local_idx += 1) { - RDI_Local *local_var = &rdi->locals[local_idx]; + RDI_Local *local_var = rdi_element_from_name_idx(rdi, Locals, local_idx); U64 local_name_size = 0; U8 *local_name_str = rdi_string_from_idx(rdi, local_var->name_string_idx, &local_name_size); String8 name = push_str8_copy(arena, str8(local_name_str, local_name_size)); @@ -139,52 +139,30 @@ internal EVAL_String2NumMap * eval_push_member_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff) { //- rjf: voff -> tightest scope - RDI_Scope *tightest_scope = 0; - if(rdi->scope_vmap != 0 && rdi->scopes != 0) - { - U64 scope_idx = rdi_vmap_idx_from_voff(rdi->scope_vmap, rdi->scope_vmap_count, voff); - tightest_scope = &rdi->scopes[scope_idx]; - } + U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); + RDI_Scope *tightest_scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); //- rjf: tightest scope -> procedure - RDI_Procedure *procedure = 0; - if(tightest_scope != 0 && rdi->procedures != 0) - { - U32 proc_idx = tightest_scope->proc_idx; - if(0 < proc_idx && proc_idx < rdi->procedures_count) - { - procedure = &rdi->procedures[proc_idx]; - } - } + U32 proc_idx = tightest_scope->proc_idx; + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx); //- rjf: procedure -> udt - RDI_UDT *udt = 0; - if(procedure != 0 && rdi->udts != 0 && procedure->link_flags & RDI_LinkFlag_TypeScoped) - { - U32 udt_idx = procedure->container_idx; - if(0 < udt_idx && udt_idx < rdi->udts_count) - { - udt = &rdi->udts[udt_idx]; - } - } + U32 udt_idx = procedure->container_idx; + RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, udt_idx); //- rjf: build blank map EVAL_String2NumMap *map = push_array(arena, EVAL_String2NumMap, 1); *map = eval_string2num_map_make(arena, 64); //- rjf: udt -> fill member map - if(udt != 0 && !(udt->flags & RDI_UDTFlag_EnumMembers) && rdi->members != 0) + if(!(udt->flags & RDI_UDTFlag_EnumMembers)) { U64 data_member_num = 1; for(U32 member_idx = udt->member_first; member_idx < udt->member_first+udt->member_count; member_idx += 1) { - if(member_idx < 1 || rdi->members_count <= member_idx) - { - break; - } - RDI_Member *m = &rdi->members[member_idx]; + RDI_Member *m = rdi_element_from_name_idx(rdi, Members, member_idx); if(m->kind == RDI_MemberKind_DataField) { String8 name = {0}; @@ -476,11 +454,10 @@ eval_leaf_type_from_name(RDI_Parsed *rdi, String8 name) { TG_Key key = zero_struct; B32 found = 0; - if(rdi->type_nodes != 0) { - RDI_NameMap *name_map = rdi_name_map_from_kind(rdi, RDI_NameMapKind_Types); + RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Types); RDI_ParsedNameMap parsed_name_map = {0}; - rdi_name_map_parse(rdi, name_map, &parsed_name_map); + rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, name.str, name.size); if(node != 0) { @@ -488,7 +465,7 @@ eval_leaf_type_from_name(RDI_Parsed *rdi, String8 name) U32 *matches = rdi_matches_from_map_node(rdi, node, &match_count); if(match_count != 0) { - RDI_TypeNode *type_node = rdi_element_from_idx(rdi, type_nodes, matches[0]); + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, matches[0]); found = type_node->kind != RDI_TypeKind_NULL; key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)matches[0]); } @@ -838,12 +815,11 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8 //- rjf: form namespaceified fallback versions of this lookup string String8List namespaceified_token_strings = {0}; - if(ctx->rdi->procedures != 0 && ctx->rdi->scopes != 0 && ctx->rdi->scope_vmap != 0) { - U64 scope_idx = rdi_vmap_idx_from_voff(ctx->rdi->scope_vmap, ctx->rdi->scope_vmap_count, ctx->ip_voff); - RDI_Scope *scope = &ctx->rdi->scopes[scope_idx]; + U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(ctx->rdi, RDI_SectionKind_ScopeVMap, ctx->ip_voff); + RDI_Scope *scope = rdi_element_from_name_idx(ctx->rdi, Scopes, scope_idx); U64 proc_idx = scope->proc_idx; - RDI_Procedure *procedure = &ctx->rdi->procedures[proc_idx]; + RDI_Procedure *procedure = rdi_element_from_name_idx(ctx->rdi, Procedures, proc_idx); U64 name_size = 0; U8 *name_ptr = rdi_string_from_idx(ctx->rdi, procedure->name_string_idx, &name_size); String8 containing_procedure_name = str8(name_ptr, name_size); @@ -883,8 +859,8 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8 { mapped_identifier = 1; identifier_type_is_possibly_dynamically_overridden = 1; - RDI_Local *local_var = rdi_element_from_idx(ctx->rdi, locals, local_num-1); - RDI_TypeNode *type_node = rdi_element_from_idx(ctx->rdi, type_nodes, local_var->type_idx); + RDI_Local *local_var = rdi_element_from_name_idx(ctx->rdi, Locals, local_num-1); + RDI_TypeNode *type_node = rdi_element_from_name_idx(ctx->rdi, TypeNodes, local_var->type_idx); type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)local_var->type_idx); // rjf: grab location info @@ -892,19 +868,21 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8 loc_block_idx < local_var->location_opl; loc_block_idx += 1) { - RDI_LocationBlock *block = &ctx->rdi->location_blocks[loc_block_idx]; + RDI_LocationBlock *block = rdi_element_from_name_idx(ctx->rdi, LocationBlocks, loc_block_idx); if(block->scope_off_first <= ctx->ip_voff && ctx->ip_voff < block->scope_off_opl) { - loc_kind = *((RDI_LocationKind *)(ctx->rdi->location_data + block->location_data_off)); + U64 all_location_data_size = 0; + U8 *all_location_data = rdi_table_from_name(ctx->rdi, LocationData, &all_location_data_size); + loc_kind = *((RDI_LocationKind *)(all_location_data + block->location_data_off)); switch(loc_kind) { default:{mapped_identifier = 0;}break; case RDI_LocationKind_AddrBytecodeStream: case RDI_LocationKind_ValBytecodeStream: { - U8 *bytecode_base = ctx->rdi->location_data + block->location_data_off + sizeof(RDI_LocationKind); + U8 *bytecode_base = all_location_data + block->location_data_off + sizeof(RDI_LocationKind); U64 bytecode_size = 0; - for(U64 idx = 0; idx < ctx->rdi->location_data_size; idx += 1) + for(U64 idx = 0; idx < all_location_data_size; idx += 1) { U8 op = bytecode_base[idx]; if(op == 0) @@ -920,11 +898,11 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8 case RDI_LocationKind_AddrRegPlusU16: case RDI_LocationKind_AddrAddrRegPlusU16: { - MemoryCopy(&loc_reg_u16, (ctx->rdi->location_data + block->location_data_off), sizeof(loc_reg_u16)); + MemoryCopy(&loc_reg_u16, (all_location_data + block->location_data_off), sizeof(loc_reg_u16)); }break; case RDI_LocationKind_ValReg: { - MemoryCopy(&loc_reg, (ctx->rdi->location_data + block->location_data_off), sizeof(loc_reg)); + MemoryCopy(&loc_reg, (all_location_data + block->location_data_off), sizeof(loc_reg)); }break; } } @@ -959,120 +937,102 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8 //- rjf: try global variables if(mapped_identifier == 0) { - RDI_NameMap *name_map = rdi_name_map_from_kind(ctx->rdi, RDI_NameMapKind_GlobalVariables); - if(name_map != 0 && ctx->rdi->global_variables != 0) + RDI_NameMap *name_map = rdi_element_from_name_idx(ctx->rdi, NameMaps, RDI_NameMapKind_GlobalVariables); + RDI_ParsedNameMap parsed_name_map = {0}; + rdi_parsed_from_name_map(ctx->rdi, name_map, &parsed_name_map); + RDI_NameMapNode *node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, token_string.str, token_string.size); + U32 matches_count = 0; + U32 *matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); + for(String8Node *n = namespaceified_token_strings.first; + n != 0 && matches_count == 0; + n = n->next) { - RDI_ParsedNameMap parsed_name_map = {0}; - rdi_name_map_parse(ctx->rdi, name_map, &parsed_name_map); - RDI_NameMapNode *node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, token_string.str, token_string.size); - U32 matches_count = 0; - U32 *matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); - for(String8Node *n = namespaceified_token_strings.first; - n != 0 && matches_count == 0; - n = n->next) - { - node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, n->string.str, n->string.size); - matches_count = 0; - matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); - } - if(matches_count != 0) - { - // NOTE(rjf): apparently, PDBs can be produced such that they - // also keep stale *GLOBAL VARIABLE SYMBOLS* around too. I - // don't know of a magic hash table fixup path in PDBs, so - // in this case, I'm going to prefer the latest-added global. - U32 match_idx = matches[matches_count-1]; - RDI_GlobalVariable *global_var = &ctx->rdi->global_variables[match_idx]; - EVAL_OpList oplist = {0}; - eval_oplist_push_op(arena, &oplist, RDI_EvalOp_ModuleOff, global_var->voff); - loc_kind = RDI_LocationKind_AddrBytecodeStream; - loc_bytecode = eval_bytecode_from_oplist(arena, &oplist); - U32 type_idx = global_var->type_idx; - if(type_idx < ctx->rdi->type_nodes_count) - { - RDI_TypeNode *type_node = &ctx->rdi->type_nodes[type_idx]; - type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)type_idx); - } - mapped_identifier = 1; - } + node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, n->string.str, n->string.size); + matches_count = 0; + matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); + } + if(matches_count != 0) + { + // NOTE(rjf): apparently, PDBs can be produced such that they + // also keep stale *GLOBAL VARIABLE SYMBOLS* around too. I + // don't know of a magic hash table fixup path in PDBs, so + // in this case, I'm going to prefer the latest-added global. + U32 match_idx = matches[matches_count-1]; + RDI_GlobalVariable *global_var = rdi_element_from_name_idx(ctx->rdi, GlobalVariables, match_idx); + EVAL_OpList oplist = {0}; + eval_oplist_push_op(arena, &oplist, RDI_EvalOp_ModuleOff, global_var->voff); + loc_kind = RDI_LocationKind_AddrBytecodeStream; + loc_bytecode = eval_bytecode_from_oplist(arena, &oplist); + U32 type_idx = global_var->type_idx; + RDI_TypeNode *type_node = rdi_element_from_name_idx(ctx->rdi, TypeNodes, type_idx); + type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)type_idx); + mapped_identifier = 1; } } //- rjf: try thread variables if(mapped_identifier == 0) { - RDI_NameMap *name_map = rdi_name_map_from_kind(ctx->rdi, RDI_NameMapKind_ThreadVariables); - if(name_map != 0 && ctx->rdi->global_variables != 0) + RDI_NameMap *name_map = rdi_element_from_name_idx(ctx->rdi, NameMaps, RDI_NameMapKind_ThreadVariables); + RDI_ParsedNameMap parsed_name_map = {0}; + rdi_parsed_from_name_map(ctx->rdi, name_map, &parsed_name_map); + RDI_NameMapNode *node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, token_string.str, token_string.size); + U32 matches_count = 0; + U32 *matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); + for(String8Node *n = namespaceified_token_strings.first; + n != 0 && matches_count == 0; + n = n->next) { - RDI_ParsedNameMap parsed_name_map = {0}; - rdi_name_map_parse(ctx->rdi, name_map, &parsed_name_map); - RDI_NameMapNode *node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, token_string.str, token_string.size); - U32 matches_count = 0; - U32 *matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); - for(String8Node *n = namespaceified_token_strings.first; - n != 0 && matches_count == 0; - n = n->next) - { - node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, n->string.str, n->string.size); - matches_count = 0; - matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); - } - if(matches_count != 0) - { - U32 match_idx = matches[0]; - RDI_ThreadVariable *thread_var = &ctx->rdi->thread_variables[match_idx]; - EVAL_OpList oplist = {0}; - eval_oplist_push_op(arena, &oplist, RDI_EvalOp_TLSOff, thread_var->tls_off); - loc_kind = RDI_LocationKind_AddrBytecodeStream; - loc_bytecode = eval_bytecode_from_oplist(arena, &oplist); - U32 type_idx = thread_var->type_idx; - if(type_idx < ctx->rdi->type_nodes_count) - { - RDI_TypeNode *type_node = &ctx->rdi->type_nodes[type_idx]; - type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)type_idx); - } - mapped_identifier = 1; - } + node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, n->string.str, n->string.size); + matches_count = 0; + matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); + } + if(matches_count != 0) + { + U32 match_idx = matches[0]; + RDI_ThreadVariable *thread_var = rdi_element_from_name_idx(ctx->rdi, ThreadVariables, match_idx); + EVAL_OpList oplist = {0}; + eval_oplist_push_op(arena, &oplist, RDI_EvalOp_TLSOff, thread_var->tls_off); + loc_kind = RDI_LocationKind_AddrBytecodeStream; + loc_bytecode = eval_bytecode_from_oplist(arena, &oplist); + U32 type_idx = thread_var->type_idx; + RDI_TypeNode *type_node = rdi_element_from_name_idx(ctx->rdi, TypeNodes, type_idx); + type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)type_idx); + mapped_identifier = 1; } } //- rjf: try procedures if(mapped_identifier == 0) { - RDI_NameMap *name_map = rdi_name_map_from_kind(ctx->rdi, RDI_NameMapKind_Procedures); - if(name_map != 0 && ctx->rdi->procedures != 0 && ctx->rdi->scopes != 0 && ctx->rdi->scope_voffs) + RDI_NameMap *name_map = rdi_element_from_name_idx(ctx->rdi, NameMaps, RDI_NameMapKind_Procedures); + RDI_ParsedNameMap parsed_name_map = {0}; + rdi_parsed_from_name_map(ctx->rdi, name_map, &parsed_name_map); + RDI_NameMapNode *node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, token_string.str, token_string.size); + U32 matches_count = 0; + U32 *matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); + for(String8Node *n = namespaceified_token_strings.first; + n != 0 && matches_count == 0; + n = n->next) { - RDI_ParsedNameMap parsed_name_map = {0}; - rdi_name_map_parse(ctx->rdi, name_map, &parsed_name_map); - RDI_NameMapNode *node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, token_string.str, token_string.size); - U32 matches_count = 0; - U32 *matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); - for(String8Node *n = namespaceified_token_strings.first; - n != 0 && matches_count == 0; - n = n->next) - { - node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, n->string.str, n->string.size); - matches_count = 0; - matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); - } - if(matches_count != 0) - { - U32 match_idx = matches[0]; - RDI_Procedure *procedure = &ctx->rdi->procedures[match_idx]; - RDI_Scope *scope = &ctx->rdi->scopes[procedure->root_scope_idx]; - U64 voff = ctx->rdi->scope_voffs[scope->voff_range_first]; - EVAL_OpList oplist = {0}; - eval_oplist_push_op(arena, &oplist, RDI_EvalOp_ModuleOff, voff); - loc_kind = RDI_LocationKind_ValBytecodeStream; - loc_bytecode = eval_bytecode_from_oplist(arena, &oplist); - U32 type_idx = procedure->type_idx; - if(type_idx < ctx->rdi->type_nodes_count) - { - RDI_TypeNode *type_node = &ctx->rdi->type_nodes[type_idx]; - type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)type_idx); - } - mapped_identifier = 1; - } + node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, n->string.str, n->string.size); + matches_count = 0; + matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); + } + if(matches_count != 0) + { + U32 match_idx = matches[0]; + RDI_Procedure *procedure = rdi_element_from_name_idx(ctx->rdi, Procedures, match_idx); + RDI_Scope *scope = rdi_element_from_name_idx(ctx->rdi, Scopes, procedure->root_scope_idx); + U64 voff = *rdi_element_from_name_idx(ctx->rdi, ScopeVOffData, scope->voff_range_first); + EVAL_OpList oplist = {0}; + eval_oplist_push_op(arena, &oplist, RDI_EvalOp_ModuleOff, voff); + loc_kind = RDI_LocationKind_ValBytecodeStream; + loc_bytecode = eval_bytecode_from_oplist(arena, &oplist); + U32 type_idx = procedure->type_idx; + RDI_TypeNode *type_node = rdi_element_from_name_idx(ctx->rdi, TypeNodes, type_idx); + type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)type_idx); + mapped_identifier = 1; } } diff --git a/src/fuzzy_search/fuzzy_search.c b/src/fuzzy_search/fuzzy_search.c index 24cc8b13..49f2bbe9 100644 --- a/src/fuzzy_search/fuzzy_search.c +++ b/src/fuzzy_search/fuzzy_search.c @@ -52,29 +52,29 @@ fzy_item_string_from_rdi_target_element_idx(RDI_Parsed *rdi, FZY_Target target, // NOTE(rjf): no default - warn if we miss a case case FZY_Target_Procedures: { - RDI_Procedure *proc = rdi_element_from_idx(rdi, procedures, element_idx); + RDI_Procedure *proc = rdi_element_from_name_idx(rdi, Procedures, element_idx); U64 name_size = 0; U8 *name_base = rdi_string_from_idx(rdi, proc->name_string_idx, &name_size); result = str8(name_base, name_size); }break; case FZY_Target_GlobalVariables: { - RDI_GlobalVariable *gvar = rdi_element_from_idx(rdi, global_variables, element_idx); + RDI_GlobalVariable *gvar = rdi_element_from_name_idx(rdi, GlobalVariables, element_idx); U64 name_size = 0; U8 *name_base = rdi_string_from_idx(rdi, gvar->name_string_idx, &name_size); result = str8(name_base, name_size); }break; case FZY_Target_ThreadVariables: { - RDI_ThreadVariable *tvar = rdi_element_from_idx(rdi, thread_variables, element_idx); + RDI_ThreadVariable *tvar = rdi_element_from_name_idx(rdi, ThreadVariables, element_idx); U64 name_size = 0; U8 *name_base = rdi_string_from_idx(rdi, tvar->name_string_idx, &name_size); result = str8(name_base, name_size); }break; case FZY_Target_UDTs: { - RDI_UDT *udt = rdi_element_from_idx(rdi, udts, element_idx); - RDI_TypeNode *type_node = rdi_element_from_idx(rdi, type_nodes, udt->self_type_idx); + RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, element_idx); + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); U64 name_size = 0; U8 *name_base = rdi_string_from_idx(rdi, type_node->user_defined.name_string_idx, &name_size); result = str8(name_base, name_size); @@ -407,10 +407,8 @@ fzy_search_thread__entry_point(void *p) //////////////////////////// //- rjf: search target -> info about search space // - U64 table_ptr_off = 0; - U64 table_count_off = 0; + RDI_SectionKind section_kind = RDI_SectionKind_NULL; U64 element_name_idx_off = 0; - U64 element_size = 0; if(task_is_good) { switch(params.target) @@ -419,30 +417,22 @@ fzy_search_thread__entry_point(void *p) case FZY_Target_COUNT:{}break; case FZY_Target_Procedures: { - table_ptr_off = OffsetOf(RDI_Parsed, procedures); - table_count_off = OffsetOf(RDI_Parsed, procedures_count); + section_kind = RDI_SectionKind_Procedures; element_name_idx_off = OffsetOf(RDI_Procedure, name_string_idx); - element_size = sizeof(RDI_Procedure); }break; case FZY_Target_GlobalVariables: { - table_ptr_off = OffsetOf(RDI_Parsed, global_variables); - table_count_off = OffsetOf(RDI_Parsed, global_variables_count); + section_kind = RDI_SectionKind_GlobalVariables; element_name_idx_off = OffsetOf(RDI_GlobalVariable, name_string_idx); - element_size = sizeof(RDI_GlobalVariable); }break; case FZY_Target_ThreadVariables: { - table_ptr_off = OffsetOf(RDI_Parsed, thread_variables); - table_count_off = OffsetOf(RDI_Parsed, thread_variables_count); + section_kind = RDI_SectionKind_ThreadVariables; element_name_idx_off = OffsetOf(RDI_ThreadVariable, name_string_idx); - element_size = sizeof(RDI_ThreadVariable); }break; case FZY_Target_UDTs: { - table_ptr_off = OffsetOf(RDI_Parsed, udts); - table_count_off = OffsetOf(RDI_Parsed, udts_count); - element_size = sizeof(RDI_UDT); + section_kind = RDI_SectionKind_UDTs; }break; } } @@ -457,8 +447,9 @@ fzy_search_thread__entry_point(void *p) for(U64 rdi_idx = 0; rdi_idx < rdis_count; rdi_idx += 1) { RDI_Parsed *rdi = rdis[rdi_idx]; - void *table_base = (U8*)rdi + table_ptr_off; - U64 element_count = *MemberFromOffset(U64 *, rdi, table_count_off); + U64 element_count = 0; + void *table_base = rdi_section_raw_table_from_kind(rdi, section_kind, &element_count); + U64 element_size = rdi_section_element_size_table[section_kind]; for(U64 idx = 1; task_is_good && idx < element_count; idx += 1) { void *element = (U8 *)(*(void **)table_base) + element_size*idx; @@ -466,7 +457,7 @@ fzy_search_thread__entry_point(void *p) if(params.target == FZY_Target_UDTs) { RDI_UDT *udt = (RDI_UDT *)element; - RDI_TypeNode *type_node = rdi_element_from_idx(rdi, type_nodes, udt->self_type_idx); + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); name_idx_ptr = &type_node->user_defined.name_string_idx; } U32 name_idx = *name_idx_ptr; diff --git a/src/lib_rdi_format/rdi_format.c b/src/lib_rdi_format/rdi_format.c index ef9eea1b..71243041 100644 --- a/src/lib_rdi_format/rdi_format.c +++ b/src/lib_rdi_format/rdi_format.c @@ -10,6 +10,88 @@ #ifndef RDI_FORMAT_C #define RDI_FORMAT_C +RDI_U16 rdi_section_element_size_table[37] = +{ +sizeof(RDI_U8), +sizeof(RDI_TopLevelInfo), +sizeof(RDI_U8), +sizeof(RDI_U32), +sizeof(RDI_U32), +sizeof(RDI_BinarySection), +sizeof(RDI_FilePathNode), +sizeof(RDI_SourceFile), +sizeof(RDI_LineTable), +sizeof(RDI_U64), +sizeof(RDI_Line), +sizeof(RDI_Column), +sizeof(RDI_SourceLineMap), +sizeof(RDI_U32), +sizeof(RDI_U32), +sizeof(RDI_U64), +sizeof(RDI_Unit), +sizeof(RDI_VMapEntry), +sizeof(RDI_TypeNode), +sizeof(RDI_UDT), +sizeof(RDI_Member), +sizeof(RDI_EnumMember), +sizeof(RDI_GlobalVariable), +sizeof(RDI_VMapEntry), +sizeof(RDI_ThreadVariable), +sizeof(RDI_Procedure), +sizeof(RDI_Scope), +sizeof(RDI_U64), +sizeof(RDI_VMapEntry), +sizeof(RDI_InlineSite), +sizeof(RDI_Local), +sizeof(RDI_LocationBlock), +sizeof(RDI_U8), +sizeof(RDI_NameMap), +sizeof(RDI_NameMapBucket), +sizeof(RDI_NameMapNode), +sizeof(RDI_U8), +}; + +RDI_U8 rdi_section_is_required_table[37] = +{ +0, +0, +1, +1, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +}; + RDI_U8 rdi_eval_op_ctrlbits_table[45] = { RDI_EVAL_CTRLBITS(0, 0, 0), diff --git a/src/lib_rdi_format/rdi_format.h b/src/lib_rdi_format/rdi_format.h index 298a54c5..eb8ea99e 100644 --- a/src/lib_rdi_format/rdi_format.h +++ b/src/lib_rdi_format/rdi_format.h @@ -40,65 +40,71 @@ typedef int32_t RDI_S32; typedef int64_t RDI_S64; #endif +//////////////////////////////////////////////////////////////// +//~ Overridable Enabling/Disabling Of Table Index Typechecking + +#if !defined(RDI_DISABLE_TABLE_INDEX_TYPECHECKING) +# define RDI_DISABLE_TABLE_INDEX_TYPECHECKING 0 +#endif + //////////////////////////////////////////////////////////////// //~ Format Constants // \"raddbg\0\0\" #define RDI_MAGIC_CONSTANT 0x0000676264646172 -#define RDI_ENCODING_VERSION 3 +#define RDI_ENCODING_VERSION 4 //////////////////////////////////////////////////////////////// //~ Format Types & Functions -typedef RDI_U32 RDI_DataSectionTag; -typedef enum RDI_DataSectionTagEnum +typedef RDI_U32 RDI_SectionKind; +typedef enum RDI_SectionKindEnum { -RDI_DataSectionTag_NULL = 0x0000, -RDI_DataSectionTag_TopLevelInfo = 0x0001, -RDI_DataSectionTag_StringData = 0x0002, -RDI_DataSectionTag_StringTable = 0x0003, -RDI_DataSectionTag_IndexRuns = 0x0004, -RDI_DataSectionTag_BinarySections = 0x0005, -RDI_DataSectionTag_FilePathNodes = 0x0006, -RDI_DataSectionTag_SourceFiles = 0x0007, -RDI_DataSectionTag_LineTables = 0x0008, -RDI_DataSectionTag_LineInfoVoffs = 0x0009, -RDI_DataSectionTag_LineInfoLines = 0x000A, -RDI_DataSectionTag_LineInfoColumns = 0x000B, -RDI_DataSectionTag_SourceLineMaps = 0x000C, -RDI_DataSectionTag_SourceLineMapNumbers = 0x000D, -RDI_DataSectionTag_SourceLineMapRanges = 0x000E, -RDI_DataSectionTag_SourceLineMapVOffs = 0x000F, -RDI_DataSectionTag_Units = 0x0010, -RDI_DataSectionTag_UnitVmap = 0x0011, -RDI_DataSectionTag_TypeNodes = 0x0012, -RDI_DataSectionTag_UDTs = 0x0013, -RDI_DataSectionTag_Members = 0x0014, -RDI_DataSectionTag_EnumMembers = 0x0015, -RDI_DataSectionTag_GlobalVariables = 0x0016, -RDI_DataSectionTag_GlobalVmap = 0x0017, -RDI_DataSectionTag_ThreadVariables = 0x0018, -RDI_DataSectionTag_Procedures = 0x0019, -RDI_DataSectionTag_Scopes = 0x001A, -RDI_DataSectionTag_ScopeVoffData = 0x001B, -RDI_DataSectionTag_ScopeVmap = 0x001C, -RDI_DataSectionTag_InlineSites = 0x001D, -RDI_DataSectionTag_Locals = 0x001E, -RDI_DataSectionTag_LocationBlocks = 0x001F, -RDI_DataSectionTag_LocationData = 0x0020, -RDI_DataSectionTag_NameMaps = 0x0021, -RDI_DataSectionTag_PRIMARY_COUNT = 0x0022, -RDI_DataSectionTag_SECONDARY = 0x80000000, -RDI_DataSectionTag_NameMapBuckets = RDI_DataSectionTag_SECONDARY|0x0001, -RDI_DataSectionTag_NameMapNodes = RDI_DataSectionTag_SECONDARY|0x0002, -} RDI_DataSectionTagEnum; +RDI_SectionKind_NULL = 0x0000, +RDI_SectionKind_TopLevelInfo = 0x0001, +RDI_SectionKind_StringData = 0x0002, +RDI_SectionKind_StringTable = 0x0003, +RDI_SectionKind_IndexRuns = 0x0004, +RDI_SectionKind_BinarySections = 0x0005, +RDI_SectionKind_FilePathNodes = 0x0006, +RDI_SectionKind_SourceFiles = 0x0007, +RDI_SectionKind_LineTables = 0x0008, +RDI_SectionKind_LineInfoVOffs = 0x0009, +RDI_SectionKind_LineInfoLines = 0x000A, +RDI_SectionKind_LineInfoColumns = 0x000B, +RDI_SectionKind_SourceLineMaps = 0x000C, +RDI_SectionKind_SourceLineMapNumbers = 0x000D, +RDI_SectionKind_SourceLineMapRanges = 0x000E, +RDI_SectionKind_SourceLineMapVOffs = 0x000F, +RDI_SectionKind_Units = 0x0010, +RDI_SectionKind_UnitVMap = 0x0011, +RDI_SectionKind_TypeNodes = 0x0012, +RDI_SectionKind_UDTs = 0x0013, +RDI_SectionKind_Members = 0x0014, +RDI_SectionKind_EnumMembers = 0x0015, +RDI_SectionKind_GlobalVariables = 0x0016, +RDI_SectionKind_GlobalVMap = 0x0017, +RDI_SectionKind_ThreadVariables = 0x0018, +RDI_SectionKind_Procedures = 0x0019, +RDI_SectionKind_Scopes = 0x001A, +RDI_SectionKind_ScopeVOffData = 0x001B, +RDI_SectionKind_ScopeVMap = 0x001C, +RDI_SectionKind_InlineSites = 0x001D, +RDI_SectionKind_Locals = 0x001E, +RDI_SectionKind_LocationBlocks = 0x001F, +RDI_SectionKind_LocationData = 0x0020, +RDI_SectionKind_NameMaps = 0x0021, +RDI_SectionKind_NameMapBuckets = 0x0022, +RDI_SectionKind_NameMapNodes = 0x0023, +RDI_SectionKind_COUNT = 0x0024, +} RDI_SectionKindEnum; -typedef RDI_U32 RDI_DataSectionEncoding; -typedef enum RDI_DataSectionEncodingEnum +typedef RDI_U32 RDI_SectionEncoding; +typedef enum RDI_SectionEncodingEnum { -RDI_DataSectionEncoding_Unpacked = 0, -RDI_DataSectionEncoding_LZB = 1, -} RDI_DataSectionEncodingEnum; +RDI_SectionEncoding_Unpacked = 0, +RDI_SectionEncoding_LZB = 1, +} RDI_SectionEncodingEnum; typedef RDI_U32 RDI_Arch; typedef enum RDI_ArchEnum @@ -494,53 +500,51 @@ X(RDI_U32, encoding_version)\ X(RDI_U32, data_section_off)\ X(RDI_U32, data_section_count)\ -#define RDI_DataSectionTag_XList \ -X(NULL)\ -X(TopLevelInfo)\ -X(StringData)\ -X(StringTable)\ -X(IndexRuns)\ -X(BinarySections)\ -X(FilePathNodes)\ -X(SourceFiles)\ -X(LineTables)\ -X(LineInfoVoffs)\ -X(LineInfoLines)\ -X(LineInfoColumns)\ -X(SourceLineMaps)\ -X(SourceLineMapNumbers)\ -X(SourceLineMapRanges)\ -X(SourceLineMapVOffs)\ -X(Units)\ -X(UnitVmap)\ -X(TypeNodes)\ -X(UDTs)\ -X(Members)\ -X(EnumMembers)\ -X(GlobalVariables)\ -X(GlobalVmap)\ -X(ThreadVariables)\ -X(Procedures)\ -X(Scopes)\ -X(ScopeVoffData)\ -X(ScopeVmap)\ -X(InlineSites)\ -X(Locals)\ -X(LocationBlocks)\ -X(LocationData)\ -X(NameMaps)\ -X(PRIMARY_COUNT)\ -X(SECONDARY)\ -X(NameMapBuckets)\ -X(NameMapNodes)\ +#define RDI_SectionKind_XList \ +X(NULL, null, RDI_U8)\ +X(TopLevelInfo, top_level_info, RDI_TopLevelInfo)\ +X(StringData, string_data, RDI_U8)\ +X(StringTable, string_table, RDI_U32)\ +X(IndexRuns, index_runs, RDI_U32)\ +X(BinarySections, binary_sections, RDI_BinarySection)\ +X(FilePathNodes, file_path_nodes, RDI_FilePathNode)\ +X(SourceFiles, source_files, RDI_SourceFile)\ +X(LineTables, line_tables, RDI_LineTable)\ +X(LineInfoVOffs, line_info_voffs, RDI_U64)\ +X(LineInfoLines, line_info_lines, RDI_Line)\ +X(LineInfoColumns, line_info_columns, RDI_Column)\ +X(SourceLineMaps, source_line_maps, RDI_SourceLineMap)\ +X(SourceLineMapNumbers, source_line_map_numbers, RDI_U32)\ +X(SourceLineMapRanges, source_line_map_ranges, RDI_U32)\ +X(SourceLineMapVOffs, source_line_map_voffs, RDI_U64)\ +X(Units, units, RDI_Unit)\ +X(UnitVMap, unit_vmap, RDI_VMapEntry)\ +X(TypeNodes, type_nodes, RDI_TypeNode)\ +X(UDTs, udts, RDI_UDT)\ +X(Members, members, RDI_Member)\ +X(EnumMembers, enum_members, RDI_EnumMember)\ +X(GlobalVariables, global_variables, RDI_GlobalVariable)\ +X(GlobalVMap, global_vmap, RDI_VMapEntry)\ +X(ThreadVariables, thread_variables, RDI_ThreadVariable)\ +X(Procedures, procedures, RDI_Procedure)\ +X(Scopes, scopes, RDI_Scope)\ +X(ScopeVOffData, scope_voff_data, RDI_U64)\ +X(ScopeVMap, scope_vmap, RDI_VMapEntry)\ +X(InlineSites, inline_sites, RDI_InlineSite)\ +X(Locals, locals, RDI_Local)\ +X(LocationBlocks, location_blocks, RDI_LocationBlock)\ +X(LocationData, location_data, RDI_U8)\ +X(NameMaps, name_maps, RDI_NameMap)\ +X(NameMapBuckets, name_map_buckets, RDI_NameMapBucket)\ +X(NameMapNodes, name_map_nodes, RDI_NameMapNode)\ -#define RDI_DataSectionEncoding_XList \ +#define RDI_SectionEncoding_XList \ X(Unpacked)\ X(LZB)\ -#define RDI_DataSection_XList \ -X(RDI_DataSectionTag, tag)\ -X(RDI_DataSectionEncoding, encoding)\ +#define RDI_Section_XList \ +X(RDI_SectionEncoding, encoding)\ +X(RDI_U32, pad)\ X(RDI_U64, off)\ X(RDI_U64, encoded_size)\ X(RDI_U64, unpacked_size)\ @@ -885,8 +889,10 @@ X(COUNT)\ #define RDI_NameMap_XList \ X(RDI_NameMapKind, kind)\ -X(RDI_U32, bucket_data_idx)\ -X(RDI_U32, node_data_idx)\ +X(RDI_U32, bucket_base_idx)\ +X(RDI_U32, node_base_idx)\ +X(RDI_U32, bucket_count)\ +X(RDI_U32, node_count)\ #define RDI_NameMapBucket_XList \ X(RDI_U32, first_node)\ @@ -897,6 +903,72 @@ X(RDI_U32, string_idx)\ X(RDI_U32, match_count)\ X(RDI_U32, match_idx_or_idx_run_first)\ +#if !RDI_DISABLE_TABLE_INDEX_TYPECHECKING +typedef struct RDI_U32_StringTable { RDI_U32 v; } RDI_U32_StringTable; +typedef struct RDI_U32_IndexRuns { RDI_U32 v; } RDI_U32_IndexRuns; +typedef struct RDI_U32_BinarySections { RDI_U32 v; } RDI_U32_BinarySections; +typedef struct RDI_U32_FilePathNodes { RDI_U32 v; } RDI_U32_FilePathNodes; +typedef struct RDI_U32_SourceFiles { RDI_U32 v; } RDI_U32_SourceFiles; +typedef struct RDI_U32_LineTables { RDI_U32 v; } RDI_U32_LineTables; +typedef struct RDI_U32_LineInfoVOffs { RDI_U32 v; } RDI_U32_LineInfoVOffs; +typedef struct RDI_U32_LineInfoLines { RDI_U32 v; } RDI_U32_LineInfoLines; +typedef struct RDI_U32_LineInfoColumns { RDI_U32 v; } RDI_U32_LineInfoColumns; +typedef struct RDI_U32_SourceLineMaps { RDI_U32 v; } RDI_U32_SourceLineMaps; +typedef struct RDI_U32_SourceLineMapNumbers { RDI_U32 v; } RDI_U32_SourceLineMapNumbers; +typedef struct RDI_U32_SourceLineMapRanges { RDI_U32 v; } RDI_U32_SourceLineMapRanges; +typedef struct RDI_U32_SourceLineMapVOffs { RDI_U32 v; } RDI_U32_SourceLineMapVOffs; +typedef struct RDI_U32_Units { RDI_U32 v; } RDI_U32_Units; +typedef struct RDI_U32_TypeNodes { RDI_U32 v; } RDI_U32_TypeNodes; +typedef struct RDI_U32_UDTs { RDI_U32 v; } RDI_U32_UDTs; +typedef struct RDI_U32_Members { RDI_U32 v; } RDI_U32_Members; +typedef struct RDI_U32_EnumMembers { RDI_U32 v; } RDI_U32_EnumMembers; +typedef struct RDI_U32_GlobalVariables { RDI_U32 v; } RDI_U32_GlobalVariables; +typedef struct RDI_U32_ThreadVariables { RDI_U32 v; } RDI_U32_ThreadVariables; +typedef struct RDI_U32_Procedures { RDI_U32 v; } RDI_U32_Procedures; +typedef struct RDI_U32_Scopes { RDI_U32 v; } RDI_U32_Scopes; +typedef struct RDI_U32_ScopeVOffData { RDI_U32 v; } RDI_U32_ScopeVOffData; +typedef struct RDI_U32_InlineSites { RDI_U32 v; } RDI_U32_InlineSites; +typedef struct RDI_U32_Locals { RDI_U32 v; } RDI_U32_Locals; +typedef struct RDI_U32_LocationBlocks { RDI_U32 v; } RDI_U32_LocationBlocks; +typedef struct RDI_U32_LocationData { RDI_U32 v; } RDI_U32_LocationData; +typedef struct RDI_U32_NameMaps { RDI_U32 v; } RDI_U32_NameMaps; +typedef struct RDI_U32_NameMapBuckets { RDI_U32 v; } RDI_U32_NameMapBuckets; +typedef struct RDI_U32_NameMapNodes { RDI_U32 v; } RDI_U32_NameMapNodes; +#else +typedef struct RDI_U32_Table { RDI_U32 v; } RDI_U32_Table; +typedef struct RDI_U64_Table { RDI_U64 v; } RDI_U64_Table; +typedef RDI_U32_Table RDI_U32_StringTable; +typedef RDI_U32_Table RDI_U32_IndexRuns; +typedef RDI_U32_Table RDI_U32_BinarySections; +typedef RDI_U32_Table RDI_U32_FilePathNodes; +typedef RDI_U32_Table RDI_U32_SourceFiles; +typedef RDI_U32_Table RDI_U32_LineTables; +typedef RDI_U32_Table RDI_U32_LineInfoVOffs; +typedef RDI_U32_Table RDI_U32_LineInfoLines; +typedef RDI_U32_Table RDI_U32_LineInfoColumns; +typedef RDI_U32_Table RDI_U32_SourceLineMaps; +typedef RDI_U32_Table RDI_U32_SourceLineMapNumbers; +typedef RDI_U32_Table RDI_U32_SourceLineMapRanges; +typedef RDI_U32_Table RDI_U32_SourceLineMapVOffs; +typedef RDI_U32_Table RDI_U32_Units; +typedef RDI_U32_Table RDI_U32_TypeNodes; +typedef RDI_U32_Table RDI_U32_UDTs; +typedef RDI_U32_Table RDI_U32_Members; +typedef RDI_U32_Table RDI_U32_EnumMembers; +typedef RDI_U32_Table RDI_U32_GlobalVariables; +typedef RDI_U32_Table RDI_U32_ThreadVariables; +typedef RDI_U32_Table RDI_U32_Procedures; +typedef RDI_U32_Table RDI_U32_Scopes; +typedef RDI_U32_Table RDI_U32_ScopeVOffData; +typedef RDI_U32_Table RDI_U32_InlineSites; +typedef RDI_U32_Table RDI_U32_Locals; +typedef RDI_U32_Table RDI_U32_LocationBlocks; +typedef RDI_U32_Table RDI_U32_LocationData; +typedef RDI_U32_Table RDI_U32_NameMaps; +typedef RDI_U32_Table RDI_U32_NameMapBuckets; +typedef RDI_U32_Table RDI_U32_NameMapNodes; +#endif + #define RDI_EVAL_CTRLBITS(decodeN,popN,pushN) ((decodeN) | ((popN) << 4) | ((pushN) << 6)) #define RDI_DECODEN_FROM_CTRLBITS(ctrlbits) ((ctrlbits) & 0xf) #define RDI_POPN_FROM_CTRLBITS(ctrlbits) (((ctrlbits) >> 4) & 0x3) @@ -912,11 +984,11 @@ RDI_U32 data_section_off; RDI_U32 data_section_count; }; -typedef struct RDI_DataSection RDI_DataSection; -struct RDI_DataSection +typedef struct RDI_Section RDI_Section; +struct RDI_Section { -RDI_DataSectionTag tag; -RDI_DataSectionEncoding encoding; +RDI_SectionEncoding encoding; +RDI_U32 pad; RDI_U64 off; RDI_U64 encoded_size; RDI_U64 unpacked_size; @@ -1034,13 +1106,15 @@ RDI_U32 byte_size; { RDI_U32 direct_type_idx; RDI_U32 count; - union{ + union + { // when kind is 'Function' or 'Method' RDI_U32 param_idx_run_first; // when kind is 'MemberPtr' RDI_U32 owner_type_idx; }; - } constructed; + } + constructed; // kind is 'user defined' struct @@ -1048,7 +1122,8 @@ RDI_U32 byte_size; RDI_U32 name_string_idx; RDI_U32 direct_type_idx; RDI_U32 udt_idx; - } user_defined; + } + user_defined; // (kind = Bitfield) struct @@ -1056,7 +1131,8 @@ RDI_U32 byte_size; RDI_U32 direct_type_idx; RDI_U32 off; RDI_U32 size; - } bitfield; + } + bitfield; } ; }; @@ -1193,8 +1269,10 @@ typedef struct RDI_NameMap RDI_NameMap; struct RDI_NameMap { RDI_NameMapKind kind; -RDI_U32 bucket_data_idx; -RDI_U32 node_data_idx; +RDI_U32 bucket_base_idx; +RDI_U32 node_base_idx; +RDI_U32 bucket_count; +RDI_U32 node_count; }; typedef struct RDI_NameMapBucket RDI_NameMapBucket; @@ -1212,6 +1290,43 @@ RDI_U32 match_count; RDI_U32 match_idx_or_idx_run_first; }; +typedef RDI_U8 RDI_SectionElementType_NULL; +typedef RDI_TopLevelInfo RDI_SectionElementType_TopLevelInfo; +typedef RDI_U8 RDI_SectionElementType_StringData; +typedef RDI_U32 RDI_SectionElementType_StringTable; +typedef RDI_U32 RDI_SectionElementType_IndexRuns; +typedef RDI_BinarySection RDI_SectionElementType_BinarySections; +typedef RDI_FilePathNode RDI_SectionElementType_FilePathNodes; +typedef RDI_SourceFile RDI_SectionElementType_SourceFiles; +typedef RDI_LineTable RDI_SectionElementType_LineTables; +typedef RDI_U64 RDI_SectionElementType_LineInfoVOffs; +typedef RDI_Line RDI_SectionElementType_LineInfoLines; +typedef RDI_Column RDI_SectionElementType_LineInfoColumns; +typedef RDI_SourceLineMap RDI_SectionElementType_SourceLineMaps; +typedef RDI_U32 RDI_SectionElementType_SourceLineMapNumbers; +typedef RDI_U32 RDI_SectionElementType_SourceLineMapRanges; +typedef RDI_U64 RDI_SectionElementType_SourceLineMapVOffs; +typedef RDI_Unit RDI_SectionElementType_Units; +typedef RDI_VMapEntry RDI_SectionElementType_UnitVMap; +typedef RDI_TypeNode RDI_SectionElementType_TypeNodes; +typedef RDI_UDT RDI_SectionElementType_UDTs; +typedef RDI_Member RDI_SectionElementType_Members; +typedef RDI_EnumMember RDI_SectionElementType_EnumMembers; +typedef RDI_GlobalVariable RDI_SectionElementType_GlobalVariables; +typedef RDI_VMapEntry RDI_SectionElementType_GlobalVMap; +typedef RDI_ThreadVariable RDI_SectionElementType_ThreadVariables; +typedef RDI_Procedure RDI_SectionElementType_Procedures; +typedef RDI_Scope RDI_SectionElementType_Scopes; +typedef RDI_U64 RDI_SectionElementType_ScopeVOffData; +typedef RDI_VMapEntry RDI_SectionElementType_ScopeVMap; +typedef RDI_InlineSite RDI_SectionElementType_InlineSites; +typedef RDI_Local RDI_SectionElementType_Locals; +typedef RDI_LocationBlock RDI_SectionElementType_LocationBlocks; +typedef RDI_U8 RDI_SectionElementType_LocationData; +typedef RDI_NameMap RDI_SectionElementType_NameMaps; +typedef RDI_NameMapBucket RDI_SectionElementType_NameMapBuckets; +typedef RDI_NameMapNode RDI_SectionElementType_NameMapNodes; + RDI_PROC RDI_U64 rdi_hash(RDI_U8 *ptr, RDI_U64 size); RDI_PROC RDI_U32 rdi_size_from_basic_type_kind(RDI_TypeKind kind); RDI_PROC RDI_U32 rdi_addr_size_from_arch(RDI_Arch arch); @@ -1219,6 +1334,8 @@ RDI_PROC RDI_EvalConversionKind rdi_eval_conversion_kind_from_typegroups(RDI_Eva RDI_PROC RDI_S32 rdi_eval_op_typegroup_are_compatible(RDI_EvalOp op, RDI_EvalTypeGroup group); RDI_PROC RDI_U8 *rdi_explanation_string_from_eval_conversion_kind(RDI_EvalConversionKind kind, RDI_U64 *size_out); +extern RDI_U16 rdi_section_element_size_table[37]; +extern RDI_U8 rdi_section_is_required_table[37]; extern RDI_U8 rdi_eval_op_ctrlbits_table[45]; #endif // RDI_FORMAT_H diff --git a/src/lib_rdi_format/rdi_format_parse.c b/src/lib_rdi_format/rdi_format_parse.c index a61de07b..bd54876c 100644 --- a/src/lib_rdi_format/rdi_format_parse.c +++ b/src/lib_rdi_format/rdi_format_parse.c @@ -34,14 +34,14 @@ rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out) ////////////////////////////// //- rjf: extract data sections // - RDI_DataSection *dsecs = 0; + RDI_Section *dsecs = 0; RDI_U32 dsec_count = 0; if(result == RDI_ParseStatus_Good) { RDI_U64 opl = (RDI_U64)hdr->data_section_off + (RDI_U64)hdr->data_section_count*sizeof(*dsecs); if(opl <= size) { - dsecs = (RDI_DataSection*)(data + hdr->data_section_off); + dsecs = (RDI_Section*)(data + hdr->data_section_off); dsec_count = hdr->data_section_count; } if(dsecs == 0) @@ -51,211 +51,146 @@ rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out) } ////////////////////////////// - //- rjf: extract primary data section indexes - // - RDI_U32 dsec_idx[RDI_DataSectionTag_PRIMARY_COUNT] = {0}; - if(result == RDI_ParseStatus_Good) - { - RDI_DataSection *sec_ptr = dsecs; - for(RDI_U32 i = 0; i < dsec_count; i += 1, sec_ptr += 1) - { - if(sec_ptr->tag < RDI_DataSectionTag_PRIMARY_COUNT) - { - dsec_idx[sec_ptr->tag] = i; - } - } - } - - ////////////////////////////// - //- rjf: fill out raw data info + //- rjf: fill result // if(result == RDI_ParseStatus_Good) { out->raw_data = data; out->raw_data_size = size; - out->dsecs = dsecs; - out->dsec_count = dsec_count; - for(RDI_U32 i = 0; i < RDI_DataSectionTag_PRIMARY_COUNT; i += 1) - { - out->dsec_idx[i] = dsec_idx[i]; - } + out->sections = dsecs; + out->sections_count = dsec_count; } ////////////////////////////// - //- rjf: extract string table info - // - RDI_U8 *string_data = 0; - RDI_U64 string_opl = 0; - RDI_U32 *string_offs = 0; - RDI_U64 string_count = 0; - if(result == RDI_ParseStatus_Good) - { - RDI_U64 table_entry_count = 0; - rdi_parse__extract_primary(out, string_offs, &table_entry_count, RDI_DataSectionTag_StringTable); - rdi_parse__extract_primary(out, string_data, &string_opl, RDI_DataSectionTag_StringData); - if(table_entry_count > 0) - { - string_count = table_entry_count - 1; - } - if(string_data == 0) - { - result = RDI_ParseStatus_MissingStringDataSection; - } - else if (string_offs == 0) - { - result = RDI_ParseStatus_MissingStringTableSection; - } - } - - ////////////////////////////// - //- rjf: extract index run table info - // - RDI_U32 *idx_run_data = 0; - RDI_U64 idx_run_count = 0; - if(result == RDI_ParseStatus_Good) - { - rdi_parse__extract_primary(out, idx_run_data, &idx_run_count, RDI_DataSectionTag_IndexRuns); - if(idx_run_data == 0) - { - result = RDI_ParseStatus_MissingIndexRunSection; - } - } - - ////////////////////////////// - //- rjf: extract info tables + //- rjf: validate results // if(result == RDI_ParseStatus_Good) { - out->string_data = string_data; - out->string_offs = string_offs; - out->string_data_size = string_opl; - out->string_count = string_count; - out->idx_run_data = idx_run_data; - out->idx_run_count = idx_run_count; + for(RDI_SectionKind k = (RDI_SectionKind)(RDI_SectionKind_NULL+1); k < RDI_SectionKind_COUNT; k = (RDI_SectionKind)(k+1)) { - RDI_TopLevelInfo *tli = 0; - RDI_U64 dummy = 0; - rdi_parse__extract_primary(out, tli, &dummy, RDI_DataSectionTag_TopLevelInfo); - if (dummy != 1){ - tli = 0; - } - out->top_level_info = tli; - } - rdi_parse__extract_primary(out, out->binary_sections, &out->binary_sections_count, RDI_DataSectionTag_BinarySections); - rdi_parse__extract_primary(out, out->file_paths, &out->file_paths_count, RDI_DataSectionTag_FilePathNodes); - rdi_parse__extract_primary(out, out->source_files, &out->source_files_count, RDI_DataSectionTag_SourceFiles); - rdi_parse__extract_primary(out, out->line_tables, &out->line_tables_count, RDI_DataSectionTag_LineTables); - rdi_parse__extract_primary(out, out->source_line_maps, &out->source_line_maps_count, RDI_DataSectionTag_SourceLineMaps); - rdi_parse__extract_primary(out, out->line_info_voffs, &out->line_info_voffs_count, RDI_DataSectionTag_LineInfoVoffs); - rdi_parse__extract_primary(out, out->line_info_lines, &out->line_info_lines_count, RDI_DataSectionTag_LineInfoLines); - rdi_parse__extract_primary(out, out->line_info_columns, &out->line_info_columns_count, RDI_DataSectionTag_LineInfoColumns); - rdi_parse__extract_primary(out, out->units, &out->units_count, RDI_DataSectionTag_Units); - rdi_parse__extract_primary(out, out->unit_vmap, &out->unit_vmap_count, RDI_DataSectionTag_UnitVmap); - rdi_parse__extract_primary(out, out->unit_vmap, &out->unit_vmap_count, RDI_DataSectionTag_UnitVmap); - rdi_parse__extract_primary(out, out->type_nodes, &out->type_nodes_count, RDI_DataSectionTag_TypeNodes); - rdi_parse__extract_primary(out, out->udts, &out->udts_count, RDI_DataSectionTag_UDTs); - rdi_parse__extract_primary(out, out->members, &out->members_count, RDI_DataSectionTag_Members); - rdi_parse__extract_primary(out, out->enum_members, &out->enum_members_count, RDI_DataSectionTag_EnumMembers); - rdi_parse__extract_primary(out, out->global_variables, &out->global_variables_count, RDI_DataSectionTag_GlobalVariables); - rdi_parse__extract_primary(out, out->global_vmap, &out->global_vmap_count, RDI_DataSectionTag_GlobalVmap); - rdi_parse__extract_primary(out, out->thread_variables, &out->thread_variables_count, RDI_DataSectionTag_ThreadVariables); - rdi_parse__extract_primary(out, out->procedures, &out->procedures_count, RDI_DataSectionTag_Procedures); - rdi_parse__extract_primary(out, out->scopes, &out->scopes_count, RDI_DataSectionTag_Scopes); - rdi_parse__extract_primary(out, out->scope_voffs, &out->scope_voffs_count, RDI_DataSectionTag_ScopeVoffData); - rdi_parse__extract_primary(out, out->scope_vmap, &out->scope_vmap_count, RDI_DataSectionTag_ScopeVmap); - rdi_parse__extract_primary(out, out->locals, &out->locals_count, RDI_DataSectionTag_Locals); - rdi_parse__extract_primary(out, out->location_blocks, &out->location_blocks_count, RDI_DataSectionTag_LocationBlocks); - rdi_parse__extract_primary(out, out->location_data, &out->location_data_size, RDI_DataSectionTag_LocationData); - rdi_parse__extract_primary(out, out->name_maps, &out->name_maps_count, RDI_DataSectionTag_NameMaps); - { - RDI_NameMap *name_map_ptr = out->name_maps; - RDI_NameMap *name_map_opl = out->name_maps + out->name_maps_count; - for (; name_map_ptr < name_map_opl; name_map_ptr += 1){ - if (out->name_maps_by_kind[name_map_ptr->kind] == 0){ - out->name_maps_by_kind[name_map_ptr->kind] = name_map_ptr; + if(rdi_section_is_required_table[k]) + { + RDI_U64 data_size = 0; + RDI_SectionEncoding encoding = 0; + void *data = rdi_section_raw_data_from_kind(out, k, &encoding, &data_size); + if(data == 0 || data == &rdi_nil_element_union || data_size == 0) + { + result = RDI_ParseStatus_MissingRequiredSection; + break; } } } } - ////////////////////////////// - //- rjf: fill any missing tables with nil elements - // -#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->line_tables == 0) { out->line_tables = &rdi_line_table_nil; out->line_tables_count = 1; } - if(out->source_line_maps == 0) { out->source_line_maps = &rdi_source_line_map_nil; out->source_line_maps_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; } //////////////////////////////// -//~ Parsed Info Extraction Helpers +//~ Base Parsed Info Extraction Helpers -//- top-level info +//- section table/element raw data extraction + +RDI_PROC void * +rdi_section_raw_data_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_SectionEncoding *encoding_out, RDI_U64 *size_out) +{ + void *result = 0; +#if !defined(RDI_DISABLE_NILS) + result = &rdi_nil_element_union; + *size_out = rdi_section_element_size_table[kind]; +#endif + if(0 <= kind && kind < rdi->sections_count) + { + result = rdi->raw_data+rdi->sections[kind].off; + *size_out = rdi->sections[kind].encoded_size; + *encoding_out = rdi->sections[kind].encoding; + } + return result; +} + +RDI_PROC void * +rdi_section_raw_table_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 *count_out) +{ + void *result = 0; + RDI_U64 all_elements_size = 0; + RDI_SectionEncoding all_elements_encoding = 0; + void *all_elements = rdi_section_raw_data_from_kind(rdi, kind, &all_elements_encoding, &all_elements_size); + if(all_elements_encoding == RDI_SectionEncoding_Unpacked) + { + RDI_U64 element_size = (RDI_U64)rdi_section_element_size_table[kind]; + RDI_U64 all_elements_count = all_elements_size/element_size; + result = all_elements; + *count_out = all_elements_count; + } + return result; +} + +RDI_PROC void * +rdi_section_raw_element_from_kind_idx(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 idx) +{ + RDI_U64 count = 0; + void *table = rdi_section_raw_table_from_kind(rdi, kind, &count); + void *result = table; + if(idx < count) + { + RDI_U64 element_size = (RDI_U64)rdi_section_element_size_table[kind]; + result = (RDI_U8 *)table + element_size*idx; + } + return result; +} + +//- info about whole parse RDI_PROC RDI_U64 rdi_decompressed_size_from_parsed(RDI_Parsed *rdi) { RDI_U64 decompressed_size = rdi->raw_data_size; - for(RDI_U64 dsec_idx = 0; dsec_idx < rdi->dsec_count; dsec_idx += 1) + for(RDI_U64 section_idx = 0; section_idx < rdi->sections_count; section_idx += 1) { - decompressed_size += (rdi->dsecs[dsec_idx].unpacked_size - rdi->dsecs[dsec_idx].encoded_size); + decompressed_size += (rdi->sections[section_idx].unpacked_size - rdi->sections[section_idx].encoded_size); } return decompressed_size; } //- strings -RDI_PROC RDI_U8* -rdi_string_from_idx(RDI_Parsed *parsed, RDI_U32 idx, RDI_U64 *len_out) +RDI_PROC RDI_U8 * +rdi_string_from_idx(RDI_Parsed *rdi, RDI_U32 idx, RDI_U64 *len_out) { - RDI_U8 *result = 0; - RDI_U64 len_result = 0; - if(idx < parsed->string_count) + RDI_U8 *result_base = 0; + RDI_U64 result_size = 0; { - RDI_U32 off_raw = parsed->string_offs[idx]; - RDI_U32 opl_raw = parsed->string_offs[idx + 1]; - RDI_U32 opl = rdi_parse__min(opl_raw, parsed->string_data_size); - RDI_U32 off = rdi_parse__min(off_raw, opl); - result = parsed->string_data + off; - len_result = opl - off; + RDI_U64 string_offs_count = 0; + RDI_U32 *string_offs = rdi_table_from_name(rdi, StringTable, &string_offs_count); + if(idx < string_offs_count) + { + RDI_U64 string_data_size = 0; + RDI_U8 *string_data = rdi_table_from_name(rdi, StringData, &string_data_size); + RDI_U32 off_raw = string_offs[idx]; + RDI_U32 opl_raw = string_offs[idx + 1]; + RDI_U32 opl = rdi_parse__min(opl_raw, string_data_size); + RDI_U32 off = rdi_parse__min(off_raw, opl); + result_base = string_data + off; + result_size = opl - off; + } } - *len_out = len_result; - return result; + *len_out = result_size; + return result_base; } //- index runs RDI_PROC RDI_U32* -rdi_idx_run_from_first_count(RDI_Parsed *parsed, RDI_U32 raw_first, RDI_U32 raw_count, RDI_U32 *n_out) +rdi_idx_run_from_first_count(RDI_Parsed *rdi, RDI_U32 raw_first, RDI_U32 raw_count, RDI_U32 *n_out) { + RDI_U64 idx_run_count = 0; + RDI_U32 *idx_run_data = rdi_table_from_name(rdi, IndexRuns, &idx_run_count); RDI_U32 raw_opl = raw_first + raw_count; - RDI_U32 opl = rdi_parse__min(raw_opl, parsed->idx_run_count); + RDI_U32 opl = rdi_parse__min(raw_opl, idx_run_count); RDI_U32 first = rdi_parse__min(raw_first, opl); RDI_U32 *result = 0; - if(first < parsed->idx_run_count) + if(first < idx_run_count) { - result = parsed->idx_run_data + first; + result = idx_run_data + first; } *n_out = opl - first; return result; @@ -264,17 +199,17 @@ rdi_idx_run_from_first_count(RDI_Parsed *parsed, RDI_U32 raw_first, RDI_U32 raw_ //- line info RDI_PROC void -rdi_parsed_from_line_table(RDI_Parsed *p, RDI_LineTable *line_table, RDI_ParsedLineTable *out) +rdi_parsed_from_line_table(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_ParsedLineTable *out) { //- rjf: extract top-level line info tables RDI_U64 all_voffs_count = 0; - RDI_U64 *all_voffs = (RDI_U64 *)rdi_data_from_dsec(p, p->dsec_idx[RDI_DataSectionTag_LineInfoVoffs], sizeof(RDI_U64), RDI_DataSectionTag_LineInfoVoffs, &all_voffs_count); + RDI_U64 *all_voffs = rdi_table_from_name(rdi, LineInfoVOffs, &all_voffs_count); RDI_U64 *all_voffs_opl = all_voffs + all_voffs_count; RDI_U64 all_lines_count = 0; - RDI_Line *all_lines = (RDI_Line *)rdi_data_from_dsec(p, p->dsec_idx[RDI_DataSectionTag_LineInfoLines], sizeof(RDI_Line), RDI_DataSectionTag_LineInfoLines, &all_lines_count); + RDI_Line *all_lines = rdi_table_from_name(rdi, LineInfoLines, &all_lines_count); RDI_Line *all_lines_opl = all_lines + all_lines_count; RDI_U64 all_cols_count = 0; - RDI_Column *all_cols = (RDI_Column *)rdi_data_from_dsec(p, p->dsec_idx[RDI_DataSectionTag_LineInfoColumns], sizeof(RDI_Column), RDI_DataSectionTag_LineInfoColumns, &all_cols_count); + RDI_Column *all_cols = rdi_table_from_name(rdi, LineInfoColumns, &all_cols_count); RDI_Column *all_cols_opl = all_cols + all_cols_count; //- rjf: extract ranges of top-level tables belonging to this line table @@ -332,17 +267,17 @@ rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff) } RDI_PROC void -rdi_parsed_from_source_line_map(RDI_Parsed *p, RDI_SourceLineMap *map, RDI_ParsedSourceLineMap *out) +rdi_parsed_from_source_line_map(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_ParsedSourceLineMap *out) { //- rjf: extract top-level line info tables RDI_U64 all_nums_count = 0; - RDI_U32 *all_nums = (RDI_U32 *)rdi_data_from_dsec(p, p->dsec_idx[RDI_DataSectionTag_SourceLineMapNumbers], sizeof(RDI_U32), RDI_DataSectionTag_SourceLineMapNumbers, &all_nums_count); + RDI_U32 *all_nums = rdi_table_from_name(rdi, SourceLineMapNumbers, &all_nums_count); RDI_U32 *all_nums_opl = all_nums + all_nums_count; RDI_U64 all_rngs_count = 0; - RDI_U32 *all_rngs = (RDI_U32 *)rdi_data_from_dsec(p, p->dsec_idx[RDI_DataSectionTag_SourceLineMapRanges], sizeof(RDI_U32), RDI_DataSectionTag_SourceLineMapRanges, &all_rngs_count); + RDI_U32 *all_rngs = rdi_table_from_name(rdi, SourceLineMapRanges, &all_rngs_count); RDI_U32 *all_rngs_opl = all_rngs + all_rngs_count; RDI_U64 all_voffs_count = 0; - RDI_U64 *all_voffs = (RDI_U64 *)rdi_data_from_dsec(p, p->dsec_idx[RDI_DataSectionTag_SourceLineMapVOffs], sizeof(RDI_U64), RDI_DataSectionTag_SourceLineMapVOffs, &all_voffs_count); + RDI_U64 *all_voffs = rdi_table_from_name(rdi, SourceLineMapVOffs, &all_voffs_count); RDI_U64 *all_voffs_opl = all_voffs + all_voffs_count; //- rjf: extract ranges of top-level tables belonging to this line map @@ -363,7 +298,7 @@ rdi_parsed_from_source_line_map(RDI_Parsed *p, RDI_SourceLineMap *map, RDI_Parse out->voff_count = voffs_count; } -RDI_PROC RDI_U64* +RDI_PROC RDI_U64 * rdi_line_voffs_from_num(RDI_ParsedSourceLineMap *map, RDI_U32 linenum, RDI_U32 *n_out) { RDI_U64 *result = 0; @@ -424,7 +359,7 @@ rdi_line_voffs_from_num(RDI_ParsedSourceLineMap *map, RDI_U32 linenum, RDI_U32 * //- vmap lookups RDI_PROC RDI_U64 -rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U32 vmap_count, RDI_U64 voff) +rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U64 vmap_count, RDI_U64 voff) { RDI_U64 result = 0; if(vmap_count > 0 && vmap[0].voff <= voff && voff < vmap[vmap_count - 1].voff) @@ -459,27 +394,42 @@ rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U32 vmap_count, RDI_U64 voff) return result; } -//- name maps - -RDI_PROC RDI_NameMap* -rdi_name_map_from_kind(RDI_Parsed *p, RDI_NameMapKind kind){ - RDI_NameMap *result = 0; - if(0 < kind && kind < RDI_NameMapKind_COUNT) - { - result = p->name_maps_by_kind[kind]; - } +RDI_PROC RDI_U64 +rdi_vmap_idx_from_section_kind_voff(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 voff) +{ + RDI_U64 vmaps_count = 0; + RDI_VMapEntry *vmaps = rdi_section_raw_table_from_kind(rdi, kind, &vmaps_count); + RDI_U64 result = rdi_vmap_idx_from_voff(vmaps, vmaps_count, voff); return result; } +//- name maps + RDI_PROC void -rdi_name_map_parse(RDI_Parsed *p, RDI_NameMap *mapptr, RDI_ParsedNameMap *out) +rdi_parsed_from_name_map(RDI_Parsed *rdi, RDI_NameMap *mapptr, RDI_ParsedNameMap *out) { out->buckets = 0; out->bucket_count = 0; if(mapptr != 0) { - out->buckets = (RDI_NameMapBucket*)rdi_data_from_dsec(p, mapptr->bucket_data_idx, sizeof(RDI_NameMapBucket), RDI_DataSectionTag_NameMapBuckets, &out->bucket_count); - out->nodes = (RDI_NameMapNode*)rdi_data_from_dsec(p, mapptr->node_data_idx, sizeof(RDI_NameMapNode), RDI_DataSectionTag_NameMapNodes, &out->node_count); + RDI_U64 all_buckets_count = 0; + RDI_NameMapBucket *all_buckets = rdi_table_from_name(rdi, NameMapBuckets, &all_buckets_count); + RDI_U64 all_nodes_count = 0; + RDI_NameMapNode *all_nodes = rdi_table_from_name(rdi, NameMapNodes, &all_nodes_count); + out->buckets = all_buckets+mapptr->bucket_base_idx; + out->nodes = all_nodes+mapptr->node_base_idx; + out->bucket_count = mapptr->bucket_count; + out->node_count = mapptr->node_count; + if(mapptr->bucket_base_idx > all_buckets_count) + { + out->buckets = 0; + out->bucket_count = 0; + } + if(mapptr->node_base_idx > all_nodes_count) + { + out->nodes = 0; + out->node_count = 0; + } } } @@ -545,49 +495,20 @@ rdi_matches_from_map_node(RDI_Parsed *p, RDI_NameMapNode *node, RDI_U32 *n_out) return result; } +//////////////////////////////// +//~ High-Level Composite Lookup Functions + //- procedures RDI_PROC RDI_U64 -rdi_first_voff_from_proc(RDI_Parsed *p, RDI_U32 proc_id) +rdi_first_voff_from_proc_idx(RDI_Parsed *rdi, RDI_U32 proc_idx) { RDI_U64 result = 0; - if(0 < proc_id && proc_id < p->procedures_count) { - RDI_Procedure *proc = p->procedures + proc_id; - RDI_U32 scope_id = proc->root_scope_idx; - if(0 < scope_id && scope_id < p->scopes_count) - { - RDI_Scope *scope = p->scopes + scope_id; - if(scope->voff_range_first < scope->voff_range_opl && scope->voff_range_first < p->scope_voffs_count) - { - result = p->scope_voffs[scope->voff_range_first]; - } - } + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx); + RDI_U64 *voffs = rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_first); + result = *voffs; } return result; } - -//////////////////////////////// -//~ Parser Helpers - -RDI_PROC void* -rdi_data_from_dsec(RDI_Parsed *parsed, RDI_U32 idx, RDI_U32 item_size, RDI_DataSectionTag expected_tag, RDI_U64 *count_out) -{ - void *result = 0; - RDI_U32 count_result = 0; - if(0 < idx && idx < parsed->dsec_count) - { - RDI_DataSection *ds = parsed->dsecs + idx; - if(ds->tag == expected_tag) - { - RDI_U64 encoded_opl = ds->off + ds->encoded_size; - if(encoded_opl <= parsed->raw_data_size) - { - count_result = ds->unpacked_size/item_size; - result = (parsed->raw_data + ds->off); - } - } - } - *count_out = count_result; - return result; -} diff --git a/src/lib_rdi_format/rdi_format_parse.h b/src/lib_rdi_format/rdi_format_parse.h index c280f008..e056a7d3 100644 --- a/src/lib_rdi_format/rdi_format_parse.h +++ b/src/lib_rdi_format/rdi_format_parse.h @@ -19,83 +19,17 @@ typedef enum RDI_ParseStatus RDI_ParseStatus_HeaderDoesNotMatch = 1, RDI_ParseStatus_UnsupportedVersionNumber = 2, RDI_ParseStatus_InvalidDataSecionLayout = 3, - RDI_ParseStatus_MissingStringDataSection = 4, - RDI_ParseStatus_MissingStringTableSection = 5, - RDI_ParseStatus_MissingIndexRunSection = 6, + RDI_ParseStatus_MissingRequiredSection = 4, } RDI_ParseStatus; typedef struct RDI_Parsed RDI_Parsed; struct RDI_Parsed { - // raw data & primary data sections RDI_U8 *raw_data; RDI_U64 raw_data_size; - RDI_DataSection *dsecs; - RDI_U64 dsec_count; - RDI_U32 dsec_idx[RDI_DataSectionTag_PRIMARY_COUNT]; - - // parsed universal data structures (strings, index runs) - RDI_U8* string_data; - RDI_U64 string_data_size; - RDI_U32* string_offs; - RDI_U64 string_count; - RDI_U32* idx_run_data; - RDI_U32 idx_run_count; - - // extracted info & tables (any of these may be empty or null, even with a successful parse) - RDI_TopLevelInfo* top_level_info; - RDI_BinarySection* binary_sections; - RDI_U64 binary_sections_count; - RDI_FilePathNode* file_paths; - RDI_U64 file_paths_count; - RDI_SourceFile* source_files; - RDI_U64 source_files_count; - RDI_LineTable* line_tables; - RDI_U64 line_tables_count; - RDI_SourceLineMap* source_line_maps; - RDI_U64 source_line_maps_count; - RDI_U64* line_info_voffs; - RDI_U64 line_info_voffs_count; - RDI_Line* line_info_lines; - RDI_U64 line_info_lines_count; - RDI_Column* line_info_columns; - RDI_U64 line_info_columns_count; - RDI_Unit* units; - RDI_U64 units_count; - RDI_VMapEntry* unit_vmap; - RDI_U64 unit_vmap_count; - RDI_TypeNode* type_nodes; - RDI_U64 type_nodes_count; - RDI_UDT* udts; - RDI_U64 udts_count; - RDI_Member* members; - RDI_U64 members_count; - RDI_EnumMember* enum_members; - RDI_U64 enum_members_count; - RDI_GlobalVariable* global_variables; - RDI_U64 global_variables_count; - RDI_VMapEntry* global_vmap; - RDI_U64 global_vmap_count; - RDI_ThreadVariable* thread_variables; - RDI_U64 thread_variables_count; - RDI_Procedure* procedures; - RDI_U64 procedures_count; - RDI_Scope* scopes; - RDI_U64 scopes_count; - RDI_U64* scope_voffs; - RDI_U64 scope_voffs_count; - RDI_VMapEntry* scope_vmap; - RDI_U64 scope_vmap_count; - RDI_Local* locals; - RDI_U64 locals_count; - RDI_LocationBlock* location_blocks; - RDI_U64 location_blocks_count; - RDI_U8* location_data; - RDI_U64 location_data_size; - RDI_NameMap* name_maps; - RDI_U64 name_maps_count; - RDI_NameMap* name_maps_by_kind[RDI_NameMapKind_COUNT]; + RDI_Section *sections; + RDI_U64 sections_count; }; typedef struct RDI_ParsedLineTable RDI_ParsedLineTable; @@ -142,29 +76,31 @@ 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}; -static RDI_LineTable rdi_line_table_nil = {0}; -static RDI_SourceLineMap rdi_source_line_map_nil = {0}; -static RDI_Line rdi_line_nil = {0}; -static RDI_Column rdi_column_nil = {0}; -static RDI_Unit rdi_unit_nil = {0}; -static RDI_VMapEntry rdi_vmap_entry_nil = {0}; -static RDI_TypeNode rdi_type_node_nil = {0}; -static RDI_UDT rdi_udt_nil = {0}; -static RDI_Member rdi_member_nil = {0}; -static RDI_EnumMember rdi_enum_member_nil = {0}; -static RDI_GlobalVariable rdi_global_variable_nil = {0}; -static RDI_ThreadVariable rdi_thread_variable_nil = {0}; -static RDI_Procedure rdi_procedure_nil = {0}; -static RDI_Scope rdi_scope_nil = {0}; -static RDI_U64 rdi_voff_nil = 0; -static RDI_LocationBlock rdi_location_block_nil = {0}; -static RDI_Local rdi_local_nil = {0}; -#endif +static union +{ + RDI_TopLevelInfo top_level_info; + RDI_BinarySection binary_section; + RDI_FilePathNode file_path_node; + RDI_SourceFile source_file; + RDI_LineTable line_table; + RDI_SourceLineMap source_line_map; + RDI_Line line; + RDI_Column column; + RDI_Unit unit; + RDI_VMapEntry vmap_entry; + RDI_TypeNode type_node; + RDI_UDT udt; + RDI_Member member; + RDI_EnumMember enum_member; + RDI_GlobalVariable global_variable; + RDI_ThreadVariable thread_variable; + RDI_Procedure procedure; + RDI_Scope scope; + RDI_U64 voff; + RDI_LocationBlock location_block; + RDI_Local local; +} +rdi_nil_element_union = {0}; //////////////////////////////// //~ Top-Level Parsing API @@ -172,28 +108,32 @@ static RDI_Local rdi_local_nil = {0}; RDI_PROC RDI_ParseStatus rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out); //////////////////////////////// -//~ Parsed Info Extraction Helpers +//~ Base Parsed Info Extraction Helpers -//- element extractor -#define rdi_element_from_idx(parsed, name, idx) ((0 <= (idx) && (idx) < (parsed)->name##_count) ? &(parsed)->name[idx] : (parsed)->name ? &(parsed)->name[0] : 0) +//- section table/element raw data extraction +RDI_PROC void *rdi_section_raw_data_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_SectionEncoding *encoding_out, RDI_U64 *size_out); +RDI_PROC void *rdi_section_raw_table_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 *count_out); +RDI_PROC void *rdi_section_raw_element_from_kind_idx(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 idx); +#define rdi_table_from_name(rdi, name, count_out) (RDI_SectionElementType_##name *)rdi_section_raw_table_from_kind((rdi), RDI_SectionKind_##name, (count_out)) +#define rdi_element_from_name_idx(rdi, name, idx) (RDI_SectionElementType_##name *)rdi_section_raw_element_from_kind_idx((rdi), RDI_SectionKind_##name, (idx)) -//- top-level info +//- info about whole parse RDI_PROC RDI_U64 rdi_decompressed_size_from_parsed(RDI_Parsed *rdi); //- strings -RDI_PROC RDI_U8 *rdi_string_from_idx(RDI_Parsed *parsed, RDI_U32 idx, RDI_U64 *len_out); +RDI_PROC RDI_U8 *rdi_string_from_idx(RDI_Parsed *rdi, RDI_U32 idx, RDI_U64 *len_out); //- index runs -RDI_PROC RDI_U32 *rdi_idx_run_from_first_count(RDI_Parsed *parsed, RDI_U32 first, RDI_U32 raw_count, RDI_U32 *n_out); +RDI_PROC RDI_U32 *rdi_idx_run_from_first_count(RDI_Parsed *rdi, RDI_U32 raw_first, RDI_U32 raw_count, RDI_U32 *n_out); //- line info -RDI_PROC void rdi_parsed_from_line_table(RDI_Parsed *p, RDI_LineTable *line_table, RDI_ParsedLineTable *out); +RDI_PROC void rdi_parsed_from_line_table(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_ParsedLineTable *out); RDI_PROC RDI_U64 rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff); -RDI_PROC void rdi_parsed_from_source_line_map(RDI_Parsed *p, RDI_SourceLineMap *map, RDI_ParsedSourceLineMap *out); +RDI_PROC void rdi_parsed_from_source_line_map(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_ParsedSourceLineMap *out); RDI_PROC RDI_U64 *rdi_line_voffs_from_num(RDI_ParsedSourceLineMap *map, RDI_U32 linenum, RDI_U32 *n_out); //- vmap lookups -RDI_PROC RDI_U64 rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U32 vmap_count, RDI_U64 voff); +RDI_PROC RDI_U64 rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U64 vmap_count, RDI_U64 voff); //- name maps RDI_PROC RDI_NameMap *rdi_name_map_from_kind(RDI_Parsed *p, RDI_NameMapKind kind); @@ -201,16 +141,15 @@ RDI_PROC void rdi_name_map_parse(RDI_Parsed* p, RDI_NameMap *mapptr, RDI_ParsedN RDI_PROC RDI_NameMapNode *rdi_name_map_lookup(RDI_Parsed *p, RDI_ParsedNameMap *map, RDI_U8 *str, RDI_U64 len); RDI_PROC RDI_U32 *rdi_matches_from_map_node(RDI_Parsed *p, RDI_NameMapNode *node, RDI_U32 *n_out); +//////////////////////////////// +//~ High-Level Composite Lookup Functions + //- procedures -RDI_PROC RDI_U64 rdi_first_voff_from_proc(RDI_Parsed *p, RDI_U32 proc_id); +RDI_PROC RDI_U64 rdi_first_voff_from_proc_idx(RDI_Parsed *rdi, RDI_U32 proc_idx); //////////////////////////////// //~ Parser Helpers #define rdi_parse__min(a,b) (((a)<(b))?(a):(b)) -#define rdi_parse__extract_primary(p,outptr,outn,pritag) \ -( (*(void**)&(outptr)) = \ -rdi_data_from_dsec((p),(p)->dsec_idx[pritag],sizeof(*(outptr)),(pritag),(outn)) ) -RDI_PROC void *rdi_data_from_dsec(RDI_Parsed *p, RDI_U32 idx, RDI_U32 item_size, RDI_DataSectionTag expected_tag, RDI_U64 *n_out); #endif // RDI_FORMAT_PARSE_H diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index 23ce17e9..0cc4b342 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -480,7 +480,7 @@ rdim_idx_from_src_file(RDIM_SrcFile *src_file) RDI_U64 idx = 0; if(src_file != 0 && src_file->chunk != 0) { - idx = src_file->chunk->base_idx + (src_file - src_file->chunk->v) + 1; + idx = (src_file->chunk->base_idx + (src_file - src_file->chunk->v) + 1); } return idx; } @@ -1109,48 +1109,6 @@ rdim_location_set_push_case(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM scopes->location_count +=1; } -//////////////////////////////// -//~ rjf: [Baking Helpers] Baked File Layout Calculations - -RDI_PROC RDI_U64 -rdim_bake_section_count_from_params(RDIM_BakeParams *params) -{ - RDI_U64 section_count = 0; - { - section_count += RDI_DataSectionTag_PRIMARY_COUNT; - section_count += RDI_NameMapKind_COUNT-1; // PER-NAME-MAP buckets section - section_count += RDI_NameMapKind_COUNT-1; // PER-NAME-MAP nodes section - } - return section_count; -} - -RDI_PROC RDI_U64 -rdim_bake_section_idx_from_params_tag_idx(RDIM_BakeParams *params, RDI_DataSectionTag tag, RDI_U64 idx) -{ - RDI_U64 result = 0; - if(tag < RDI_DataSectionTag_PRIMARY_COUNT) - { - result = (RDI_U64)tag; - } - else switch(tag) - { - default:{}break; - - //- rjf: per-name-map sections - case (RDI_U32)RDI_DataSectionTag_NameMapBuckets: - if(idx != 0) - { - result = RDI_DataSectionTag_PRIMARY_COUNT + 0*(RDI_NameMapKind_COUNT-1) + (idx-1)%(RDI_NameMapKind_COUNT-1); - }break; - case (RDI_U32)RDI_DataSectionTag_NameMapNodes: - if(idx != 0) - { - result = RDI_DataSectionTag_PRIMARY_COUNT + 1*(RDI_NameMapKind_COUNT-1) + (idx-1)%(RDI_NameMapKind_COUNT-1); - }break; - } - return result; -} - //////////////////////////////// //~ rjf: [Baking Helpers] Baked VMap Building @@ -1520,10 +1478,10 @@ rdim_bake_string_map_tight_from_loose(RDIM_Arena *arena, RDIM_BakeStringMapTopol return m; } -RDI_PROC RDI_U64 +RDI_PROC RDI_U32 rdim_bake_idx_from_string(RDIM_BakeStringMapTight *map, RDIM_String8 string) { - RDI_U64 idx = 0; + RDI_U32 idx = 0; if(string.RDIM_String8_SizeMember != 0) { RDI_U64 hash = rdi_hash(string.RDIM_String8_BaseMember, string.RDIM_String8_SizeMember); @@ -1696,7 +1654,12 @@ RDI_PROC RDI_U32 rdim_bake_path_node_idx_from_string(RDIM_BakePathTree *tree, RDIM_String8 string) { RDIM_BakePathNode *path_node = rdim_bake_path_node_from_string(tree, string); - return path_node ? path_node->idx : 0; + RDI_U32 result = 0; + if(path_node != 0) + { + result = path_node->idx; + } + return result; } RDI_PROC RDIM_BakePathNode * @@ -1833,11 +1796,11 @@ rdim_bake_section_list_push(RDIM_Arena *arena, RDIM_BakeSectionList *list) } RDI_PROC RDIM_BakeSection * -rdim_bake_section_list_push_new_unpacked(RDIM_Arena *arena, RDIM_BakeSectionList *list, void *data, RDI_U64 size, RDI_DataSectionTag tag, RDI_U64 tag_idx) +rdim_bake_section_list_push_new_unpacked(RDIM_Arena *arena, RDIM_BakeSectionList *list, void *data, RDI_U64 size, RDI_SectionKind tag, RDI_U64 tag_idx) { RDIM_BakeSection *section = rdim_bake_section_list_push(arena, list); section->data = data; - section->encoding = RDI_DataSectionEncoding_Unpacked; + section->encoding = RDI_SectionEncoding_Unpacked; section->encoded_size = size; section->unpacked_size = size; section->tag = tag; @@ -2101,8 +2064,8 @@ rdim_bake_name_map_from_kind_params(RDIM_Arena *arena, RDI_NameMapKind kind, RDI { for(RDI_U64 idx = 0; idx < n->count; idx += 1) { - RDI_U32 src_file_idx = (RDI_U32)rdim_idx_from_src_file(&n->v[idx]); // TODO(rjf): @u64_to_u32 - rdim_bake_name_map_push(arena, map, n->v[idx].normal_full_path, src_file_idx); + RDI_U64 src_file_idx = rdim_idx_from_src_file(&n->v[idx]); + rdim_bake_name_map_push(arena, map, n->v[idx].normal_full_path, (RDI_U32)src_file_idx); // TODO(rjf): @u64_to_u32 } } }break; @@ -2229,11 +2192,11 @@ rdim_bake_top_level_info_section_list_from_params(RDIM_Arena *arena, RDIM_BakeSt RDIM_BakeSectionList sections = {0}; RDI_TopLevelInfo *dst_tli = rdim_push_array(arena, RDI_TopLevelInfo, 1); RDIM_TopLevelInfo *src_tli = ¶ms->top_level_info; - dst_tli->arch = src_tli->arch; - dst_tli->exe_name_string_idx = rdim_bake_idx_from_string(strings, src_tli->exe_name); - dst_tli->exe_hash = src_tli->exe_hash; - dst_tli->voff_max = src_tli->voff_max; - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_tli, sizeof(*dst_tli), RDI_DataSectionTag_TopLevelInfo, 0); + dst_tli->arch = src_tli->arch; + dst_tli->exe_name_string_idx = rdim_bake_idx_from_string(strings, src_tli->exe_name); + dst_tli->exe_hash = src_tli->exe_hash; + dst_tli->voff_max = src_tli->voff_max; + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_tli, sizeof(*dst_tli), RDI_SectionKind_TopLevelInfo, 0); return sections; } @@ -2257,7 +2220,7 @@ rdim_bake_binary_section_section_list_from_params(RDIM_Arena *arena, RDIM_BakeSt dst->foff_first = src->foff_first; dst->foff_opl = src->foff_opl; } - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_base, sizeof(*dst_base)*dst_idx, RDI_DataSectionTag_BinarySections, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_base, sizeof(*dst_base)*dst_idx, RDI_SectionKind_BinarySections, 0); return sections; } @@ -2275,8 +2238,8 @@ rdim_bake_unit_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTig { RDIM_Unit *src = &src_n->v[src_chunk_idx]; RDI_Unit *dst = &dst_base[dst_idx]; - dst->unit_name_string_idx = (RDI_U32)rdim_bake_idx_from_string(strings, src->unit_name); // TODO(rjf): @u64_to_u32 - dst->compiler_name_string_idx = (RDI_U32)rdim_bake_idx_from_string(strings, src->compiler_name); // TODO(rjf): @u64_to_u32 + dst->unit_name_string_idx = rdim_bake_idx_from_string(strings, src->unit_name); + dst->compiler_name_string_idx = rdim_bake_idx_from_string(strings, src->compiler_name); dst->source_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->source_file); dst->object_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->object_file); dst->archive_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->archive_file); @@ -2285,7 +2248,7 @@ rdim_bake_unit_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTig dst->line_table_idx = (RDI_U32)rdim_idx_from_line_table(src->line_table); // TODO(rjf): @u64_to_u32 } } - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_base, sizeof(*dst_base)*dst_idx, RDI_DataSectionTag_Units, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_base, sizeof(*dst_base)*dst_idx, RDI_SectionKind_Units, 0); return sections; } @@ -2360,7 +2323,7 @@ rdim_bake_unit_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams //- rjf: build section RDIM_BakeSectionList sections = {0}; RDI_U64 unit_vmap_size = sizeof(unit_vmap.vmap[0])*(unit_vmap.count+1); - rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_vmap.vmap, unit_vmap_size, RDI_DataSectionTag_UnitVmap, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_vmap.vmap, unit_vmap_size, RDI_SectionKind_UnitVMap, 0); return sections; } @@ -2612,11 +2575,11 @@ rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMa //////////////////////////// //- rjf: build sections // - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_files, sizeof(RDI_SourceFile)*dst_files_count, RDI_DataSectionTag_SourceFiles, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_maps, sizeof(RDI_SourceLineMap)*dst_maps_count, RDI_DataSectionTag_SourceLineMaps, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, source_line_map_nums, sizeof(RDI_U32)*dst_nums_idx, RDI_DataSectionTag_SourceLineMapNumbers, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, source_line_map_rngs, sizeof(RDI_U32)*dst_rngs_idx, RDI_DataSectionTag_SourceLineMapRanges, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, source_line_map_voffs,sizeof(RDI_U64)*dst_voffs_idx, RDI_DataSectionTag_SourceLineMapVOffs, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_files, sizeof(RDI_SourceFile)*dst_files_count, RDI_SectionKind_SourceFiles, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_maps, sizeof(RDI_SourceLineMap)*dst_maps_count, RDI_SectionKind_SourceLineMaps, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, source_line_map_nums, sizeof(RDI_U32)*dst_nums_idx, RDI_SectionKind_SourceLineMapNumbers, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, source_line_map_rngs, sizeof(RDI_U32)*dst_rngs_idx, RDI_SectionKind_SourceLineMapRanges, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, source_line_map_voffs,sizeof(RDI_U64)*dst_voffs_idx, RDI_SectionKind_SourceLineMapVOffs, 0); rdim_scratch_end(scratch); return sections; @@ -2749,10 +2712,10 @@ rdim_bake_line_table_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams //- rjf: produce sections RDIM_BakeSectionList sections = {0}; { - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_line_tables, sizeof(RDI_LineTable)*params->line_tables.total_count, RDI_DataSectionTag_LineTables, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_line_voffs, sizeof(RDI_U64) * (params->line_tables.total_line_count + params->line_tables.total_seq_count), RDI_DataSectionTag_LineInfoVoffs, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_lines, sizeof(RDI_Line) * (params->line_tables.total_line_count + params->line_tables.total_seq_count), RDI_DataSectionTag_LineInfoLines, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_cols, sizeof(RDI_Column) * params->line_tables.total_col_count, RDI_DataSectionTag_LineInfoColumns, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_line_tables, sizeof(RDI_LineTable)*params->line_tables.total_count, RDI_SectionKind_LineTables, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_line_voffs, sizeof(RDI_U64) * (params->line_tables.total_line_count + params->line_tables.total_seq_count), RDI_SectionKind_LineInfoVOffs, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_lines, sizeof(RDI_Line) * (params->line_tables.total_line_count + params->line_tables.total_seq_count), RDI_SectionKind_LineInfoLines, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_cols, sizeof(RDI_Column) * params->line_tables.total_col_count, RDI_SectionKind_LineInfoColumns, 0); } return sections; } @@ -2828,7 +2791,7 @@ rdim_bake_type_node_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringM //- rjf: build sections RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, type_nodes, sizeof(RDI_TypeNode)*(params->types.total_count+1), RDI_DataSectionTag_TypeNodes, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, type_nodes, sizeof(RDI_TypeNode)*(params->types.total_count+1), RDI_SectionKind_TypeNodes, 0); return sections; } @@ -2896,9 +2859,9 @@ rdim_bake_udt_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTigh //- rjf: build sections RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, udts, sizeof(RDI_UDT) * (params->udts.total_count+1), RDI_DataSectionTag_UDTs, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, members , sizeof(RDI_Member) * (params->udts.total_member_count+1), RDI_DataSectionTag_Members, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, enum_members, sizeof(RDI_EnumMember) * (params->udts.total_enum_val_count+1), RDI_DataSectionTag_EnumMembers, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, udts, sizeof(RDI_UDT) * (params->udts.total_count+1), RDI_SectionKind_UDTs, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, members , sizeof(RDI_Member) * (params->udts.total_member_count+1), RDI_SectionKind_Members, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, enum_members, sizeof(RDI_EnumMember) * (params->udts.total_enum_val_count+1), RDI_SectionKind_EnumMembers, 0); return sections; } @@ -2940,7 +2903,7 @@ rdim_bake_global_variable_section_list_from_params(RDIM_Arena *arena, RDIM_BakeS //- rjf: build sections RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, global_variables, sizeof(RDI_GlobalVariable)*(params->global_variables.total_count+1), RDI_DataSectionTag_GlobalVariables, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, global_variables, sizeof(RDI_GlobalVariable)*(params->global_variables.total_count+1), RDI_SectionKind_GlobalVariables, 0); return sections; } @@ -3020,7 +2983,7 @@ rdim_bake_global_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParam //- rjf: build sections RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, global_vmap.vmap, sizeof(RDI_VMapEntry)*(global_vmap.count+1), RDI_DataSectionTag_GlobalVmap, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, global_vmap.vmap, sizeof(RDI_VMapEntry)*(global_vmap.count+1), RDI_SectionKind_GlobalVMap, 0); return sections; } @@ -3062,7 +3025,7 @@ rdim_bake_thread_variable_section_list_from_params(RDIM_Arena *arena, RDIM_BakeS //- rjf: build sections RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, thread_variables, sizeof(RDI_ThreadVariable)*(params->thread_variables.total_count+1), RDI_DataSectionTag_ThreadVariables, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, thread_variables, sizeof(RDI_ThreadVariable)*(params->thread_variables.total_count+1), RDI_SectionKind_ThreadVariables, 0); return sections; } @@ -3105,7 +3068,7 @@ rdim_bake_procedure_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringM //- rjf: build sections RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, procedures, sizeof(RDI_Procedure)*(params->procedures.total_count+1), RDI_DataSectionTag_Procedures, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, procedures, sizeof(RDI_Procedure)*(params->procedures.total_count+1), RDI_SectionKind_Procedures, 0); return sections; } @@ -3272,11 +3235,11 @@ rdim_bake_scope_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTi RDIM_BakeSectionList sections = {0}; RDIM_ProfScope("push all symbol info sections") { - rdim_bake_section_list_push_new_unpacked(arena, §ions, scopes, sizeof(RDI_Scope) * (params->scopes.total_count+1), RDI_DataSectionTag_Scopes, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, scope_voffs, sizeof(RDI_U64) * (params->scopes.scope_voff_count+1), RDI_DataSectionTag_ScopeVoffData, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, locals, sizeof(RDI_Local) * (params->scopes.local_count+1), RDI_DataSectionTag_Locals, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, location_blocks, sizeof(RDI_LocationBlock) * (params->scopes.location_count+1), RDI_DataSectionTag_LocationBlocks, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, location_data_blob.str, location_data_blob.size, RDI_DataSectionTag_LocationData, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, scopes, sizeof(RDI_Scope) * (params->scopes.total_count+1), RDI_SectionKind_Scopes, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, scope_voffs, sizeof(RDI_U64) * (params->scopes.scope_voff_count+1), RDI_SectionKind_ScopeVOffData, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, locals, sizeof(RDI_Local) * (params->scopes.local_count+1), RDI_SectionKind_Locals, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, location_blocks, sizeof(RDI_LocationBlock) * (params->scopes.location_count+1), RDI_SectionKind_LocationBlocks, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, location_data_blob.str, location_data_blob.size, RDI_SectionKind_LocationData, 0); } rdim_scratch_end(scratch); return sections; @@ -3334,7 +3297,7 @@ rdim_bake_scope_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams //- rjf: build sections RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, scope_vmap.vmap, sizeof(RDI_VMapEntry)*(scope_vmap.count+1), RDI_DataSectionTag_ScopeVmap, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, scope_vmap.vmap, sizeof(RDI_VMapEntry)*(scope_vmap.count+1), RDI_SectionKind_ScopeVMap, 0); return sections; } @@ -3345,22 +3308,12 @@ rdim_bake_top_level_name_map_section_list_from_params_maps(RDIM_Arena *arena, RD { RDIM_BakeSectionList sections = {0}; - //- rjf: count the # of name maps we have with any content - RDI_U32 name_map_count = 0; - for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); - k < RDI_NameMapKind_COUNT; - k = (RDI_NameMapKind)(k+1)) - { - if(name_maps[k] != 0 && name_maps[k]->name_count != 0) - { - name_map_count += 1; - } - } - //- rjf: allocate & fill baked name maps - RDI_NameMap *dst_maps = rdim_push_array(arena, RDI_NameMap, name_map_count); + RDI_NameMap *dst_maps = rdim_push_array(arena, RDI_NameMap, RDI_NameMapKind_COUNT); { RDI_U64 dst_map_idx = 0; + RDI_U64 dst_map_bucket_idx = 0; + RDI_U64 dst_map_node_idx = 0; for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); k < RDI_NameMapKind_COUNT; k = (RDI_NameMapKind)(k+1)) @@ -3369,14 +3322,16 @@ rdim_bake_top_level_name_map_section_list_from_params_maps(RDIM_Arena *arena, RD RDIM_BakeNameMap *src_map = name_maps[k]; if(src_map == 0 || src_map->name_count == 0) { continue; } dst_map->kind = k; - dst_map->bucket_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_NameMapBuckets, (RDI_U64)k); // TODO(rjf): @u64_to_u32 - dst_map->node_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_NameMapNodes, (RDI_U64)k); // TODO(rjf): @u64_to_u32 + dst_map->bucket_base_idx = (RDI_U32)dst_map_bucket_idx; // TODO(rjf): @u64_to_u32 + dst_map->node_base_idx = (RDI_U32)dst_map_node_idx; // TODO(rjf): @u64_to_u32 + dst_map->bucket_count = (RDI_U32)src_map->name_count; // TODO(rjf): @u64_to_u32 + dst_map->node_count = (RDI_U32)src_map->name_count; // TODO(rjf): @u64_to_u32 dst_map_idx += 1; } } // rjf: push section for all name maps - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_maps, sizeof(RDI_NameMap)*name_map_count, RDI_DataSectionTag_NameMaps, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_maps, sizeof(RDI_NameMap)*RDI_NameMapKind_COUNT, RDI_SectionKind_NameMaps, 0); return sections; } @@ -3478,8 +3433,8 @@ rdim_bake_name_map_section_list_from_params_kind_map(RDIM_Arena *arena, RDIM_Bak } // rjf: sections for buckets/nodes - rdim_bake_section_list_push_new_unpacked(arena, §ions, baked_buckets, sizeof(RDI_NameMapBucket)* baked_buckets_count, RDI_DataSectionTag_NameMapBuckets, (RDI_U64)k); - rdim_bake_section_list_push_new_unpacked(arena, §ions, baked_nodes, sizeof(RDI_NameMapNode) * baked_nodes_count, RDI_DataSectionTag_NameMapNodes, (RDI_U64)k); + rdim_bake_section_list_push_new_unpacked(arena, §ions, baked_buckets, sizeof(RDI_NameMapBucket)* baked_buckets_count, RDI_SectionKind_NameMapBuckets, (RDI_U64)k); + rdim_bake_section_list_push_new_unpacked(arena, §ions, baked_nodes, sizeof(RDI_NameMapNode) * baked_nodes_count, RDI_SectionKind_NameMapNodes, (RDI_U64)k); } return sections; } @@ -3515,7 +3470,7 @@ rdim_bake_file_path_section_list_from_path_tree(RDIM_Arena *arena, RDIM_BakeStri } } RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_nodes, sizeof(RDI_FilePathNode)*dst_nodes_count, RDI_DataSectionTag_FilePathNodes, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_nodes, sizeof(RDI_FilePathNode)*dst_nodes_count, RDI_SectionKind_FilePathNodes, 0); return sections; } @@ -3561,8 +3516,8 @@ rdim_bake_string_section_list_from_string_map(RDIM_Arena *arena, RDIM_BakeString } } } - rdim_bake_section_list_push_new_unpacked(arena, §ions, str_offs, sizeof(RDI_U32)*(strings->total_count+1), RDI_DataSectionTag_StringTable, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, buf, off_cursor, RDI_DataSectionTag_StringData, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, str_offs, sizeof(RDI_U32)*(strings->total_count+1), RDI_SectionKind_StringTable, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, buf, off_cursor, RDI_SectionKind_StringData, 0); return sections; } @@ -3584,7 +3539,7 @@ rdim_bake_idx_run_section_list_from_idx_run_map(RDIM_Arena *arena, RDIM_BakeIdxR out_ptr += node->count; } } - rdim_bake_section_list_push_new_unpacked(arena, §ions, idx_data, sizeof(RDI_U32)*idx_runs->idx_count, RDI_DataSectionTag_IndexRuns, 0); + rdim_bake_section_list_push_new_unpacked(arena, §ions, idx_data, sizeof(RDI_U32)*idx_runs->idx_count, RDI_SectionKind_IndexRuns, 0); return sections; } @@ -3599,15 +3554,13 @@ rdim_serialized_strings_from_params_bake_section_list(RDIM_Arena *arena, RDIM_Ba { RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - //- rjf: calculate total possible section count, given these params - RDI_U64 section_count = rdim_bake_section_count_from_params(params); - //- rjf: make table for actually laid out sections + RDI_U64 section_count = RDI_SectionKind_COUNT; RDIM_BakeSection **bake_sections = rdim_push_array(scratch.arena, RDIM_BakeSection *, section_count); for(RDIM_BakeSectionNode *n = sections->first; n != 0; n = n->next) { RDIM_BakeSection *bake_section = &n->v; - RDI_U64 idx = rdim_bake_section_idx_from_params_tag_idx(params, bake_section->tag, bake_section->tag_idx); + RDI_U64 idx = (RDI_U64)bake_section->tag; if(0 <= idx && idx < section_count) { if(bake_sections[idx] != 0) @@ -3623,11 +3576,11 @@ rdim_serialized_strings_from_params_bake_section_list(RDIM_Arena *arena, RDIM_Ba //- rjf: push empty header & data section table RDI_Header *rdi_header = rdim_push_array(arena, RDI_Header, 1); - RDI_DataSection *rdi_sections = rdim_push_array(arena, RDI_DataSection, section_count); + RDI_Section *rdi_sections = rdim_push_array(arena, RDI_Section, section_count); rdim_str8_list_push(arena, &strings, rdim_str8_struct(rdi_header)); rdim_str8_list_push_align(arena, &strings, 8); U32 data_section_off = (U32)strings.total_size; - rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)rdi_sections, sizeof(RDI_DataSection)*section_count)); + rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)rdi_sections, sizeof(RDI_Section)*section_count)); // rjf: fill baked header { @@ -3643,7 +3596,7 @@ rdim_serialized_strings_from_params_bake_section_list(RDIM_Arena *arena, RDIM_Ba { RDIM_BakeSection *src = bake_sections[src_idx]; if(src == 0) { continue; } - RDI_DataSection *dst = rdi_sections+dst_idx; + RDI_Section *dst = rdi_sections+dst_idx; U64 data_section_off = 0; if(src->encoded_size != 0) { @@ -3651,7 +3604,6 @@ rdim_serialized_strings_from_params_bake_section_list(RDIM_Arena *arena, RDIM_Ba data_section_off = strings.total_size; rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)src->data, src->encoded_size)); } - dst->tag = src->tag; dst->encoding = src->encoding; dst->off = data_section_off; dst->encoded_size = src->encoded_size; diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index ce8330fb..0e7dbe8d 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -878,10 +878,10 @@ typedef struct RDIM_BakeSection RDIM_BakeSection; struct RDIM_BakeSection { void *data; - RDI_DataSectionEncoding encoding; + RDI_SectionEncoding encoding; RDI_U64 encoded_size; RDI_U64 unpacked_size; - RDI_DataSectionTag tag; + RDI_SectionKind tag; RDI_U64 tag_idx; }; @@ -1190,12 +1190,6 @@ RDI_PROC RDIM_Location *rdim_push_location_val_reg(RDIM_Arena *arena, RDI_U8 reg //- rjf: location sets RDI_PROC void rdim_location_set_push_case(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_LocationSet *locset, RDIM_Rng1U64 voff_range, RDIM_Location *location); -//////////////////////////////// -//~ rjf: [Baking Helpers] Baked File Layout Calculations - -RDI_PROC RDI_U64 rdim_bake_section_count_from_params(RDIM_BakeParams *params); -RDI_PROC RDI_U64 rdim_bake_section_idx_from_params_tag_idx(RDIM_BakeParams *params, RDI_DataSectionTag tag, RDI_U64 idx); - //////////////////////////////// //~ rjf: [Baking Helpers] Baked VMap Building @@ -1217,7 +1211,7 @@ RDI_PROC RDIM_BakeStringMapBaseIndices rdim_bake_string_map_base_indices_from_ma //- rjf: finalized bake string map RDI_PROC RDIM_BakeStringMapTight rdim_bake_string_map_tight_from_loose(RDIM_Arena *arena, RDIM_BakeStringMapTopology *map_topology, RDIM_BakeStringMapBaseIndices *map_base_indices, RDIM_BakeStringMapLoose *map); -RDI_PROC RDI_U64 rdim_bake_idx_from_string(RDIM_BakeStringMapTight *map, RDIM_String8 string); +RDI_PROC RDI_U32 rdim_bake_idx_from_string(RDIM_BakeStringMapTight *map, RDIM_String8 string); //- rjf: bake idx run map reading/writing RDI_PROC RDI_U64 rdim_hash_from_idx_run(RDI_U32 *idx_run, RDI_U32 count); @@ -1236,7 +1230,7 @@ RDI_PROC void rdim_bake_name_map_push(RDIM_Arena *arena, RDIM_BakeNameMap *map, //~ rjf: [Baking Helpers] Data Section List Building Helpers RDI_PROC RDIM_BakeSection *rdim_bake_section_list_push(RDIM_Arena *arena, RDIM_BakeSectionList *list); -RDI_PROC RDIM_BakeSection *rdim_bake_section_list_push_new_unpacked(RDIM_Arena *arena, RDIM_BakeSectionList *list, void *data, RDI_U64 size, RDI_DataSectionTag tag, RDI_U64 tag_idx); +RDI_PROC RDIM_BakeSection *rdim_bake_section_list_push_new_unpacked(RDIM_Arena *arena, RDIM_BakeSectionList *list, void *data, RDI_U64 size, RDI_SectionKind tag, RDI_U64 tag_idx); RDI_PROC void rdim_bake_section_list_concat_in_place(RDIM_BakeSectionList *dst, RDIM_BakeSectionList *to_push); //////////////////////////////// diff --git a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c index 227a72e0..8a125b47 100644 --- a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c +++ b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c @@ -77,7 +77,7 @@ internal TS_TASK_FUNCTION_DEF(p2b_bake_unit_vmap_task__entry_point) switch(n->v.tag) { default:{}break; - case RDI_DataSectionTag_UnitVmap:{vmap_section = &n->v;}break; + case RDI_SectionKind_UnitVmap:{vmap_section = &n->v;}break; } } if(vmap_section != 0) @@ -116,8 +116,8 @@ internal TS_TASK_FUNCTION_DEF(p2b_bake_unit_task__entry_point) switch(n->v.tag) { default:{}break; - case RDI_DataSectionTag_LineInfoVoffs:{voffs_section = &n->v;}break; - case RDI_DataSectionTag_LineInfoData: {lines_section = &n->v;}break; + case RDI_SectionKind_LineInfoVoffs:{voffs_section = &n->v;}break; + case RDI_SectionKind_LineInfoData: {lines_section = &n->v;}break; } } if(voffs_section != 0 && lines_section != 0) diff --git a/src/rdi_dump/rdi_dump.c b/src/rdi_dump/rdi_dump.c index c1647c20..4aa3e7cf 100644 --- a/src/rdi_dump/rdi_dump.c +++ b/src/rdi_dump/rdi_dump.c @@ -5,14 +5,14 @@ //~ rjf: RDI Enum -> String Functions internal String8 -rdi_string_from_data_section_tag(RDI_DataSectionTag v) +rdi_string_from_data_section_kind(RDI_SectionKind v) { - String8 result = str8_lit(""); + String8 result = str8_lit(""); switch(v) { default:{}break; -#define X(name) case RDI_DataSectionTag_##name:{result = str8_lit(#name);}break; - RDI_DataSectionTag_XList +#define X(name, lower, type) case RDI_SectionKind_##name:{result = str8_lit(#name);}break; + RDI_SectionKind_XList #undef X } return result; @@ -134,35 +134,35 @@ rdi_stringize_link_flags(Arena *arena, String8List *out, RDI_LinkFlags flags) global char rdi_stringize_spaces[] = " "; internal void -rdi_stringize_data_sections(Arena *arena, String8List *out, RDI_Parsed *parsed, U32 indent_level) +rdi_stringize_data_sections(Arena *arena, String8List *out, RDI_Parsed *rdi, 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) + for(U64 idx = 0; idx < rdi->sections_count; idx += 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", + RDI_SectionKind kind = (RDI_SectionKind)idx; + RDI_Section *section = &rdi->sections[idx]; + String8 kind_str = rdi_string_from_data_section_kind(kind); + str8_list_pushf(arena, out, "%.*sdata_section[%5I64u] = {0x%08llx, %7u, %7u} %S\n", indent_level, rdi_stringize_spaces, - i, ptr->off, ptr->encoded_size, ptr->unpacked_size, str8_varg(tag_str)); + idx, section->off, section->encoded_size, section->unpacked_size, kind_str); } } internal void -rdi_stringize_top_level_info(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_TopLevelInfo *tli, U32 indent_level) +rdi_stringize_top_level_info(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_TopLevelInfo *tli, U32 indent_level) { String8 arch_str = rdi_string_from_arch(tli->arch); String8 exe_name = {0}; - exe_name.str = rdi_string_from_idx(parsed, tli->exe_name_string_idx, &exe_name.size); + exe_name.str = rdi_string_from_idx(rdi, tli->exe_name_string_idx, &exe_name.size); str8_list_pushf(arena, out, "%.*sarch=%.*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) +rdi_stringize_binary_section(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_BinarySection *bin_section, U32 indent_level) { String8 name = {0}; - name.str = rdi_string_from_idx(parsed, bin_section->name_string_idx, &name.size); + name.str = rdi_string_from_idx(rdi, 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); @@ -176,10 +176,10 @@ rdi_stringize_binary_section(Arena *arena, String8List *out, RDI_Parsed *parsed, } internal void -rdi_stringize_file_path(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_FilePathBundle *bundle, RDI_FilePathNode *file_path, U32 indent_level) +rdi_stringize_file_path(Arena *arena, String8List *out, RDI_Parsed *rdi, 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); + name.str = rdi_string_from_idx(rdi, file_path->name_string_idx, &name.size); U32 this_idx = (U32)(file_path - bundle->file_paths); if(file_path->source_file_idx == 0) { @@ -206,7 +206,7 @@ rdi_stringize_file_path(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_ } // stringize child - rdi_stringize_file_path(arena, out, parsed, bundle, child_node, indent_level + 1); + rdi_stringize_file_path(arena, out, rdi, bundle, child_node, indent_level + 1); // increment iterator child = child_node->next_sibling; @@ -214,11 +214,11 @@ rdi_stringize_file_path(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_ } internal void -rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_SourceFile *source_file, U32 indent_level) +rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_SourceFile *source_file, U32 indent_level) { // normal source path String8 path = {0}; - path.str = rdi_string_from_idx(parsed, source_file->normal_full_path_string_idx, &path.size); + path.str = rdi_string_from_idx(rdi, source_file->normal_full_path_string_idx, &path.size); str8_list_pushf(arena, out, "%.*spath: \"%S\"\n", indent_level, rdi_stringize_spaces, path); // rjf: source line map idx @@ -226,11 +226,11 @@ rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *parsed, RD } internal void -rdi_stringize_line_table(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_LineTable *line_table, U32 indent_level) +rdi_stringize_line_table(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_LineTable *line_table, U32 indent_level) { // rjf: parse line table RDI_ParsedLineTable parsed_line_table = {0}; - rdi_parsed_from_line_table(parsed, line_table, &parsed_line_table); + rdi_parsed_from_line_table(rdi, line_table, &parsed_line_table); // rjf: stringize lines str8_list_pushf(arena, out, "%.*slines:\n", indent_level, rdi_stringize_spaces); @@ -261,10 +261,10 @@ rdi_stringize_line_table(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI } internal void -rdi_stringize_source_line_map(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_SourceLineMap *map, U32 indent_level) +rdi_stringize_source_line_map(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_SourceLineMap *map, U32 indent_level) { RDI_ParsedSourceLineMap line_map = {0}; - rdi_parsed_from_source_line_map(parsed, map, &line_map); + rdi_parsed_from_source_line_map(rdi, map, &line_map); str8_list_pushf(arena, out, "%.*slines:\n", indent_level, rdi_stringize_spaces); for(U32 i = 0; i < line_map.count; i += 1) @@ -307,12 +307,12 @@ rdi_stringize_source_line_map(Arena *arena, String8List *out, RDI_Parsed *parsed } internal void -rdi_stringize_unit(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_Unit *unit, U32 indent_level) +rdi_stringize_unit(Arena *arena, String8List *out, RDI_Parsed *rdi, 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); + unit_name.str = rdi_string_from_idx(rdi, 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); + compiler_name.str = rdi_string_from_idx(rdi, 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)); @@ -329,7 +329,7 @@ rdi_stringize_unit(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_Unit } internal void -rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, +rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_TypeNode *type, U32 indent_level){ RDI_TypeKind kind = type->kind; String8 type_kind_str = rdi_string_from_type_kind(kind); @@ -360,7 +360,7 @@ rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, 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); + name.str = rdi_string_from_idx(rdi, 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)); } @@ -381,7 +381,7 @@ rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, 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 *run = rdi_idx_run_from_first_count(rdi, run_first, run_count_raw, &run_count); U32 this_type_idx = 0; if (run_count > 0 && type->kind == RDI_TypeKind_Method){ @@ -413,7 +413,7 @@ rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, 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); + name.str = rdi_string_from_idx(rdi, 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", @@ -433,7 +433,7 @@ rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, } internal void -rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *parsed, +rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_UDTMemberBundle *member_bundle, RDI_UDT *udt, U32 indent_level){ str8_list_pushf(arena, out, "%.*sself_type=%u\n", @@ -461,7 +461,7 @@ rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *parsed, 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); + name.str = rdi_string_from_idx(rdi, 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); @@ -489,7 +489,7 @@ rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *parsed, if (member->name_string_idx != 0){ String8 name = {0}; - name.str = rdi_string_from_idx(parsed, member->name_string_idx, &name.size); + name.str = rdi_string_from_idx(rdi, member->name_string_idx, &name.size); str8_list_pushf(arena, out, "%.*s name='%.*s'\n", indent_level, rdi_stringize_spaces, str8_varg(name)); } @@ -507,10 +507,10 @@ rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *parsed, } internal void -rdi_stringize_global_variable(Arena *arena, String8List *out, RDI_Parsed *parsed, +rdi_stringize_global_variable(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_GlobalVariable *global_variable, U32 indent_level){ String8 name = {0}; - name.str = rdi_string_from_idx(parsed, global_variable->name_string_idx, &name.size); + name.str = rdi_string_from_idx(rdi, global_variable->name_string_idx, &name.size); str8_list_pushf(arena, out, "%.*sname='%.*s'\n", indent_level, rdi_stringize_spaces, str8_varg(name)); @@ -529,11 +529,11 @@ rdi_stringize_global_variable(Arena *arena, String8List *out, RDI_Parsed *parsed } internal void -rdi_stringize_thread_variable(Arena *arena, String8List *out, RDI_Parsed *parsed, +rdi_stringize_thread_variable(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_ThreadVariable *thread_var, U32 indent_level){ String8 name = {0}; - name.str = rdi_string_from_idx(parsed, thread_var->name_string_idx, &name.size); + name.str = rdi_string_from_idx(rdi, thread_var->name_string_idx, &name.size); str8_list_pushf(arena, out, "%.*sname='%.*s'\n", indent_level, rdi_stringize_spaces, str8_varg(name)); @@ -552,15 +552,15 @@ rdi_stringize_thread_variable(Arena *arena, String8List *out, RDI_Parsed *parsed } internal void -rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *parsed, +rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_Procedure *proc, U32 indent_level){ String8 name = {0}; - name.str = rdi_string_from_idx(parsed, proc->name_string_idx, &name.size); + name.str = rdi_string_from_idx(rdi, 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); + link_name.str = rdi_string_from_idx(rdi, 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)); @@ -579,7 +579,7 @@ rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *parsed, } internal void -rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *parsed, +rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_ScopeBundle *bundle, RDI_Scope *scope, U32 indent_level){ U32 this_idx = (U32)(scope - bundle->scopes); @@ -638,7 +638,7 @@ rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *parsed, 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); + name.str = rdi_string_from_idx(rdi, local_ptr->name_string_idx, &name.size); str8_list_pushf(arena, out, "%.*s name='%.*s'\n", indent_level, rdi_stringize_spaces, str8_varg(name)); @@ -756,7 +756,7 @@ rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *parsed, } // stringize child - rdi_stringize_scope(arena, out, parsed, bundle, child_scope, indent_level + 1); + rdi_stringize_scope(arena, out, rdi, bundle, child_scope, indent_level + 1); // increment iterator child = child_scope->next_sibling_scope_idx; diff --git a/src/rdi_dump/rdi_dump.h b/src/rdi_dump/rdi_dump.h index 18534566..0ebe6479 100644 --- a/src/rdi_dump/rdi_dump.h +++ b/src/rdi_dump/rdi_dump.h @@ -11,7 +11,7 @@ typedef struct RDI_FilePathBundle RDI_FilePathBundle; struct RDI_FilePathBundle { RDI_FilePathNode *file_paths; - U32 file_path_count; + U64 file_path_count; }; typedef struct RDI_UDTMemberBundle RDI_UDTMemberBundle; @@ -41,7 +41,7 @@ struct RDI_ScopeBundle //////////////////////////////// //~ rjf: RDI Enum -> String Functions -internal String8 rdi_string_from_data_section_tag(RDI_DataSectionTag v); +internal String8 rdi_string_from_data_section_kind(RDI_SectionKind v); internal String8 rdi_string_from_arch(RDI_Arch v); internal String8 rdi_string_from_language(RDI_Language v); internal String8 rdi_string_from_type_kind(RDI_TypeKind v); @@ -59,19 +59,19 @@ internal void rdi_stringize_link_flags(Arena *arena, String8List *out, RDI_LinkF //////////////////////////////// //~ rjf: RDI 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_line_table(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_LineTable *line_table, U32 indent_level); -internal void rdi_stringize_source_line_map(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_SourceLineMap *map, 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); +internal void rdi_stringize_data_sections(Arena *arena, String8List *out, RDI_Parsed *rdi, U32 indent_level); +internal void rdi_stringize_top_level_info(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_TopLevelInfo *tli, U32 indent_level); +internal void rdi_stringize_binary_section(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_BinarySection *bin_section, U32 indent_level); +internal void rdi_stringize_file_path(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_FilePathBundle *bundle, RDI_FilePathNode *file_path, U32 indent_level); +internal void rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_SourceFile *source_file, U32 indent_level); +internal void rdi_stringize_line_table(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_LineTable *line_table, U32 indent_level); +internal void rdi_stringize_source_line_map(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_SourceLineMap *map, U32 indent_level); +internal void rdi_stringize_unit(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_Unit *unit, U32 indent_level); +internal void rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_TypeNode *type, U32 indent_level); +internal void rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_UDTMemberBundle *bundle, RDI_UDT *udt, U32 indent_level); +internal void rdi_stringize_global_variable(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_GlobalVariable *global_variable, U32 indent_level); +internal void rdi_stringize_thread_variable(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_ThreadVariable *thread_var, U32 indent_level); +internal void rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_Procedure *proc, U32 indent_level); +internal void rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_ScopeBundle *bundle, RDI_Scope *scope, U32 indent_level); #endif // RDI_DUMP_H diff --git a/src/rdi_dump/rdi_dump_main.c b/src/rdi_dump/rdi_dump_main.c index 7bd37ec2..3e26bdb6 100644 --- a/src/rdi_dump/rdi_dump_main.c +++ b/src/rdi_dump/rdi_dump_main.c @@ -174,7 +174,8 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_TopLevelInfo) { str8_list_pushf(arena, &dump, "# TOP LEVEL INFO:\n"); - rdi_stringize_top_level_info(arena, &dump, rdi, rdi->top_level_info, 1); + RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); + rdi_stringize_top_level_info(arena, &dump, rdi, tli, 1); str8_list_push(arena, &dump, str8_lit("\n")); } @@ -182,11 +183,12 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_BinarySections) { str8_list_pushf(arena, &dump, "# BINARY SECTIONS:\n"); - RDI_BinarySection *ptr = rdi->binary_sections; - for(U32 i = 0; i < rdi->binary_sections_count; i += 1, ptr += 1) + U64 count = 0; + RDI_BinarySection *v = rdi_table_from_name(rdi, BinarySections, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " section[%u]:\n", i); - rdi_stringize_binary_section(arena, &dump, rdi, ptr, 2); + str8_list_pushf(arena, &dump, " section[%I64u]:\n", idx); + rdi_stringize_binary_section(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -195,13 +197,10 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_FilePaths) { RDI_FilePathBundle file_path_bundle = {0}; - { - file_path_bundle.file_paths = rdi->file_paths; - file_path_bundle.file_path_count = rdi->file_paths_count; - } + file_path_bundle.file_paths = rdi_table_from_name(rdi, FilePathNodes, &file_path_bundle.file_path_count); str8_list_pushf(arena, &dump, "# FILE PATHS\n"); - RDI_FilePathNode *ptr = rdi->file_paths; - for(U32 i = 0; i < rdi->file_paths_count; i += 1, ptr += 1) + RDI_FilePathNode *ptr = file_path_bundle.file_paths; + for(U32 i = 0; i < file_path_bundle.file_path_count; i += 1, ptr += 1) { if(ptr->parent_path_node == 0) { @@ -215,11 +214,12 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_SourceFiles) { str8_list_pushf(arena, &dump, "# SOURCE FILES\n"); - RDI_SourceFile *ptr = rdi->source_files; - for(U32 i = 0; i < rdi->source_files_count; i += 1, ptr += 1) + U64 count = 0; + RDI_SourceFile *v = rdi_table_from_name(rdi, SourceFiles, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " source_file[%u]:\n", i); - rdi_stringize_source_file(arena, &dump, rdi, ptr, 2); + str8_list_pushf(arena, &dump, " source_file[%I64u]:\n", idx); + rdi_stringize_source_file(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -228,11 +228,12 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_LineTables) { str8_list_pushf(arena, &dump, "# LINE TABLES\n"); - RDI_LineTable *ptr = rdi->line_tables; - for(U32 i = 0; i < rdi->line_tables_count; i += 1, ptr += 1) + U64 count = 0; + RDI_LineTable *v = rdi_table_from_name(rdi, LineTables, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " line_table[%u]:\n", i); - rdi_stringize_line_table(arena, &dump, rdi, ptr, 2); + str8_list_pushf(arena, &dump, " line_table[%I64u]:\n", idx); + rdi_stringize_line_table(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -241,11 +242,12 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_SourceLineMaps) { str8_list_pushf(arena, &dump, "# SOURCE LINE MAPS\n"); - RDI_SourceLineMap *ptr = rdi->source_line_maps; - for(U32 i = 0; i < rdi->source_line_maps_count; i += 1, ptr += 1) + U64 count = 0; + RDI_SourceLineMap *v = rdi_table_from_name(rdi, SourceLineMaps, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " source_line_map[%u]:\n", i); - rdi_stringize_source_line_map(arena, &dump, rdi, ptr, 2); + str8_list_pushf(arena, &dump, " source_line_map[%I64u]:\n", idx); + rdi_stringize_source_line_map(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -254,11 +256,12 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_Units) { str8_list_pushf(arena, &dump, "# UNITS\n"); - RDI_Unit *ptr = rdi->units; - for (U32 i = 0; i < rdi->units_count; i += 1, ptr += 1) + U64 count = 0; + RDI_Unit *v = rdi_table_from_name(rdi, Units, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " unit[%u]:\n", i); - rdi_stringize_unit(arena, &dump, rdi, ptr, 2); + str8_list_pushf(arena, &dump, " unit[%I64u]:\n", idx); + rdi_stringize_unit(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -267,10 +270,11 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_UnitVMap) { str8_list_pushf(arena, &dump, "# UNIT VMAP\n"); - RDI_VMapEntry *ptr = rdi->unit_vmap; - for(U32 i = 0; i < rdi->unit_vmap_count; i += 1, ptr += 1) + U64 count = 0; + RDI_VMapEntry *v = rdi_table_from_name(rdi, UnitVMap, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", ptr->voff, ptr->idx); + str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", v[idx].voff, v[idx].idx); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -279,11 +283,12 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_TypeNodes) { str8_list_pushf(arena, &dump, "# TYPE NODES:\n"); - RDI_TypeNode *ptr = rdi->type_nodes; - for(U32 i = 0; i < rdi->type_nodes_count; i += 1, ptr += 1) + U64 count = 0; + RDI_TypeNode *v = rdi_table_from_name(rdi, TypeNodes, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " type[%u]:\n", i); - rdi_stringize_type_node(arena, &dump, rdi, ptr, 2); + str8_list_pushf(arena, &dump, " type[%I64u]:\n", idx); + rdi_stringize_type_node(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -291,19 +296,24 @@ entry_point(CmdLine *cmd_line) //- rjf: UDT DATA if(dump_flags & DumpFlag_UDTs) { + U64 all_members_count = 0; + RDI_Member *all_members = rdi_table_from_name(rdi, Members, &all_members_count); + U64 all_enum_members_count = 0; + RDI_EnumMember *all_enum_members = rdi_table_from_name(rdi, EnumMembers, &all_enum_members_count); + U64 all_udts_count = 0; + RDI_UDT *all_udts = rdi_table_from_name(rdi, UDTs, &all_udts_count); RDI_UDTMemberBundle member_bundle = {0}; { - member_bundle.members = rdi->members; - member_bundle.enum_members = rdi->enum_members; - member_bundle.member_count = rdi->members_count; - member_bundle.enum_member_count = rdi->enum_members_count; + member_bundle.members = all_members; + member_bundle.enum_members = all_enum_members; + member_bundle.member_count = (RDI_U32)all_members_count; + member_bundle.enum_member_count = (RDI_U32)all_enum_members_count; } str8_list_pushf(arena, &dump, "# UDTS:\n"); - RDI_UDT *ptr = rdi->udts; - for(U32 i = 0; i < rdi->udts_count; i += 1, ptr += 1) + for(U64 idx = 0; idx < all_udts_count; idx += 1) { - str8_list_pushf(arena, &dump, " udt[%u]:\n", i); - rdi_stringize_udt(arena, &dump, rdi, &member_bundle, ptr, 2); + str8_list_pushf(arena, &dump, " udt[%I64u]:\n", idx); + rdi_stringize_udt(arena, &dump, rdi, &member_bundle, &all_udts[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -312,11 +322,12 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_GlobalVariables) { str8_list_pushf(arena, &dump, "# GLOBAL VARIABLES:\n"); - RDI_GlobalVariable *ptr = rdi->global_variables; - for(U32 i = 0; i < rdi->global_variables_count; i += 1, ptr += 1) + RDI_U64 count = 0; + RDI_GlobalVariable *v = rdi_table_from_name(rdi, GlobalVariables, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " global_variable[%u]:\n", i); - rdi_stringize_global_variable(arena, &dump, rdi, ptr, 2); + str8_list_pushf(arena, &dump, " global_variable[%I64u]:\n", idx); + rdi_stringize_global_variable(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -325,10 +336,11 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_GlobalVMap) { str8_list_pushf(arena, &dump, "# GLOBAL VMAP:\n"); - RDI_VMapEntry *ptr = rdi->global_vmap; - for(U32 i = 0; i < rdi->global_vmap_count; i += 1, ptr += 1) + U64 count = 0; + RDI_VMapEntry *v = rdi_table_from_name(rdi, GlobalVMap, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", ptr->voff, ptr->idx); + str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", v[idx].voff, v[idx].idx); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -337,11 +349,12 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_ThreadVariables) { str8_list_pushf(arena, &dump, "# THREAD VARIABLES:\n"); - RDI_ThreadVariable *ptr = rdi->thread_variables; - for(U32 i = 0; i < rdi->thread_variables_count; i += 1, ptr += 1) + U64 count = 0; + RDI_ThreadVariable *v = rdi_table_from_name(rdi, ThreadVariables, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " thread_variable[%u]:\n", i); - rdi_stringize_thread_variable(arena, &dump, rdi, ptr, 2); + str8_list_pushf(arena, &dump, " thread_variable[%I64u]:\n", idx); + rdi_stringize_thread_variable(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -350,11 +363,12 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_Procedures) { str8_list_pushf(arena, &dump, "# PROCEDURES:\n"); - RDI_Procedure *ptr = rdi->procedures; - for(U32 i = 0; i < rdi->procedures_count; i += 1, ptr += 1) + U64 count = 0; + RDI_Procedure *v = rdi_table_from_name(rdi, Procedures, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " procedure[%u]:\n", i); - rdi_stringize_procedure(arena, &dump, rdi, ptr, 2); + str8_list_pushf(arena, &dump, " procedure[%I64u]:\n", idx); + rdi_stringize_procedure(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -362,26 +376,35 @@ entry_point(CmdLine *cmd_line) //- rjf: SCOPES if(dump_flags & DumpFlag_Scopes) { + U64 scopes_count = 0; + RDI_Scope *scopes = rdi_table_from_name(rdi, Scopes, &scopes_count); + U64 scopes_voffs_count = 0; + U64 *scopes_voffs = rdi_table_from_name(rdi, ScopeVOffData, &scopes_voffs_count); + U64 locals_count = 0; + RDI_Local *locals = rdi_table_from_name(rdi, Locals, &locals_count); + U64 location_block_count = 0; + RDI_LocationBlock *location_blocks = rdi_table_from_name(rdi, LocationBlocks, &location_block_count); + U64 location_data_size = 0; + RDI_U8 *location_data = rdi_table_from_name(rdi, LocationData, &location_data_size); RDI_ScopeBundle scope_bundle = {0}; { - scope_bundle.scopes = rdi->scopes; - scope_bundle.scope_count = rdi->scopes_count; - scope_bundle.scope_voffs = rdi->scope_voffs; - scope_bundle.scope_voff_count = rdi->scope_voffs_count; - scope_bundle.locals = rdi->locals; - scope_bundle.local_count = rdi->locals_count; - scope_bundle.location_blocks = rdi->location_blocks; - scope_bundle.location_block_count = rdi->location_blocks_count; - scope_bundle.location_data = rdi->location_data; - scope_bundle.location_data_size = rdi->location_data_size; + scope_bundle.scopes = scopes; + scope_bundle.scope_count = scopes_count; + scope_bundle.scope_voffs = scopes_voffs; + scope_bundle.scope_voff_count = scopes_voffs_count; + scope_bundle.locals = locals; + scope_bundle.local_count = locals_count; + scope_bundle.location_blocks = location_blocks; + scope_bundle.location_block_count = location_block_count; + scope_bundle.location_data = location_data; + scope_bundle.location_data_size = location_data_size; } str8_list_pushf(arena, &dump, "# SCOPES:\n"); - RDI_Scope *ptr = rdi->scopes; - for(U32 i = 0; i < rdi->scopes_count; i += 1, ptr += 1) + for(U64 idx = 0; idx < scopes_count; idx += 1) { - if(ptr->parent_scope_idx == 0) + if(scopes[idx].parent_scope_idx == 0) { - rdi_stringize_scope(arena, &dump, rdi, &scope_bundle, ptr, 1); + rdi_stringize_scope(arena, &dump, rdi, &scope_bundle, &scopes[idx], 1); } } str8_list_push(arena, &dump, str8_lit("\n")); @@ -391,10 +414,11 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_ScopeVMap) { str8_list_pushf(arena, &dump, "# SCOPE VMAP:\n"); - RDI_VMapEntry *ptr = rdi->scope_vmap; - for(U32 i = 0; i < rdi->scope_vmap_count; i += 1, ptr += 1) + U64 count = 0; + RDI_VMapEntry *v = rdi_table_from_name(rdi, ScopeVMap, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", ptr->voff, ptr->idx); + str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", v[idx].voff, v[idx].idx); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -403,12 +427,13 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_NameMaps) { str8_list_pushf(arena, &dump, "# NAME MAP:\n"); - RDI_NameMap *ptr = rdi->name_maps; - for(U32 i = 0; i < rdi->name_maps_count; i += 1, ptr += 1) + U64 count = 0; + RDI_NameMap *v = rdi_table_from_name(rdi, NameMaps, &count); + for(U64 idx = 0; idx < count; idx += 1) { RDI_ParsedNameMap name_map = {0}; - rdi_name_map_parse(rdi, ptr, &name_map); - str8_list_pushf(arena, &dump, " name_map[%u]:\n", i); + rdi_parsed_from_name_map(rdi, &v[idx], &name_map); + str8_list_pushf(arena, &dump, " name_map[%I64u]:\n", idx); RDI_NameMapBucket *bucket = name_map.buckets; for(U32 j = 0; j < name_map.bucket_count; j += 1, bucket += 1) { @@ -455,11 +480,13 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_Strings) { str8_list_pushf(arena, &dump, "# STRINGS:\n"); - for(U64 string_idx = 0; string_idx < rdi->string_count; string_idx += 1) + U64 count = 0; + U32 *v = rdi_table_from_name(rdi, StringTable, &count); + for(U64 idx = 0; idx < count; idx += 1) { String8 string = {0}; - string.str = rdi_string_from_idx(rdi, string_idx, &string.size); - str8_list_pushf(arena, &dump, " string[%I64u]: \"%S\"\n", string_idx, string); + string.str = rdi_string_from_idx(rdi, (RDI_U32)idx, &string.size); + str8_list_pushf(arena, &dump, " string[%I64u]: \"%S\"\n", idx, string); } str8_list_push(arena, &dump, str8_lit("\n")); } diff --git a/src/rdi_format/rdi_format.mdesk b/src/rdi_format/rdi_format.mdesk index 7ef0a47f..1177f352 100644 --- a/src/rdi_format/rdi_format.mdesk +++ b/src/rdi_format/rdi_format.mdesk @@ -51,11 +51,18 @@ "#endif"; ""; "////////////////////////////////////////////////////////////////"; + "//~ Overridable Enabling/Disabling Of Table Index Typechecking"; + ""; + "#if !defined(RDI_DISABLE_TABLE_INDEX_TYPECHECKING)"; + "# define RDI_DISABLE_TABLE_INDEX_TYPECHECKING 0"; + "#endif"; + ""; + "////////////////////////////////////////////////////////////////"; "//~ Format Constants"; ""; "// \"raddbg\0\0\""; "#define RDI_MAGIC_CONSTANT 0x0000676264646172"; - "#define RDI_ENCODING_VERSION 3"; + "#define RDI_ENCODING_VERSION 4"; ""; "////////////////////////////////////////////////////////////////"; "//~ Format Types & Functions"; @@ -108,96 +115,123 @@ RDI_HeaderMemberTable: } //////////////////////////////// -//~ rjf: Format Data Section Tables +//~ rjf: Format Section Tables -@table(name value desc) -RDI_DataSectionTable: +@table(name name_lower element_type value is_required index_base_type desc) +RDI_SectionTable: { - {NULL 0x0000 ""} - {TopLevelInfo 0x0001 ""} - {StringData 0x0002 ""} - {StringTable 0x0003 ""} - {IndexRuns 0x0004 ""} - {BinarySections 0x0005 ""} - {FilePathNodes 0x0006 ""} - {SourceFiles 0x0007 ""} - {LineTables 0x0008 ""} - {LineInfoVoffs 0x0009 ""} - {LineInfoLines 0x000A ""} - {LineInfoColumns 0x000B ""} - {SourceLineMaps 0x000C ""} - {SourceLineMapNumbers 0x000D ""} - {SourceLineMapRanges 0x000E ""} - {SourceLineMapVOffs 0x000F ""} - {Units 0x0010 ""} - {UnitVmap 0x0011 ""} - {TypeNodes 0x0012 ""} - {UDTs 0x0013 ""} - {Members 0x0014 ""} - {EnumMembers 0x0015 ""} - {GlobalVariables 0x0016 ""} - {GlobalVmap 0x0017 ""} - {ThreadVariables 0x0018 ""} - {Procedures 0x0019 ""} - {Scopes 0x001A ""} - {ScopeVoffData 0x001B ""} - {ScopeVmap 0x001C ""} - {InlineSites 0x001D ""} - {Locals 0x001E ""} - {LocationBlocks 0x001F ""} - {LocationData 0x0020 ""} - {NameMaps 0x0021 ""} - {PRIMARY_COUNT 0x0022 ""} - {SECONDARY 0x80000000 ""} - {NameMapBuckets `RDI_DataSectionTag_SECONDARY|0x0001` ""} - {NameMapNodes `RDI_DataSectionTag_SECONDARY|0x0002` ""} + {NULL null RDI_U8 0x0000 - - ""} + {TopLevelInfo top_level_info RDI_TopLevelInfo 0x0001 - - ""} + {StringData string_data RDI_U8 0x0002 x - ""} + {StringTable string_table RDI_U32 0x0003 x U32 ""} + {IndexRuns index_runs RDI_U32 0x0004 x U32 ""} + {BinarySections binary_sections RDI_BinarySection 0x0005 - U32 ""} + {FilePathNodes file_path_nodes RDI_FilePathNode 0x0006 - U32 ""} + {SourceFiles source_files RDI_SourceFile 0x0007 - U32 ""} + {LineTables line_tables RDI_LineTable 0x0008 - U32 ""} + {LineInfoVOffs line_info_voffs RDI_U64 0x0009 - U32 ""} + {LineInfoLines line_info_lines RDI_Line 0x000A - U32 ""} + {LineInfoColumns line_info_columns RDI_Column 0x000B - U32 ""} + {SourceLineMaps source_line_maps RDI_SourceLineMap 0x000C - U32 ""} + {SourceLineMapNumbers source_line_map_numbers RDI_U32 0x000D - U32 ""} + {SourceLineMapRanges source_line_map_ranges RDI_U32 0x000E - U32 ""} + {SourceLineMapVOffs source_line_map_voffs RDI_U64 0x000F - U32 ""} + {Units units RDI_Unit 0x0010 - U32 ""} + {UnitVMap unit_vmap RDI_VMapEntry 0x0011 - - ""} + {TypeNodes type_nodes RDI_TypeNode 0x0012 - U32 ""} + {UDTs udts RDI_UDT 0x0013 - U32 ""} + {Members members RDI_Member 0x0014 - U32 ""} + {EnumMembers enum_members RDI_EnumMember 0x0015 - U32 ""} + {GlobalVariables global_variables RDI_GlobalVariable 0x0016 - U32 ""} + {GlobalVMap global_vmap RDI_VMapEntry 0x0017 - - ""} + {ThreadVariables thread_variables RDI_ThreadVariable 0x0018 - U32 ""} + {Procedures procedures RDI_Procedure 0x0019 - U32 ""} + {Scopes scopes RDI_Scope 0x001A - U32 ""} + {ScopeVOffData scope_voff_data RDI_U64 0x001B - U32 ""} + {ScopeVMap scope_vmap RDI_VMapEntry 0x001C - - ""} + {InlineSites inline_sites RDI_InlineSite 0x001D - U32 ""} + {Locals locals RDI_Local 0x001E - U32 ""} + {LocationBlocks location_blocks RDI_LocationBlock 0x001F - U32 ""} + {LocationData location_data RDI_U8 0x0020 - U32 ""} + {NameMaps name_maps RDI_NameMap 0x0021 - U32 ""} + {NameMapBuckets name_map_buckets RDI_NameMapBucket 0x0022 - U32 ""} + {NameMapNodes name_map_nodes RDI_NameMapNode 0x0023 - U32 ""} + {COUNT count RDI_U8 0x0024 - - ""} } @table(name value) -RDI_DataSectionEncodingTable: +RDI_SectionEncodingTable: { {Unpacked 0} {LZB 1} } @table(name type desc) -RDI_DataSectionMemberTable: +RDI_SectionMemberTable: { - {tag RDI_DataSectionTag ""} - {encoding RDI_DataSectionEncoding ""} + {encoding RDI_SectionEncoding ""} + {pad RDI_U32 ""} {off RDI_U64 ""} {encoded_size RDI_U64 ""} {unpacked_size RDI_U64 ""} } -@enum(RDI_U32) RDI_DataSectionTag: +@enum(RDI_U32) RDI_SectionKind: { - @expand(RDI_DataSectionTable a) `$(a.name .. =>20) = $(a.value)`, + @expand(RDI_SectionTable a) `$(a.name .. =>20) = $(a.value)`, } -@enum(RDI_U32) RDI_DataSectionEncoding: +@enum(RDI_U32) RDI_SectionEncoding: { - @expand(RDI_DataSectionEncodingTable a) `$(a.name .. =>10) = $(a.value)`, + @expand(RDI_SectionEncodingTable a) `$(a.name .. =>10) = $(a.value)`, } -@xlist RDI_DataSectionTag_XList: +@xlist RDI_SectionKind_XList: { - @expand(RDI_DataSectionTable a) `$(a.name)`; + @expand(RDI_SectionTable a) `$(a.name != COUNT -> a.name .. ', ' .. a.name_lower .. ', ' .. a.element_type)`; } -@xlist RDI_DataSectionEncoding_XList: +@xlist RDI_SectionEncoding_XList: { - @expand(RDI_DataSectionEncodingTable a) `$(a.name)`; + @expand(RDI_SectionEncodingTable a) `$(a.name)`; } -@xlist RDI_DataSection_XList: +@xlist RDI_Section_XList: { - @expand(RDI_DataSectionMemberTable a) `$(a.type), $(a.name)` + @expand(RDI_SectionMemberTable a) `$(a.type), $(a.name)` } -@struct RDI_DataSection: +@struct RDI_Section: { - @expand(RDI_DataSectionMemberTable a) `$(a.type) $(a.name)` + @expand(RDI_SectionMemberTable a) `$(a.type) $(a.name)` +} + +@gen(enums) +{ + `#if !RDI_DISABLE_TABLE_INDEX_TYPECHECKING`; + @expand(RDI_SectionTable a) `$(a.index_base_type != '-' -> "typedef struct RDI_" .. a.index_base_type .. "_" .. a.name .. =>50 .. " { RDI_" .. a.index_base_type .. " v; }".. " RDI_" .. a.index_base_type .. "_" .. a.name .. ";")`; + `#else`; + `typedef struct RDI_U32_Table { RDI_U32 v; } RDI_U32_Table;`; + `typedef struct RDI_U64_Table { RDI_U64 v; } RDI_U64_Table;`; + @expand(RDI_SectionTable a) `$(a.index_base_type != '-' -> "typedef RDI_" .. a.index_base_type .. "_Table RDI_" .. a.index_base_type .. "_" .. a.name .. ";")`; + `#endif`; + ``; +} + +@gen(catchall) +{ + @expand(RDI_SectionTable a) `$(a.name != COUNT -> "typedef " .. a.element_type .. " RDI_SectionElementType_" .. a.name .. ";")`; + ``; +} + +@data(RDI_U16) rdi_section_element_size_table: +{ + @expand(RDI_SectionTable a) `sizeof($(a.element_type))`; +} + +@data(RDI_U8) rdi_section_is_required_table: +{ + @expand(RDI_SectionTable a) `$(a.is_required == 'x' -> 1)$(a.is_required != 'x' -> 0)`; } //////////////////////////////// @@ -407,10 +441,10 @@ RDI_RegCodeX64Table: @table(name type desc) RDI_TopLevelInfoMemberTable: { - {arch RDI_Arch ""} - {exe_name_string_idx RDI_U32 ""} - {exe_hash RDI_U64 ""} - {voff_max RDI_U64 ""} + {arch RDI_Arch ""} + {exe_name_string_idx RDI_U32 ""} + {exe_hash RDI_U64 ""} + {voff_max RDI_U64 ""} } @xlist RDI_TopLevelInfo_XList: @@ -471,23 +505,23 @@ RDI_BinarySectionMemberTable: @table(name type desc) RDI_FilePathNodeMemberTable: { - {name_string_idx RDI_U32 ""} - {parent_path_node RDI_U32 ""} - {first_child RDI_U32 ""} - {next_sibling RDI_U32 ""} - {source_file_idx RDI_U32 ""} + {name_string_idx RDI_U32 ""} + {parent_path_node RDI_U32 ""} + {first_child RDI_U32 ""} + {next_sibling RDI_U32 ""} + {source_file_idx RDI_U32 ""} } @table(name type desc) RDI_SourceFileMemberTable: { - {file_path_node_idx RDI_U32 ""} - {normal_full_path_string_idx RDI_U32 ""} + {file_path_node_idx RDI_U32 ""} + {normal_full_path_string_idx RDI_U32 ""} // usage of line map to go from a line number to an array of voffs // (line_map_nums * line_number) -> (nil | index) // (line_map_data * index) -> (range) // (line_map_voff_data * range) -> (array(voff)) - {source_line_map_idx RDI_U32 ""} + {source_line_map_idx RDI_U32 ""} } @xlist RDI_FilePathNode_XList: @@ -516,14 +550,14 @@ RDI_SourceFileMemberTable: @table(name type desc) RDI_UnitMemberTable: { - {unit_name_string_idx RDI_U32 ""} - {compiler_name_string_idx RDI_U32 ""} - {source_file_path_node RDI_U32 ""} - {object_file_path_node RDI_U32 ""} - {archive_file_path_node RDI_U32 ""} - {build_path_node RDI_U32 ""} - {language RDI_Language ""} - {line_table_idx RDI_U32 ""} + {unit_name_string_idx RDI_U32 ""} + {compiler_name_string_idx RDI_U32 ""} + {source_file_path_node RDI_U32 ""} + {object_file_path_node RDI_U32 ""} + {archive_file_path_node RDI_U32 ""} + {build_path_node RDI_U32 ""} + {language RDI_Language ""} + {line_table_idx RDI_U32 ""} } @xlist RDI_Unit_XList: @@ -545,18 +579,18 @@ RDI_LineTableMemberTable: // usage of line info to go from voff to file & line number: // (line_info_voffs * voff) -> (nil + index) // (line_info_data * index) -> (RDI_Line = (file_idx * line_number)) - {voffs_base_idx RDI_U32 ""} // U64[lines_count+1] (sorted ranges) - {lines_base_idx RDI_U32 ""} // RDI_Line[lines_count] - {cols_base_idx RDI_U32 ""} // RDI_Column[cols_count] - {lines_count RDI_U32 ""} - {cols_count RDI_U32 ""} + {voffs_base_idx RDI_U32 ""} // U64[lines_count+1] (sorted ranges) + {lines_base_idx RDI_U32 ""} // RDI_Line[lines_count] + {cols_base_idx RDI_U32 ""} // RDI_Column[cols_count] + {lines_count RDI_U32 ""} + {cols_count RDI_U32 ""} } @table(name type desc) RDI_LineMemberTable: { - {file_idx RDI_U32 ""} - {line_num RDI_U32 ""} + {file_idx RDI_U32 ""} + {line_num RDI_U32 ""} } @table(name type desc) @@ -573,11 +607,11 @@ RDI_SourceLineMapMemberTable: // (line_map_nums * line_number) -> (nil | index) // (line_map_data * index) -> (range) // (line_map_voff_data * range) -> (array(voff)) - {line_count RDI_U32 ""} - {voff_count RDI_U32 ""} - {line_map_nums_base_idx RDI_U32 ""} // U32[line_count] (sorted - not closed ranges) - {line_map_range_base_idx RDI_U32 ""} // U32[line_count + 1] (pairs form ranges) - {line_map_voff_base_idx RDI_U32 ""} // U64[voff_count] (idx by line_map_range_data) + {line_count RDI_U32 ""} + {voff_count RDI_U32 ""} + {line_map_nums_base_idx RDI_U32 ""} // U32[line_count] (sorted - not closed ranges) + {line_map_range_base_idx RDI_U32 ""} // U32[line_count + 1] (pairs form ranges) + {line_map_voff_base_idx RDI_U32 ""} // U64[voff_count] (idx by line_map_range_data) } @xlist RDI_LineTable_XList: @@ -732,13 +766,13 @@ RDI_UDTFlagTable: @table(name type desc) RDI_UDTMemberTable: { - {self_type_idx RDI_U32 ""} - {flags RDI_UDTFlags ""} - {member_first RDI_U32 ""} - {member_count RDI_U32 ""} - {file_idx RDI_U32 ""} - {line RDI_U32 ""} - {col RDI_U32 ""} + {self_type_idx RDI_U32 ""} + {flags RDI_UDTFlags ""} + {member_first RDI_U32 ""} + {member_count RDI_U32 ""} + {file_idx RDI_U32 ""} + {line RDI_U32 ""} + {col RDI_U32 ""} } @table(name value) @@ -759,19 +793,19 @@ RDI_MemberKindTable: @table(name type desc) RDI_MemberMemberTable: { - {kind RDI_MemberKind ""} - {pad RDI_U16 ""} - {name_string_idx RDI_U32 ""} - {type_idx RDI_U32 ""} - {off RDI_U32 ""} + {kind RDI_MemberKind ""} + {pad RDI_U16 ""} + {name_string_idx RDI_U32 ""} + {type_idx RDI_U32 ""} + {off RDI_U32 ""} } @table(name type desc) RDI_EnumMemberTable: { - {name_string_idx RDI_U32 ""} - {pad RDI_U32 ""} - {val RDI_U64 ""} + {name_string_idx RDI_U32 ""} + {pad RDI_U32 ""} + {val RDI_U64 ""} } @enum(RDI_U16) RDI_TypeKind: @@ -818,13 +852,15 @@ RDI_EnumMemberTable: { RDI_U32 direct_type_idx; RDI_U32 count; - union{ + union + { // when kind is 'Function' or 'Method' RDI_U32 param_idx_run_first; // when kind is 'MemberPtr' RDI_U32 owner_type_idx; }; - } constructed; + } + constructed; // kind is 'user defined' struct @@ -832,7 +868,8 @@ RDI_EnumMemberTable: RDI_U32 name_string_idx; RDI_U32 direct_type_idx; RDI_U32 udt_idx; - } user_defined; + } + user_defined; // (kind = Bitfield) struct @@ -840,7 +877,8 @@ RDI_EnumMemberTable: RDI_U32 direct_type_idx; RDI_U32 off; RDI_U32 size; - } bitfield; + } + bitfield; } ``` } @@ -930,44 +968,44 @@ RDI_LocationKindTable: @table(name type desc) RDI_GlobalVariableMemberTable: { - {name_string_idx RDI_U32 ""} - {link_flags RDI_LinkFlags ""} - {voff RDI_U64 ""} - {type_idx RDI_U32 ""} - {container_idx RDI_U32 ""} + {name_string_idx RDI_U32 ""} + {link_flags RDI_LinkFlags ""} + {voff RDI_U64 ""} + {type_idx RDI_U32 ""} + {container_idx RDI_U32 ""} } @table(name type desc) RDI_ThreadVariableMemberTable: { - {name_string_idx RDI_U32 ""} - {link_flags RDI_LinkFlags ""} - {tls_off RDI_U32 ""} - {type_idx RDI_U32 ""} - {container_idx RDI_U32 ""} + {name_string_idx RDI_U32 ""} + {link_flags RDI_LinkFlags ""} + {tls_off RDI_U32 ""} + {type_idx RDI_U32 ""} + {container_idx RDI_U32 ""} } @table(name type desc) RDI_ProcedureMemberTable: { - {name_string_idx RDI_U32 ""} - {link_name_string_idx RDI_U32 ""} - {link_flags RDI_LinkFlags ""} - {type_idx RDI_U32 ""} - {root_scope_idx RDI_U32 ""} - {container_idx RDI_U32 ""} + {name_string_idx RDI_U32 ""} + {link_name_string_idx RDI_U32 ""} + {link_flags RDI_LinkFlags ""} + {type_idx RDI_U32 ""} + {root_scope_idx RDI_U32 ""} + {container_idx RDI_U32 ""} } @table(name type desc) RDI_ScopeMemberTable: { - {proc_idx RDI_U32 ""} - {parent_scope_idx RDI_U32 ""} - {first_child_scope_idx RDI_U32 ""} - {next_sibling_scope_idx RDI_U32 ""} - {voff_range_first RDI_U32 ""} - {voff_range_opl RDI_U32 ""} - {local_first RDI_U32 ""} + {proc_idx RDI_U32 ""} + {parent_scope_idx RDI_U32 ""} + {first_child_scope_idx RDI_U32 ""} + {next_sibling_scope_idx RDI_U32 ""} + {voff_range_first RDI_U32 ""} + {voff_range_opl RDI_U32 ""} + {local_first RDI_U32 ""} {local_count RDI_U32 ""} {static_local_idx_run_first RDI_U32 ""} {static_local_count RDI_U32 ""} @@ -976,32 +1014,32 @@ RDI_ScopeMemberTable: @table(name type desc) RDI_InlineSiteMemberTable: { - {name_string_idx RDI_U32 ""} - {call_src_file_idx RDI_U32 ""} - {call_line_num RDI_U32 ""} - {call_col_num RDI_U32 ""} - {type_idx RDI_U32 ""} - {owner_type_idx RDI_U32 ""} - {line_table_idx RDI_U32 ""} + {name_string_idx RDI_U32 ""} + {call_src_file_idx RDI_U32 ""} + {call_line_num RDI_U32 ""} + {call_col_num RDI_U32 ""} + {type_idx RDI_U32 ""} + {owner_type_idx RDI_U32 ""} + {line_table_idx RDI_U32 ""} } @table(name type desc) RDI_LocalMemberTable: { - {kind RDI_LocalKind ""} - {name_string_idx RDI_U32 ""} - {type_idx RDI_U32 ""} - {pad RDI_U32 ""} - {location_first RDI_U32 ""} - {location_opl RDI_U32 ""} + {kind RDI_LocalKind ""} + {name_string_idx RDI_U32 ""} + {type_idx RDI_U32 ""} + {pad RDI_U32 ""} + {location_first RDI_U32 ""} + {location_opl RDI_U32 ""} } @table(name type desc) RDI_LocationBlockMemberTable: { - {scope_off_first RDI_U32} - {scope_off_opl RDI_U32} - {location_data_off RDI_U32} + {scope_off_first RDI_U32 } + {scope_off_opl RDI_U32 } + {location_data_off RDI_U32 } } @table(name type desc) @@ -1314,9 +1352,11 @@ RDI_NameMapKindTable: @table(name type desc) RDI_NameMapMemberTable: { - {kind RDI_NameMapKind ""} - {bucket_data_idx RDI_U32 ""} - {node_data_idx RDI_U32 ""} + {kind RDI_NameMapKind ""} + {bucket_base_idx RDI_U32 ""} + {node_base_idx RDI_U32 ""} + {bucket_count RDI_U32 ""} + {node_count RDI_U32 ""} } @table(name type desc) @@ -1329,11 +1369,11 @@ RDI_NameMapBucketMemberTable: @table(name type desc) RDI_NameMapNodeMemberTable: { - {string_idx RDI_U32 ""} - {match_count RDI_U32 ""} + {string_idx RDI_U32 ""} + {match_count RDI_U32 ""} // NOTE: if (match_count == 1) then this is the index of the matching item // if (match_count > 1) then this is the first for an index run of all the matches - {match_idx_or_idx_run_first RDI_U32 ""} + {match_idx_or_idx_run_first RDI_U32 ""} } @enum(RDI_U32) RDI_NameMapKind: diff --git a/src/rdi_format/rdi_format_local.c b/src/rdi_format/rdi_format_local.c index 6fae2eb3..661fb0b1 100644 --- a/src/rdi_format/rdi_format_local.c +++ b/src/rdi_format/rdi_format_local.c @@ -15,16 +15,16 @@ rdi_decompress_parsed(U8 *decompressed_data, U64 decompressed_size, RDI_Parsed * } // rjf: copy & adjust sections for decompressed version - if(og_rdi->dsec_count != 0) + if(og_rdi->sections_count != 0) { - RDI_DataSection *dsec_base = (RDI_DataSection *)(decompressed_data + dst_header->data_section_off); - MemoryCopy(dsec_base, (U8 *)og_rdi->raw_data + src_header->data_section_off, sizeof(RDI_DataSection) * og_rdi->dsec_count); - U64 off = dst_header->data_section_off + sizeof(RDI_DataSection) * og_rdi->dsec_count; + RDI_Section *dsec_base = (RDI_Section *)(decompressed_data + dst_header->data_section_off); + MemoryCopy(dsec_base, (U8 *)og_rdi->raw_data + src_header->data_section_off, sizeof(RDI_Section) * og_rdi->sections_count); + U64 off = dst_header->data_section_off + sizeof(RDI_Section) * og_rdi->sections_count; off += 7; off -= off%8; - for(U64 idx = 0; idx < og_rdi->dsec_count; idx += 1) + for(U64 idx = 0; idx < og_rdi->sections_count; idx += 1) { - dsec_base[idx].encoding = RDI_DataSectionEncoding_Unpacked; + dsec_base[idx].encoding = RDI_SectionEncoding_Unpacked; dsec_base[idx].off = off; dsec_base[idx].encoded_size = dsec_base[idx].unpacked_size; off += dsec_base[idx].unpacked_size; @@ -34,13 +34,13 @@ rdi_decompress_parsed(U8 *decompressed_data, U64 decompressed_size, RDI_Parsed * } // rjf: decompress sections into new decompressed file buffer - if(og_rdi->dsec_count != 0) + if(og_rdi->sections_count != 0) { - RDI_DataSection *src_first = og_rdi->dsecs; - RDI_DataSection *dst_first = (RDI_DataSection *)(decompressed_data + dst_header->data_section_off); - RDI_DataSection *src_opl = src_first + og_rdi->dsec_count; - RDI_DataSection *dst_opl = dst_first + og_rdi->dsec_count; - for(RDI_DataSection *src = src_first, *dst = dst_first; + RDI_Section *src_first = og_rdi->sections; + RDI_Section *dst_first = (RDI_Section *)(decompressed_data + dst_header->data_section_off); + RDI_Section *src_opl = src_first + og_rdi->sections_count; + RDI_Section *dst_opl = dst_first + og_rdi->sections_count; + for(RDI_Section *src = src_first, *dst = dst_first; src < src_opl && dst < dst_opl; src += 1, dst += 1) { diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index 9ed9b2b4..efa8a18e 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -4302,7 +4302,7 @@ p2r_compress(Arena *arena, P2R_Bake2Serialize *in) // rjf: unpack uncompressed section info void *data = src->data; - RDI_DataSectionEncoding encoding = src->encoding; + RDI_SectionEncoding encoding = src->encoding; RDI_U64 encoded_size = src->encoded_size; RDI_U64 unpacked_size = src->unpacked_size; @@ -4316,7 +4316,7 @@ p2r_compress(Arena *arena, P2R_Bake2Serialize *in) void *raw_data = data; data = push_array_no_zero(arena, U8, unpacked_size); encoded_size = rr_lzb_simple_encode_veryfast(&ctx, raw_data, unpacked_size, data); - encoding = RDI_DataSectionEncoding_LZB; + encoding = RDI_SectionEncoding_LZB; } // rjf: fill diff --git a/src/type_graph/type_graph.c b/src/type_graph/type_graph.c index 4a9af695..fbf96b33 100644 --- a/src/type_graph/type_graph.c +++ b/src/type_graph/type_graph.c @@ -336,9 +336,9 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke case TG_KeyKind_Ext: { U64 type_node_idx = key.u64[0]; - if(0 <= type_node_idx && type_node_idx < rdi->type_nodes_count) + RDI_TypeNode *rdi_type = rdi_element_from_name_idx(rdi, TypeNodes, type_node_idx); + if(rdi_type->kind != RDI_TypeKind_NULL) { - RDI_TypeNode *rdi_type = &rdi->type_nodes[type_node_idx]; TG_Kind kind = tg_kind_from_rdi_type_kind(rdi_type->kind); //- rjf: record types => unpack name * members & produce @@ -349,7 +349,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size); // rjf: unpack UDT info - RDI_UDT *udt = rdi_element_from_idx(rdi, udts, rdi_type->user_defined.udt_idx); + RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, rdi_type->user_defined.udt_idx); // rjf: unpack members TG_Member *members = 0; @@ -357,19 +357,16 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke { members_count = udt->member_count; members = push_array(arena, TG_Member, members_count); - if(members_count != 0 && 0 <= udt->member_first && udt->member_first+udt->member_count <= rdi->members_count) + if(members_count != 0) { for(U32 member_idx = udt->member_first; member_idx < udt->member_first+udt->member_count; member_idx += 1) { - RDI_Member *src = &rdi->members[member_idx]; + RDI_Member *src = rdi_element_from_name_idx(rdi, Members, member_idx); TG_Kind member_type_kind = TG_Kind_Null; - if(src->type_idx < rdi->type_nodes_count) - { - RDI_TypeNode *member_type = &rdi->type_nodes[src->type_idx]; - member_type_kind = tg_kind_from_rdi_type_kind(member_type->kind); - } + RDI_TypeNode *member_type = rdi_element_from_name_idx(rdi, TypeNodes, src->type_idx); + member_type_kind = tg_kind_from_rdi_type_kind(member_type->kind); TG_Member *dst = &members[member_idx-udt->member_first]; dst->kind = tg_member_kind_from_rdi_member_kind(src->kind); dst->type_key = tg_key_ext(member_type_kind, (U64)src->type_idx); @@ -399,7 +396,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke TG_Key direct_type_key = zero_struct; if(rdi_type->user_defined.direct_type_idx < type_node_idx) { - RDI_TypeNode *direct_type_node = &rdi->type_nodes[rdi_type->user_defined.direct_type_idx]; + RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->user_defined.direct_type_idx); TG_Kind direct_type_kind = tg_kind_from_rdi_type_kind(direct_type_node->kind); direct_type_key = tg_key_ext(direct_type_kind, (U64)rdi_type->user_defined.direct_type_idx); } @@ -409,23 +406,17 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke U32 enum_vals_count = 0; { U32 udt_idx = rdi_type->user_defined.udt_idx; - if(0 <= udt_idx && udt_idx < rdi->udts_count) + RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, udt_idx); + enum_vals_count = udt->member_count; + enum_vals = push_array(arena, TG_EnumVal, enum_vals_count); + for(U32 member_idx = udt->member_first; + member_idx < udt->member_first+udt->member_count; + member_idx += 1) { - RDI_UDT *udt = &rdi->udts[udt_idx]; - enum_vals_count = udt->member_count; - enum_vals = push_array(arena, TG_EnumVal, enum_vals_count); - if(0 <= udt->member_first && udt->member_first+udt->member_count < rdi->enum_members_count) - { - for(U32 member_idx = udt->member_first; - member_idx < udt->member_first+udt->member_count; - member_idx += 1) - { - RDI_EnumMember *src = &rdi->enum_members[member_idx]; - TG_EnumVal *dst = &enum_vals[member_idx-udt->member_first]; - dst->name.str = rdi_string_from_idx(rdi, src->name_string_idx, &dst->name.size); - dst->val = src->val; - } - } + RDI_EnumMember *src = rdi_element_from_name_idx(rdi, EnumMembers, member_idx); + TG_EnumVal *dst = &enum_vals[member_idx-udt->member_first]; + dst->name.str = rdi_string_from_idx(rdi, src->name_string_idx, &dst->name.size); + dst->val = src->val; } } @@ -448,7 +439,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke U64 direct_type_byte_size = 0; if(rdi_type->constructed.direct_type_idx < type_node_idx) { - RDI_TypeNode *direct_type_node = &rdi->type_nodes[rdi_type->constructed.direct_type_idx]; + RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->constructed.direct_type_idx); TG_Kind direct_type_kind = tg_kind_from_rdi_type_kind(direct_type_node->kind); direct_type_key = tg_key_ext(direct_type_kind, (U64)rdi_type->constructed.direct_type_idx); direct_type_is_good = 1; @@ -512,7 +503,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke U32 param_type_idx = idx_run[idx]; if(param_type_idx < type_node_idx) { - RDI_TypeNode *param_type_node = &rdi->type_nodes[param_type_idx]; + RDI_TypeNode *param_type_node = rdi_element_from_name_idx(rdi, TypeNodes, param_type_idx); TG_Kind param_kind = tg_kind_from_rdi_type_kind(param_type_node->kind); type->param_type_keys[idx] = tg_key_ext(param_kind, (U64)param_type_idx); } @@ -545,7 +536,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke U32 param_type_idx = idx_run[idx]; if(param_type_idx < type_node_idx) { - RDI_TypeNode *param_type_node = &rdi->type_nodes[param_type_idx]; + RDI_TypeNode *param_type_node = rdi_element_from_name_idx(rdi, TypeNodes, param_type_idx); TG_Kind param_kind = tg_kind_from_rdi_type_kind(param_type_node->kind); type->param_type_keys[idx] = tg_key_ext(param_kind, (U64)param_type_idx); } @@ -568,7 +559,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke TG_Key owner_type_key = zero_struct; if(rdi_type->constructed.owner_type_idx < type_node_idx) { - RDI_TypeNode *owner_type_node = &rdi->type_nodes[rdi_type->constructed.owner_type_idx]; + RDI_TypeNode *owner_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->constructed.owner_type_idx); TG_Kind owner_type_kind = tg_kind_from_rdi_type_kind(owner_type_node->kind); owner_type_key = tg_key_ext(owner_type_kind, (U64)rdi_type->constructed.owner_type_idx); } @@ -593,7 +584,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke U64 direct_type_byte_size = 0; if(rdi_type->user_defined.direct_type_idx < type_node_idx) { - RDI_TypeNode *direct_type_node = &rdi->type_nodes[rdi_type->user_defined.direct_type_idx]; + RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->user_defined.direct_type_idx); TG_Kind direct_type_kind = tg_kind_from_rdi_type_kind(direct_type_node->kind); direct_type_key = tg_key_ext(direct_type_kind, (U64)rdi_type->user_defined.direct_type_idx); direct_type_byte_size = direct_type_node->byte_size; @@ -615,7 +606,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke U64 direct_type_byte_size = 0; if(rdi_type->bitfield.direct_type_idx < type_node_idx) { - RDI_TypeNode *direct_type_node = &rdi->type_nodes[rdi_type->bitfield.direct_type_idx]; + RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->bitfield.direct_type_idx); TG_Kind direct_type_kind = tg_kind_from_rdi_type_kind(direct_type_node->kind); direct_type_key = tg_key_ext(direct_type_kind, (U64)rdi_type->bitfield.direct_type_idx); direct_type_byte_size = direct_type_node->byte_size; From 6e84c078a804b6ff867de4261b722fa093dd7d78 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 6 Jun 2024 15:37:27 -0700 Subject: [PATCH 11/44] sketch out artifact types for new rdi baking pass --- src/lib_rdi_format/rdi_format.h | 71 +++++++------- src/lib_rdi_make/rdi_make.h | 164 ++++++++++++++++++++++++++++++++ src/rdi_format/rdi_format.mdesk | 2 +- 3 files changed, 200 insertions(+), 37 deletions(-) diff --git a/src/lib_rdi_format/rdi_format.h b/src/lib_rdi_format/rdi_format.h index eb8ea99e..a43d2811 100644 --- a/src/lib_rdi_format/rdi_format.h +++ b/src/lib_rdi_format/rdi_format.h @@ -1290,42 +1290,41 @@ RDI_U32 match_count; RDI_U32 match_idx_or_idx_run_first; }; -typedef RDI_U8 RDI_SectionElementType_NULL; -typedef RDI_TopLevelInfo RDI_SectionElementType_TopLevelInfo; -typedef RDI_U8 RDI_SectionElementType_StringData; -typedef RDI_U32 RDI_SectionElementType_StringTable; -typedef RDI_U32 RDI_SectionElementType_IndexRuns; -typedef RDI_BinarySection RDI_SectionElementType_BinarySections; -typedef RDI_FilePathNode RDI_SectionElementType_FilePathNodes; -typedef RDI_SourceFile RDI_SectionElementType_SourceFiles; -typedef RDI_LineTable RDI_SectionElementType_LineTables; -typedef RDI_U64 RDI_SectionElementType_LineInfoVOffs; -typedef RDI_Line RDI_SectionElementType_LineInfoLines; -typedef RDI_Column RDI_SectionElementType_LineInfoColumns; -typedef RDI_SourceLineMap RDI_SectionElementType_SourceLineMaps; -typedef RDI_U32 RDI_SectionElementType_SourceLineMapNumbers; -typedef RDI_U32 RDI_SectionElementType_SourceLineMapRanges; -typedef RDI_U64 RDI_SectionElementType_SourceLineMapVOffs; -typedef RDI_Unit RDI_SectionElementType_Units; -typedef RDI_VMapEntry RDI_SectionElementType_UnitVMap; -typedef RDI_TypeNode RDI_SectionElementType_TypeNodes; -typedef RDI_UDT RDI_SectionElementType_UDTs; -typedef RDI_Member RDI_SectionElementType_Members; -typedef RDI_EnumMember RDI_SectionElementType_EnumMembers; -typedef RDI_GlobalVariable RDI_SectionElementType_GlobalVariables; -typedef RDI_VMapEntry RDI_SectionElementType_GlobalVMap; -typedef RDI_ThreadVariable RDI_SectionElementType_ThreadVariables; -typedef RDI_Procedure RDI_SectionElementType_Procedures; -typedef RDI_Scope RDI_SectionElementType_Scopes; -typedef RDI_U64 RDI_SectionElementType_ScopeVOffData; -typedef RDI_VMapEntry RDI_SectionElementType_ScopeVMap; -typedef RDI_InlineSite RDI_SectionElementType_InlineSites; -typedef RDI_Local RDI_SectionElementType_Locals; -typedef RDI_LocationBlock RDI_SectionElementType_LocationBlocks; -typedef RDI_U8 RDI_SectionElementType_LocationData; -typedef RDI_NameMap RDI_SectionElementType_NameMaps; -typedef RDI_NameMapBucket RDI_SectionElementType_NameMapBuckets; -typedef RDI_NameMapNode RDI_SectionElementType_NameMapNodes; +typedef RDI_TopLevelInfo RDI_SectionElementType_TopLevelInfo; +typedef RDI_U8 RDI_SectionElementType_StringData; +typedef RDI_U32 RDI_SectionElementType_StringTable; +typedef RDI_U32 RDI_SectionElementType_IndexRuns; +typedef RDI_BinarySection RDI_SectionElementType_BinarySections; +typedef RDI_FilePathNode RDI_SectionElementType_FilePathNodes; +typedef RDI_SourceFile RDI_SectionElementType_SourceFiles; +typedef RDI_LineTable RDI_SectionElementType_LineTables; +typedef RDI_U64 RDI_SectionElementType_LineInfoVOffs; +typedef RDI_Line RDI_SectionElementType_LineInfoLines; +typedef RDI_Column RDI_SectionElementType_LineInfoColumns; +typedef RDI_SourceLineMap RDI_SectionElementType_SourceLineMaps; +typedef RDI_U32 RDI_SectionElementType_SourceLineMapNumbers; +typedef RDI_U32 RDI_SectionElementType_SourceLineMapRanges; +typedef RDI_U64 RDI_SectionElementType_SourceLineMapVOffs; +typedef RDI_Unit RDI_SectionElementType_Units; +typedef RDI_VMapEntry RDI_SectionElementType_UnitVMap; +typedef RDI_TypeNode RDI_SectionElementType_TypeNodes; +typedef RDI_UDT RDI_SectionElementType_UDTs; +typedef RDI_Member RDI_SectionElementType_Members; +typedef RDI_EnumMember RDI_SectionElementType_EnumMembers; +typedef RDI_GlobalVariable RDI_SectionElementType_GlobalVariables; +typedef RDI_VMapEntry RDI_SectionElementType_GlobalVMap; +typedef RDI_ThreadVariable RDI_SectionElementType_ThreadVariables; +typedef RDI_Procedure RDI_SectionElementType_Procedures; +typedef RDI_Scope RDI_SectionElementType_Scopes; +typedef RDI_U64 RDI_SectionElementType_ScopeVOffData; +typedef RDI_VMapEntry RDI_SectionElementType_ScopeVMap; +typedef RDI_InlineSite RDI_SectionElementType_InlineSites; +typedef RDI_Local RDI_SectionElementType_Locals; +typedef RDI_LocationBlock RDI_SectionElementType_LocationBlocks; +typedef RDI_U8 RDI_SectionElementType_LocationData; +typedef RDI_NameMap RDI_SectionElementType_NameMaps; +typedef RDI_NameMapBucket RDI_SectionElementType_NameMapBuckets; +typedef RDI_NameMapNode RDI_SectionElementType_NameMapNodes; RDI_PROC RDI_U64 rdi_hash(RDI_U8 *ptr, RDI_U64 size); RDI_PROC RDI_U32 rdi_size_from_basic_type_kind(RDI_TypeKind kind); diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index 0e7dbe8d..1e3b17f2 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -1058,6 +1058,167 @@ struct RDIM_VMapMarker RDI_U32 begin_range; }; +//- rjf: baking results + +typedef struct RDIM_TopLevelInfoBakeResult RDIM_TopLevelInfoBakeResult; +struct RDIM_TopLevelInfoBakeResult +{ + RDI_TopLevelInfo *top_level_info; +}; + +typedef struct RDIM_BinarySectionBakeResult RDIM_BinarySectionBakeResult; +struct RDIM_BinarySectionBakeResult +{ + RDI_BinarySection *binary_sections; + RDI_U64 binary_sections_count; +}; + +typedef struct RDIM_UnitBakeResult RDIM_UnitBakeResult; +struct RDIM_UnitBakeResult +{ + RDI_Unit *units; + RDI_U64 units_count; +}; + +typedef struct RDIM_UnitVMapBakeResult RDIM_UnitVMapBakeResult; +struct RDIM_UnitVMapBakeResult +{ + RDIM_BakeVMap vmap; +}; + +typedef struct RDIM_SrcFileBakeResult RDIM_SrcFileBakeResult; +struct RDIM_SrcFileBakeResult +{ + RDI_SourceFile *source_files; + RDI_U64 source_files_count; + RDI_SourceLineMap *source_line_maps; + RDI_U64 source_line_maps_count; + RDI_U32 *source_line_map_nums; + RDI_U32 *source_line_map_rngs; + RDI_U64 *source_line_map_voffs; + RDI_U64 source_line_map_nums_count; + RDI_U64 source_line_map_rngs_count; + RDI_U64 source_line_map_voffs_count; +}; + +typedef struct RDIM_LineTableBakeResult RDIM_LineTableBakeResult; +struct RDIM_LineTableBakeResult +{ + RDI_LineTable *line_tables; + RDI_U64 line_tables_count; + RDI_U64 *line_table_voffs; + RDI_U64 line_table_voffs_count; + RDI_Line *line_table_lines; + RDI_U64 line_table_lines_count; + RDI_Column *line_table_columns; + RDI_U64 line_table_columns_count; +}; + +typedef struct RDIM_TypeNodeBakeResult RDIM_TypeNodeBakeResult; +struct RDIM_TypeNodeBakeResult +{ + RDI_TypeNode *type_nodes; + RDI_U64 type_nodes_count; +}; + +typedef struct RDIM_UDTBakeResult RDIM_UDTBakeResult; +struct RDIM_UDTBakeResult +{ + RDI_UDT *udts; + RDI_U64 udts_count; + RDI_Member *members; + RDI_U64 members_count; + RDI_EnumMember *enum_members; + RDI_U64 enum_members_count; +}; + +typedef struct RDIM_GlobalVariableBakeResult RDIM_GlobalVariableBakeResult; +struct RDIM_GlobalVariableBakeResult +{ + RDI_GlobalVariable *global_variables; + RDI_U64 global_variables_count; +}; + +typedef struct RDIM_GlobalVMapBakeResult RDIM_GlobalVMapBakeResult; +struct RDIM_GlobalVMapBakeResult +{ + RDIM_BakeVMap vmap; +}; + +typedef struct RDIM_ThreadVariableBakeResult RDIM_ThreadVariableBakeResult; +struct RDIM_ThreadVariableBakeResult +{ + RDI_ThreadVariable *thread_variables; + RDI_U64 thread_variables_count; +}; + +typedef struct RDIM_ProcedureBakeResult RDIM_ProcedureBakeResult; +struct RDIM_ProcedureBakeResult +{ + RDI_Procedure *procedures; + RDI_U64 procedures_count; +}; + +typedef struct RDIM_ScopeBakeResult RDIM_ScopeBakeResult; +struct RDIM_ScopeBakeResult +{ + RDI_Scope *scopes; + RDI_U64 scopes_count; + RDI_U64 *scope_voffs; + RDI_U64 scope_voffs_count; + RDI_Local *locals; + RDI_U64 locals_count; + RDI_LocationBlock *location_blocks; + RDI_U64 location_blocks_count; + RDI_U8 *location_data; + RDI_U64 location_data_size; +}; + +typedef struct RDIM_ScopeVMapBakeResult RDIM_ScopeVMapBakeResult; +struct RDIM_ScopeVMapBakeResult +{ + RDIM_BakeVMap vmap; +}; + +typedef struct RDIM_TopLevelNameMapBakeResult RDIM_TopLevelNameMapBakeResult; +struct RDIM_TopLevelNameMapBakeResult +{ + RDI_NameMap *name_maps; + RDI_U64 name_maps_count; +}; + +typedef struct RDIM_NameMapBakeResult RDIM_NameMapBakeResult; +struct RDIM_NameMapBakeResult +{ + RDI_NameMapBucket *buckets; + RDI_U64 buckets_count; + RDI_NameMapNode *nodes; + RDI_U64 nodes_count; +}; + +typedef struct RDIM_FilePathBakeResult RDIM_FilePathBakeResult; +struct RDIM_FilePathBakeResult +{ + RDI_FilePathNode *nodes; + RDI_U64 nodes_count; +}; + +typedef struct RDIM_StringBakeResult RDIM_StringBakeResult; +struct RDIM_StringBakeResult +{ + RDI_U32 *string_offs; + RDI_U64 string_offs_count; + RDI_U8 *string_data; + RDI_U64 string_data_size; +}; + +typedef struct RDIM_IndexRunBakeResult RDIM_IndexRunBakeResult; +struct RDIM_IndexRunBakeResult +{ + RDI_U32 *idx_runs; + RDI_U64 idx_count; +}; + //////////////////////////////// //~ rjf: Basic Helpers @@ -1266,6 +1427,9 @@ RDI_PROC RDIM_BakeIdxRunMap *rdim_bake_idx_run_map_from_params(RDIM_Arena *arena //- rjf: bake path tree building RDI_PROC RDIM_BakePathTree *rdim_bake_path_tree_from_params(RDIM_Arena *arena, RDIM_BakeParams *params); +//////////////////////////////// +//~ rjf: [Baking] Build Artifacts -> Baked Versions + //////////////////////////////// //~ rjf: [Baking] Build Artifacts -> Data Section Lists diff --git a/src/rdi_format/rdi_format.mdesk b/src/rdi_format/rdi_format.mdesk index 1177f352..e3e902b6 100644 --- a/src/rdi_format/rdi_format.mdesk +++ b/src/rdi_format/rdi_format.mdesk @@ -220,7 +220,7 @@ RDI_SectionMemberTable: @gen(catchall) { - @expand(RDI_SectionTable a) `$(a.name != COUNT -> "typedef " .. a.element_type .. " RDI_SectionElementType_" .. a.name .. ";")`; + @expand(RDI_SectionTable a) `$(a.name != COUNT && a.name != NULL -> "typedef " .. a.element_type .. =>40 .. " RDI_SectionElementType_" .. a.name .. ";")`; ``; } From 8d99f4859b3fd788879e097ed48fa764618de712 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 6 Jun 2024 16:06:50 -0700 Subject: [PATCH 12/44] sketch out new rdi make baking codepaths --- src/lib_rdi_make/rdi_make.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index 1e3b17f2..4b2466c0 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -1430,6 +1430,35 @@ RDI_PROC RDIM_BakePathTree *rdim_bake_path_tree_from_params(RDIM_Arena *arena, R //////////////////////////////// //~ rjf: [Baking] Build Artifacts -> Baked Versions +// TODO(rjf): +// +// separate category of partial/joinable/slice-based baking functions +// (distinct from necessarily serial, top-level, non-trivially-joinable +// paths) can go here - this includes things like the "parallel-for" +// style filling of various tables, but it does not include things like +// vmap building. + +//- rjf: independent (top-level, global) baking functions +RDI_PROC RDIM_TopLevelInfoBakeResult rdim_bake_top_level_info(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_TopLevelInfo *src); +RDI_PROC RDIM_BinarySectionBakeResult rdim_bake_binary_sections(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BinarySectionList *src); +RDI_PROC RDIM_UnitBakeResult rdim_bake_units(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_UnitChunkList *src); +RDI_PROC RDIM_UnitVMapBakeResult rdim_bake_unit_vmap(RDIM_Arena *arena, RDIM_UnitChunkList *units); +RDI_PROC RDIM_SrcFileBakeResult rdim_bake_src_files(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_SrcFileChunkList *src); +RDI_PROC RDIM_LineTableBakeResult rdim_bake_line_tables(RDIM_Arena *arena, RDIM_LineTableChunkList *src); +RDI_PROC RDIM_TypeNodeBakeResult rdim_bake_types(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_TypeChunkList *src); +RDI_PROC RDIM_UDTBakeResult rdim_bake_udts(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_UDTChunkList *src); +RDI_PROC RDIM_GlobalVariableBakeResult rdim_bake_global_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src); +RDI_PROC RDIM_GlobalVMapBakeResult rdim_bake_global_vmap(RDIM_Arena *arena, RDIM_SymbolChunkList *src); +RDI_PROC RDIM_ThreadVariableBakeResult rdim_bake_thread_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src); +RDI_PROC RDIM_ProcedureBakeResult rdim_bake_procedures(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src); +RDI_PROC RDIM_ScopeBakeResult rdim_bake_scopes(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_ScopeChunkList *src); +RDI_PROC RDIM_ScopeVMapBakeResult rdim_bake_scope_vmap(RDIM_Arena *arena, RDIM_ScopeChunkList *src); +RDI_PROC RDIM_TopLevelNameMapBakeResult rdim_bake_name_maps_top_level(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT]); +RDI_PROC RDIM_NameMapBakeResult rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *src, RDI_U64 base_node_idx); +RDI_PROC RDIM_FilePathBakeResult rdim_bake_file_paths(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree); +RDI_PROC RDIM_StringBakeResult rdim_bake_strings(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings); +RDI_PROC RDIM_IndexRunBakeResult rdim_bake_index_runs(RDIM_Arena *arena, RDIM_BakeIdxRunMap *idx_runs); + //////////////////////////////// //~ rjf: [Baking] Build Artifacts -> Data Section Lists From 11978904e15832715d29fae6cb21b5c685c4525a Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 6 Jun 2024 16:47:33 -0700 Subject: [PATCH 13/44] rdi make: first pass at new baking paths --- src/lib_rdi_format/rdi_format.h | 2 - src/lib_rdi_make/rdi_make.c | 1238 ++++++++++++++++++++++++++++++- src/lib_rdi_make/rdi_make.h | 10 +- src/raddbg/raddbg.h | 2 + src/rdi_format/rdi_format.mdesk | 1 - 5 files changed, 1240 insertions(+), 13 deletions(-) diff --git a/src/lib_rdi_format/rdi_format.h b/src/lib_rdi_format/rdi_format.h index a43d2811..dfd73d6b 100644 --- a/src/lib_rdi_format/rdi_format.h +++ b/src/lib_rdi_format/rdi_format.h @@ -888,7 +888,6 @@ X(NormalSourcePaths)\ X(COUNT)\ #define RDI_NameMap_XList \ -X(RDI_NameMapKind, kind)\ X(RDI_U32, bucket_base_idx)\ X(RDI_U32, node_base_idx)\ X(RDI_U32, bucket_count)\ @@ -1268,7 +1267,6 @@ RDI_RegCode reg_code; typedef struct RDI_NameMap RDI_NameMap; struct RDI_NameMap { -RDI_NameMapKind kind; RDI_U32 bucket_base_idx; RDI_U32 node_base_idx; RDI_U32 bucket_count; diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index 0cc4b342..371b0707 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -90,7 +90,7 @@ rdim_scratch_begin_fallback(RDIM_Arena **conflicts, RDI_U64 conflicts_count) rdim_thread_scratches[1] = rdim_arena_alloc(); } RDIM_Arena *arena = 0; - for(RDI_U64 scratch_idx = 0; + for(RDI_U64 scratch_idx = 0; scratch_idx < sizeof(rdim_thread_scratches)/sizeof(rdim_thread_scratches[0]); scratch_idx += 1) { @@ -2181,6 +2181,1241 @@ rdim_bake_path_tree_from_params(RDIM_Arena *arena, RDIM_BakeParams *params) return tree; } +//////////////////////////////// +//~ rjf: [Baking] Build Artifacts -> Baked Versions + +//- rjf: partial/joinable baking functions + +RDI_PROC RDIM_NameMapBakeResult +rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *src, RDI_U64 base_node_idx) +{ + RDIM_NameMapBakeResult result = {0}; + return result; +} + +//- rjf: independent (top-level, global) baking functions + +RDI_PROC RDIM_TopLevelInfoBakeResult +rdim_bake_top_level_info(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_TopLevelInfo *src) +{ + RDIM_TopLevelInfoBakeResult result = {0}; + { + result.top_level_info = rdim_push_array(arena, RDI_TopLevelInfo, 1); + result.top_level_info->arch = src->arch; + result.top_level_info->exe_name_string_idx = rdim_bake_idx_from_string(strings, src->exe_name); + result.top_level_info->exe_hash = src->exe_hash; + result.top_level_info->voff_max = src->voff_max; + } + return result; +} + +RDI_PROC RDIM_BinarySectionBakeResult +rdim_bake_binary_sections(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BinarySectionList *src) +{ + RDIM_BinarySectionBakeResult result = {0}; + { + RDI_BinarySection *dst_base = rdim_push_array(arena, RDI_BinarySection, src->count+1); + U64 dst_idx = 1; + for(RDIM_BinarySectionNode *src_n = src->first; src_n != 0; src_n = src_n->next, dst_idx += 1) + { + RDIM_BinarySection *src = &src_n->v; + RDI_BinarySection *dst = &dst_base[dst_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->flags = src->flags; + dst->voff_first = src->voff_first; + dst->voff_opl = src->voff_opl; + dst->foff_first = src->foff_first; + dst->foff_opl = src->foff_opl; + } + result.binary_sections = dst_base; + result.binary_sections_count = dst_idx; + } + return result; +} + +RDI_PROC RDIM_UnitBakeResult +rdim_bake_units(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_UnitChunkList *src) +{ + RDIM_UnitBakeResult result = {0}; + { + RDI_Unit *dst_base = rdim_push_array(arena, RDI_Unit, src->total_count+1); + RDI_U64 dst_idx = 1; + for(RDIM_UnitChunkNode *src_n = src->first; src_n != 0; src_n = src_n->next) + { + for(RDI_U64 src_chunk_idx = 0; src_chunk_idx < src_n->count; src_chunk_idx += 1, dst_idx += 1) + { + RDIM_Unit *src = &src_n->v[src_chunk_idx]; + RDI_Unit *dst = &dst_base[dst_idx]; + dst->unit_name_string_idx = rdim_bake_idx_from_string(strings, src->unit_name); + dst->compiler_name_string_idx = rdim_bake_idx_from_string(strings, src->compiler_name); + dst->source_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->source_file); + dst->object_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->object_file); + dst->archive_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->archive_file); + dst->build_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->build_path); + dst->language = src->language; + dst->line_table_idx = (RDI_U32)rdim_idx_from_line_table(src->line_table); // TODO(rjf): @u64_to_u32 + } + } + result.units = dst_base; + result.units_count = dst_idx; + } + return result; +} + +RDI_PROC RDIM_UnitVMapBakeResult +rdim_bake_unit_vmap(RDIM_Arena *arena, RDIM_UnitChunkList *units) +{ + //- rjf: build vmap from unit voff ranges + RDIM_BakeVMap unit_vmap = {0}; + { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + // rjf: count voff ranges + RDI_U64 voff_range_count = 0; + for(RDIM_UnitChunkNode *n = units->first; n != 0; n = n->next) + { + for(RDI_U64 idx = 0; idx < n->count; idx += 1) + { + RDIM_Unit *unit = &n->v[idx]; + voff_range_count += unit->voff_ranges.count; + } + } + + // rjf: count necessary markers + RDI_U64 marker_count = voff_range_count*2; + + // rjf: build keys/markers arrays + RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); + RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); + { + RDIM_SortKey *key_ptr = keys; + RDIM_VMapMarker *marker_ptr = markers; + RDI_U32 unit_idx = 1; + for(RDIM_UnitChunkNode *unit_chunk_n = units->first; + unit_chunk_n != 0; + unit_chunk_n = unit_chunk_n->next) + { + for(RDI_U64 idx = 0; idx < unit_chunk_n->count; idx += 1) + { + RDIM_Unit *unit = &unit_chunk_n->v[idx]; + for(RDIM_Rng1U64Node *n = unit->voff_ranges.first; n != 0; n = n->next) + { + RDIM_Rng1U64 range = n->v; + if(range.min < range.max) + { + key_ptr->key = range.min; + key_ptr->val = marker_ptr; + marker_ptr->idx = unit_idx; + marker_ptr->begin_range = 1; + key_ptr += 1; + marker_ptr += 1; + + key_ptr->key = range.max; + key_ptr->val = marker_ptr; + marker_ptr->idx = unit_idx; + marker_ptr->begin_range = 0; + key_ptr += 1; + marker_ptr += 1; + } + } + unit_idx += 1; + } + } + } + + // rjf: keys/markers -> unit vmap + unit_vmap = rdim_bake_vmap_from_markers(arena, markers, keys, marker_count); + rdim_scratch_end(scratch); + } + + //- rjf: fill result + RDIM_UnitVMapBakeResult result = {unit_vmap}; + return result; +} + +RDI_PROC RDIM_SrcFileBakeResult +rdim_bake_src_files(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_SrcFileChunkList *src) +{ + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + //////////////////////////// + //- rjf: iterate all source files, fill serialized version, fill line maps, fill line map tables + // + typedef struct RDIM_DataNode RDIM_DataNode; + struct RDIM_DataNode + { + RDIM_DataNode *next; + void *data; + RDI_U64 size; + }; + RDI_U32 dst_files_count = src->total_count + 1; + RDI_U32 dst_maps_count = src->source_line_map_count + 1; + RDI_SourceFile *dst_files = rdim_push_array(arena, RDI_SourceFile, dst_files_count); + RDI_SourceLineMap *dst_maps = rdim_push_array(arena, RDI_SourceLineMap, dst_maps_count); + RDIM_DataNode *first_dst_nums_node = 0; + RDIM_DataNode *last_dst_nums_node = 0; + RDIM_DataNode *first_dst_rngs_node = 0; + RDIM_DataNode *last_dst_rngs_node = 0; + RDIM_DataNode *first_dst_voffs_node = 0; + RDIM_DataNode *last_dst_voffs_node = 0; + RDI_U64 dst_nums_idx = 0; + RDI_U64 dst_rngs_idx = 0; + RDI_U64 dst_voffs_idx = 0; + RDI_U32 dst_file_idx = 1; + RDI_U32 dst_map_idx = 1; + for(RDIM_SrcFileChunkNode *chunk_n = src->first; + chunk_n != 0; + chunk_n = chunk_n->next) + { + for(RDI_U64 idx = 0; idx < chunk_n->count; idx += 1, dst_file_idx += 1) + { + RDIM_SrcFile *src_file = &chunk_n->v[idx]; + RDI_SourceFile *dst_file = &dst_files[dst_file_idx]; + + //////////////////////// + //- rjf: produce combined source file line info + // + RDI_U32 *src_file_line_nums = 0; + RDI_U32 *src_file_line_ranges = 0; + RDI_U64 *src_file_voffs = 0; + RDI_U32 src_file_line_count = 0; + RDI_U32 src_file_voff_count = 0; + { + //- rjf: gather line number map + typedef struct RDIM_SrcLineMapVoffBlock RDIM_SrcLineMapVoffBlock; + struct RDIM_SrcLineMapVoffBlock + { + RDIM_SrcLineMapVoffBlock *next; + RDI_U64 voff; + }; + typedef struct RDIM_SrcLineMapBucket RDIM_SrcLineMapBucket; + struct RDIM_SrcLineMapBucket + { + RDIM_SrcLineMapBucket *order_next; + RDIM_SrcLineMapBucket *hash_next; + RDI_U32 line_num; + RDIM_SrcLineMapVoffBlock *first_voff_block; + RDIM_SrcLineMapVoffBlock *last_voff_block; + RDI_U64 voff_count; + }; + RDIM_SrcLineMapBucket *first_bucket = 0; + RDIM_SrcLineMapBucket *last_bucket = 0; + RDI_U64 line_hash_slots_count = 2048; + RDIM_SrcLineMapBucket **line_hash_slots = rdim_push_array(scratch.arena, RDIM_SrcLineMapBucket *, line_hash_slots_count); + RDI_U64 line_count = 0; + RDI_U64 voff_count = 0; + RDI_U64 max_line_num = 0; + { + for(RDIM_SrcFileLineMapFragment *map_fragment = src_file->first_line_map_fragment; + map_fragment != 0; + map_fragment = map_fragment->next) + { + RDIM_LineSequence *sequence = map_fragment->seq; + RDI_U64 *seq_voffs = sequence->voffs; + RDI_U32 *seq_line_nums = sequence->line_nums; + RDI_U64 seq_line_count = sequence->line_count; + for(RDI_U64 i = 0; i < seq_line_count; i += 1) + { + RDI_U32 line_num = seq_line_nums[i]; + RDI_U64 voff = seq_voffs[i]; + RDI_U64 line_hash_slot_idx = line_num%line_hash_slots_count; + + // rjf: update unique voff counter & max line number + voff_count += 1; + max_line_num = Max(max_line_num, line_num); + + // rjf: find match + RDIM_SrcLineMapBucket *match = 0; + { + for(RDIM_SrcLineMapBucket *node = line_hash_slots[line_hash_slot_idx]; + node != 0; + node = node->hash_next) + { + if(node->line_num == line_num) + { + match = node; + break; + } + } + } + + // rjf: introduce new map if no match + if(match == 0) + { + match = rdim_push_array(scratch.arena, RDIM_SrcLineMapBucket, 1); + RDIM_SLLQueuePush_N(first_bucket, last_bucket, match, order_next); + RDIM_SLLStackPush_N(line_hash_slots[line_hash_slot_idx], match, hash_next); + match->line_num = line_num; + line_count += 1; + } + + // rjf: insert new voff + { + RDIM_SrcLineMapVoffBlock *block = rdim_push_array(scratch.arena, RDIM_SrcLineMapVoffBlock, 1); + RDIM_SLLQueuePush(match->first_voff_block, match->last_voff_block, block); + match->voff_count += 1; + block->voff = voff; + } + } + } + } + + //- rjf: bake sortable keys array + RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, line_count); + { + RDIM_SortKey *key_ptr = keys; + for(RDIM_SrcLineMapBucket *node = first_bucket; + node != 0; + node = node->order_next, key_ptr += 1){ + key_ptr->key = node->line_num; + key_ptr->val = node; + } + } + + //- rjf: sort keys array + RDIM_SortKey *sorted_keys = rdim_sort_key_array(scratch.arena, keys, line_count); + + //- rjf: bake result + RDI_U32 *line_nums = rdim_push_array_no_zero(scratch.arena, RDI_U32, line_count); + RDI_U32 *line_ranges = rdim_push_array_no_zero(scratch.arena, RDI_U32, line_count + 1); + RDI_U64 *voffs = rdim_push_array_no_zero(scratch.arena, RDI_U64, voff_count); + { + RDI_U64 *voff_ptr = voffs; + for(RDI_U32 i = 0; i < line_count; i += 1) + { + line_nums[i] = sorted_keys[i].key; + line_ranges[i] = (RDI_U32)(voff_ptr - voffs); // TODO(rjf): @u64_to_u32 + RDIM_SrcLineMapBucket *bucket = (RDIM_SrcLineMapBucket*)sorted_keys[i].val; + for(RDIM_SrcLineMapVoffBlock *node = bucket->first_voff_block; node != 0; node = node->next) + { + *voff_ptr = node->voff; + voff_ptr += 1; + } + } + line_ranges[line_count] = voff_count; + } + + //- rjf: fill output + src_file_line_nums = line_nums; + src_file_line_ranges = line_ranges; + src_file_line_count = line_count; + src_file_voffs = voffs; + src_file_voff_count = voff_count; + } + + //////////////////////// + //- rjf: grab & fill the next line map, if this file has one + // + RDI_SourceLineMap *dst_map = 0; + if(src_file->first_line_map_fragment != 0) + { + dst_map = &dst_maps[dst_map_idx]; + dst_map_idx += 1; + dst_map->line_count = (RDI_U32)src_file_line_count; // TODO(rjf): @u64_to_u32 + dst_map->voff_count = (RDI_U32)src_file_voff_count; // TODO(rjf): @u64_to_u32 + dst_map->line_map_nums_base_idx = (RDI_U32)dst_nums_idx; // TODO(rjf): @u64_to_u32 + dst_map->line_map_range_base_idx = (RDI_U32)dst_rngs_idx; // TODO(rjf): @u64_to_u32 + dst_map->line_map_voff_base_idx = (RDI_U32)dst_voffs_idx; // TODO(rjf): @u64_to_u32 + } + + //////////////////////// + //- rjf: gather line map data chunks for later collation & storage into their own top-level sections + // + { + RDIM_DataNode *dst_num_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); + RDIM_SLLQueuePush(first_dst_nums_node, last_dst_nums_node, dst_num_node); + dst_num_node->data = src_file_line_nums; + dst_num_node->size = sizeof(RDI_U32)*src_file_line_count; + RDIM_DataNode *dst_rng_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); + RDIM_SLLQueuePush(first_dst_rngs_node, last_dst_rngs_node, dst_rng_node); + dst_rng_node->data = src_file_line_ranges; + dst_rng_node->size = sizeof(RDI_U32)*(src_file_line_count+1); + RDIM_DataNode *dst_voff_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); + RDIM_SLLQueuePush(first_dst_voffs_node, last_dst_voffs_node, dst_voff_node); + dst_voff_node->data = src_file_voffs; + dst_voff_node->size = sizeof(RDI_U64)*(src_file_voff_count); + dst_nums_idx += src_file_line_count; + dst_rngs_idx += src_file_line_count+1; + dst_voffs_idx+= src_file_voff_count; + } + + //////////////////////// + //- rjf: fill file info + // + dst_file->file_path_node_idx = rdim_bake_path_node_idx_from_string(path_tree, src_file->normal_full_path); + dst_file->normal_full_path_string_idx = rdim_bake_idx_from_string(strings, src_file->normal_full_path); + dst_file->source_line_map_idx = (RDI_U32)(dst_map ? (dst_map - dst_maps) : 0); + } + } + + //////////////////////////// + //- rjf: coalesce source line map data blobs + // + RDI_U32 *source_line_map_nums = rdim_push_array_no_zero(arena, RDI_U32, dst_nums_idx); + RDI_U32 *source_line_map_rngs = rdim_push_array_no_zero(arena, RDI_U32, dst_rngs_idx); + RDI_U64 *source_line_map_voffs= rdim_push_array_no_zero(arena, RDI_U64, dst_voffs_idx); + { + RDI_U64 num_idx = 0; + RDI_U64 rng_idx = 0; + RDI_U64 voff_idx= 0; + for(RDIM_DataNode *num_n = first_dst_nums_node; num_n != 0; num_n = num_n->next) + { + rdim_memcpy(source_line_map_nums+num_idx, num_n->data, num_n->size); + num_idx += num_n->size/sizeof(RDI_U32); + } + for(RDIM_DataNode *rng_n = first_dst_rngs_node; rng_n != 0; rng_n = rng_n->next) + { + rdim_memcpy(source_line_map_rngs+rng_idx, rng_n->data, rng_n->size); + rng_idx += rng_n->size/sizeof(RDI_U32); + } + for(RDIM_DataNode *voff_n = first_dst_voffs_node; voff_n != 0; voff_n = voff_n->next) + { + rdim_memcpy(source_line_map_voffs+voff_idx, voff_n->data, voff_n->size); + voff_idx += voff_n->size/sizeof(RDI_U64); + } + } + + //////////////////////////// + //- rjf: fill result + // + RDIM_SrcFileBakeResult result = {0}; + result.source_files = dst_files; + result.source_files_count = dst_files_count; + result.source_line_maps = dst_maps; + result.source_line_maps_count = dst_maps_count; + result.source_line_map_nums = source_line_map_nums; + result.source_line_map_nums_count = dst_nums_idx; + result.source_line_map_rngs = source_line_map_rngs; + result.source_line_map_rngs_count = dst_rngs_idx; + result.source_line_map_voffs = source_line_map_voffs; + result.source_line_map_voffs_count= dst_voffs_idx; + + rdim_scratch_end(scratch); + return result; +} + +RDI_PROC RDIM_LineTableBakeResult +rdim_bake_line_tables(RDIM_Arena *arena, RDIM_LineTableChunkList *src) +{ + ////////////////////////////// + //- rjf: build all combined line info + // + RDI_LineTable *dst_line_tables = push_array(arena, RDI_LineTable, src->total_count+1); + RDI_U64 *dst_line_voffs = push_array(arena, RDI_U64, src->total_line_count + 2*src->total_seq_count); + RDI_Line *dst_lines = push_array(arena, RDI_Line, src->total_line_count + src->total_seq_count); + RDI_Column *dst_cols = push_array(arena, RDI_Column, 1); + { + RDI_U64 dst_table_idx = 1; + RDI_U64 dst_voff_idx = 0; + RDI_U64 dst_line_idx = 0; + RDI_U64 dst_col_idx = 0; + for(RDIM_LineTableChunkNode *src_n = src->first; src_n != 0; src_n = src_n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < src_n->count; chunk_idx += 1) + { + RDIM_LineTable *src_line_table = &src_n->v[chunk_idx]; + RDI_LineTable *dst_line_table = &dst_line_tables[dst_table_idx]; + + //- rjf: fill combined line table info + { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + //- rjf: gather up all line info into two arrays: + // + // [1] keys: sortable array; pairs voffs with line info records; null records are sequence enders + // [2] recs: contains all the source coordinates for a range of voffs + // + typedef struct RDIM_LineRec RDIM_LineRec; + struct RDIM_LineRec + { + RDI_U32 file_id; + RDI_U32 line_num; + RDI_U16 col_first; + RDI_U16 col_opl; + }; + RDI_U64 line_count = src_line_table->line_count; + RDI_U64 seq_count = src_line_table->seq_count; + RDI_U64 key_count = line_count + seq_count; + RDIM_SortKey *line_keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, key_count); + RDIM_LineRec *line_recs = rdim_push_array_no_zero(scratch.arena, RDIM_LineRec, line_count); + { + RDIM_SortKey *key_ptr = line_keys; + RDIM_LineRec *rec_ptr = line_recs; + for(RDIM_LineSequenceNode *seq_n = src_line_table->first_seq; seq_n != 0; seq_n = seq_n->next) + { + RDIM_LineSequence *seq = &seq_n->v; + for(RDI_U64 line_idx = 0; line_idx < seq->line_count; line_idx += 1) + { + key_ptr->key = seq->voffs[line_idx]; + key_ptr->val = rec_ptr; + key_ptr += 1; + rec_ptr->file_id = (RDI_U32)rdim_idx_from_src_file(seq->src_file); // TODO(rjf): @u64_to_u32 + rec_ptr->line_num = seq->line_nums[line_idx]; + if(seq->col_nums != 0) + { + rec_ptr->col_first = seq->col_nums[line_idx*2]; + rec_ptr->col_opl = seq->col_nums[line_idx*2 + 1]; + } + rec_ptr += 1; + } + key_ptr->key = seq->voffs[seq->line_count]; + key_ptr->val = 0; + key_ptr += 1; + } + } + + //- rjf: sort + RDIM_SortKey *sorted_line_keys = 0; + RDIM_ProfScope("sort") + { + sorted_line_keys = rdim_sort_key_array(scratch.arena, line_keys, key_count); + } + + // TODO(rjf): do a pass over sorted keys to make sure duplicate keys + // are sorted with null record first, and no more than one null + // record and one non-null record + + //- rjf: arrange output + RDI_U64 *arranged_voffs = dst_line_voffs + dst_voff_idx; + RDI_Line *arranged_lines = dst_lines + dst_line_idx; + RDIM_ProfScope("arrange output") + { + for(RDI_U64 i = 0; i < key_count; i += 1) + { + arranged_voffs[i] = sorted_line_keys[i].key; + } + arranged_voffs[key_count] = ~0ull; + for(RDI_U64 i = 0; i < key_count; i += 1) + { + RDIM_LineRec *rec = (RDIM_LineRec*)sorted_line_keys[i].val; + if(rec != 0) + { + arranged_lines[i].file_idx = rec->file_id; + arranged_lines[i].line_num = rec->line_num; + } + else + { + arranged_lines[i].file_idx = 0; + arranged_lines[i].line_num = 0; + } + } + } + + rdim_scratch_end(scratch); + } + + //- rjf: fill destination table + dst_line_table->voffs_base_idx = (RDI_U32)dst_voff_idx; // TODO(rjf): @u64_to_u32 + dst_line_table->lines_base_idx = (RDI_U32)dst_line_idx; // TODO(rjf): @u64_to_u32 + dst_line_table->cols_base_idx = (RDI_U32)dst_col_idx; // TODO(rjf): @u64_to_u32 + dst_line_table->lines_count = (RDI_U32)src_line_table->line_count + src_line_table->seq_count; // TODO(rjf): @u64_to_u32 + + //- rjf: increment + dst_table_idx += 1; + dst_voff_idx += src_line_table->line_count + 2*src_line_table->seq_count; + dst_line_idx += src_line_table->line_count + src_line_table->seq_count; + } + } + } + + ////////////////////////////// + //- rjf: fill result + // + RDIM_LineTableBakeResult result = {0}; + { + result.line_tables = dst_line_tables; + result.line_tables_count = src->total_count; + result.line_table_voffs = dst_line_voffs; + result.line_table_voffs_count = (src->total_line_count + src->total_seq_count); + result.line_table_lines = dst_lines; + result.line_table_lines_count = (src->total_line_count + src->total_seq_count); + result.line_table_columns = dst_cols; + result.line_table_columns_count = src->total_col_count; + } + return result; +} + +RDI_PROC RDIM_TypeNodeBakeResult +rdim_bake_types(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_TypeChunkList *src) +{ + RDI_TypeNode *type_nodes = push_array(arena, RDI_TypeNode, src->total_count+1); + RDI_U32 dst_idx = 1; + for(RDIM_TypeChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + { + RDIM_Type *src = &n->v[chunk_idx]; + RDI_TypeNode *dst = &type_nodes[dst_idx]; + + //- rjf: fill shared type node info + dst->kind = src->kind; + dst->flags = (RDI_U16)src->flags; // TODO(rjf): @u32_to_u16 + dst->byte_size = src->byte_size; + + //- rjf: fill built-in-only type node info + if(RDI_TypeKind_FirstBuiltIn <= dst->kind && dst->kind <= RDI_TypeKind_LastBuiltIn) + { + dst->built_in.name_string_idx = rdim_bake_idx_from_string(strings, src->name); + } + + //- rjf: fill constructed type node info + else if(RDI_TypeKind_FirstConstructed <= dst->kind && dst->kind <= RDI_TypeKind_LastConstructed) + { + dst->constructed.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 + dst->constructed.count = src->count; + if(dst->kind == RDI_TypeKind_Function || dst->kind == RDI_TypeKind_Method) + { + RDI_U32 param_idx_run_count = src->count; + RDI_U32 *param_idx_run = rdim_push_array_no_zero(arena, RDI_U32, param_idx_run_count); + for(RDI_U32 idx = 0; idx < param_idx_run_count; idx += 1) + { + param_idx_run[idx] = (RDI_U32)rdim_idx_from_type(src->param_types[idx]); // TODO(rjf): @u64_to_u32 + } + dst->constructed.param_idx_run_first = rdim_bake_idx_from_idx_run(idx_runs, param_idx_run, param_idx_run_count); + } + else if(dst->kind == RDI_TypeKind_MemberPtr) + { + // TODO(rjf): member pointers not currently supported. + } + } + + //- rjf: fill user-defined-type info + else if(RDI_TypeKind_FirstUserDefined <= dst->kind && dst->kind <= RDI_TypeKind_LastUserDefined) + { + dst->user_defined.name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->user_defined.udt_idx = (RDI_U32)rdim_idx_from_udt(src->udt); // TODO(rjf): @u64_to_u32 + dst->user_defined.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 + } + + //- rjf: fill bitfield info + else if(dst->kind == RDI_TypeKind_Bitfield) + { + dst->bitfield.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 + dst->bitfield.off = src->off; + dst->bitfield.size = src->count; + } + } + } + RDIM_TypeNodeBakeResult result = {0}; + result.type_nodes = type_nodes; + result.type_nodes_count = (src->total_count+1); + return result; +} + +RDI_PROC RDIM_UDTBakeResult +rdim_bake_udts(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_UDTChunkList *src) +{ + //- rjf: build tables + RDI_UDT * udts = push_array(arena, RDI_UDT, src->total_count+1); + RDI_Member * members = push_array(arena, RDI_Member, src->total_member_count+1); + RDI_EnumMember *enum_members = push_array(arena, RDI_EnumMember, src->total_enum_val_count+1); + { + RDI_U32 dst_udt_idx = 1; + RDI_U32 dst_member_idx = 1; + RDI_U32 dst_enum_member_idx = 1; + for(RDIM_UDTChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_udt_idx += 1) + { + RDIM_UDT *src_udt = &n->v[chunk_idx]; + RDI_UDT *dst_udt = &udts[dst_udt_idx]; + + //- rjf: fill basics + dst_udt->self_type_idx = (RDI_U32)rdim_idx_from_type(src_udt->self_type); // TODO(rjf): @u64_to_u32 + dst_udt->file_idx = (RDI_U32)rdim_idx_from_src_file(src_udt->src_file); // TODO(rjf): @u64_to_u32 + dst_udt->line = src_udt->line; + dst_udt->col = src_udt->col; + + //- rjf: fill members + if(src_udt->member_count != 0) + { + dst_udt->member_first = dst_member_idx; + dst_udt->member_count = src_udt->member_count; + for(RDIM_UDTMember *src_member = src_udt->first_member; + src_member != 0; + src_member = src_member->next, dst_member_idx += 1) + { + RDI_Member *dst_member = &members[dst_member_idx]; + dst_member->kind = src_member->kind; + dst_member->name_string_idx = rdim_bake_idx_from_string(strings, src_member->name); + dst_member->type_idx = (RDI_U32)rdim_idx_from_type(src_member->type); // TODO(rjf): @u64_to_u32 + dst_member->off = src_member->off; + } + } + + //- rjf: fill enum members + else if(src_udt->enum_val_count != 0) + { + dst_udt->flags |= RDI_UDTFlag_EnumMembers; + dst_udt->member_first = dst_enum_member_idx; + dst_udt->member_count = src_udt->enum_val_count; + for(RDIM_UDTEnumVal *src_member = src_udt->first_enum_val; + src_member != 0; + src_member = src_member->next, dst_enum_member_idx += 1) + { + RDI_EnumMember *dst_member = &enum_members[dst_enum_member_idx]; + dst_member->name_string_idx = rdim_bake_idx_from_string(strings, src_member->name); + dst_member->val = src_member->val; + } + } + } + } + } + + //- rjf: fill result + RDIM_UDTBakeResult result = {0}; + { + result.udts = udts; + result.udts_count = src->total_count+1; + result.members = members; + result.members_count = src->total_member_count+1; + result.enum_members = enum_members; + result.enum_members_count = src->total_enum_val_count+1; + } + return result; +} + +RDI_PROC RDIM_GlobalVariableBakeResult +rdim_bake_global_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src) +{ + RDI_GlobalVariable *global_variables = push_array(arena, RDI_GlobalVariable, src->total_count+1); + RDI_U32 dst_idx = 1; + for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + { + RDIM_Symbol *src = &n->v[chunk_idx]; + RDI_GlobalVariable *dst = &global_variables[dst_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->voff = src->offset; + dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 + if(src->is_extern) + { + dst->link_flags |= RDI_LinkFlag_External; + } + if(src->container_type != 0) + { + dst->link_flags |= RDI_LinkFlag_TypeScoped; + dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 + } + else if(src->container_symbol != 0) + { + dst->link_flags |= RDI_LinkFlag_ProcScoped; + dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 + } + } + } + RDIM_GlobalVariableBakeResult result = {0}; + result.global_variables = global_variables; + result.global_variables_count = (src->total_count+1); + return result; +} + +RDI_PROC RDIM_GlobalVMapBakeResult +rdim_bake_global_vmap(RDIM_Arena *arena, RDIM_SymbolChunkList *src) +{ + //- rjf: build global vmap + RDIM_BakeVMap global_vmap = {0}; + { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + //- rjf: allocate keys/markers + RDI_U64 marker_count = src->total_count*2; + RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); + RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); + + //- rjf: fill + { + RDIM_SortKey *key_ptr = keys; + RDIM_VMapMarker *marker_ptr = markers; + + // rjf: fill actual globals + for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) + { + RDIM_Symbol *global_var = &n->v[chunk_idx]; + RDI_U32 global_var_idx = (RDI_U32)rdim_idx_from_symbol(global_var); // TODO(rjf): @u64_to_u32 + RDI_U64 global_var_size = global_var->type ? global_var->type->byte_size : 1; + + RDI_U64 first = global_var->offset; + RDI_U64 opl = first + global_var_size; + + key_ptr->key = first; + key_ptr->val = marker_ptr; + marker_ptr->idx = global_var_idx; + marker_ptr->begin_range = 1; + key_ptr += 1; + marker_ptr += 1; + + key_ptr->key = opl; + key_ptr->val = marker_ptr; + marker_ptr->idx = global_var_idx; + marker_ptr->begin_range = 0; + key_ptr += 1; + marker_ptr += 1; + } + } + + // rjf: fill nil global + { + RDI_U32 global_idx = 0; + RDI_U64 first = 0; + RDI_U64 opl = 0xffffffffffffffffull; + key_ptr->key = first; + key_ptr->val = marker_ptr; + marker_ptr->idx = global_idx; + marker_ptr->begin_range = 1; + key_ptr += 1; + marker_ptr += 1; + key_ptr->key = opl; + key_ptr->val = marker_ptr; + marker_ptr->idx = global_idx; + marker_ptr->begin_range = 0; + key_ptr += 1; + marker_ptr += 1; + } + } + + // rjf: construct vmap + global_vmap = rdim_bake_vmap_from_markers(arena, markers, keys, marker_count); + + rdim_scratch_end(scratch); + } + + //- rjf: fill result + RDIM_GlobalVMapBakeResult result = {global_vmap}; + return result; +} + +RDI_PROC RDIM_ThreadVariableBakeResult +rdim_bake_thread_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src) +{ + RDI_ThreadVariable *thread_variables = push_array(arena, RDI_ThreadVariable, src->total_count+1); + RDI_U32 dst_idx = 1; + for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + { + RDIM_Symbol *src = &n->v[chunk_idx]; + RDI_ThreadVariable *dst = &thread_variables[dst_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->tls_off = (RDI_U32)src->offset; // TODO(rjf): @u64_to_u32 + dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); + if(src->is_extern) + { + dst->link_flags |= RDI_LinkFlag_External; + } + if(src->container_type != 0) + { + dst->link_flags |= RDI_LinkFlag_TypeScoped; + dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 + } + else if(src->container_symbol != 0) + { + dst->link_flags |= RDI_LinkFlag_ProcScoped; + dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 + } + } + } + RDIM_ThreadVariableBakeResult result = {0}; + result.thread_variables = thread_variables; + result.thread_variables_count = src->total_count+1; + return result; +} + +RDI_PROC RDIM_ProcedureBakeResult +rdim_bake_procedures(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src) +{ + RDI_Procedure *procedures = push_array(arena, RDI_Procedure, src->total_count+1); + RDI_U32 dst_idx = 1; + for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + { + RDIM_Symbol *src = &n->v[chunk_idx]; + RDI_Procedure *dst = &procedures[dst_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->link_name_string_idx = rdim_bake_idx_from_string(strings, src->link_name); + if(src->is_extern) + { + dst->link_flags |= RDI_LinkFlag_External; + } + if(src->container_type != 0) + { + dst->link_flags |= RDI_LinkFlag_TypeScoped; + dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 + } + else if(src->container_symbol != 0) + { + dst->link_flags |= RDI_LinkFlag_ProcScoped; + dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 + } + dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 + dst->root_scope_idx = (RDI_U32)rdim_idx_from_scope(src->root_scope); // TODO(rjf): @u64_to_u32 + } + } + RDIM_ProcedureBakeResult result = {0}; + result.procedures = procedures; + result.procedures_count = src->total_count+1; + return result; +} + +RDI_PROC RDIM_ScopeBakeResult +rdim_bake_scopes(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_ScopeChunkList *src) +{ + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + //////////////////////////// + //- rjf: build all scopes, scope voffs, locals, and location blocks + // + RDI_Scope * scopes = rdim_push_array(arena, RDI_Scope, src->total_count+1); + RDI_U64 * scope_voffs = rdim_push_array(arena, RDI_U64, src->scope_voff_count+1); + RDI_Local * locals = rdim_push_array(arena, RDI_Local, src->local_count+1); + RDI_LocationBlock * location_blocks = rdim_push_array(arena, RDI_LocationBlock, src->location_count+1); + RDIM_String8List location_data_blobs = {0}; + RDIM_ProfScope("build all scopes, scope voffs, locals, and location blocks") + { + RDI_U64 dst_scope_idx = 1; + RDI_U64 dst_scope_voff_idx = 1; + RDI_U64 dst_local_idx = 1; + RDI_U64 dst_location_block_idx = 1; + for(RDIM_ScopeChunkNode *chunk_n = src->first; chunk_n != 0; chunk_n = chunk_n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < chunk_n->count; chunk_idx += 1, dst_scope_idx += 1) + { + RDIM_Scope *src_scope = &chunk_n->v[chunk_idx]; + RDI_Scope *dst_scope = &scopes[dst_scope_idx]; + + //- rjf: push scope's voffs + RDI_U64 voff_idx_first = dst_scope_voff_idx; + { + for(RDIM_Rng1U64Node *n = src_scope->voff_ranges.first; n != 0; n = n->next) + { + scope_voffs[dst_scope_voff_idx] = n->v.min; + dst_scope_voff_idx += 1; + scope_voffs[dst_scope_voff_idx] = n->v.max; + dst_scope_voff_idx += 1; + } + } + RDI_U64 voff_idx_opl = dst_scope_voff_idx; + + //- rjf: push locals + RDI_U64 local_idx_first = dst_local_idx; + for(RDIM_Local *src_local = src_scope->first_local; + src_local != 0; + src_local = src_local->next, dst_local_idx += 1) + { + //- rjf: push local's locations + RDI_U64 location_block_idx_first = dst_location_block_idx; + for(RDIM_LocationCase *loccase = src_local->locset.first_location_case; + loccase != 0; + loccase = loccase->next, dst_location_block_idx += 1) + { + // rjf: fill location block + RDI_LocationBlock *dst_locblock = &location_blocks[dst_location_block_idx]; + dst_locblock->scope_off_first = loccase->voff_range.min; + dst_locblock->scope_off_opl = loccase->voff_range.max; + dst_locblock->location_data_off = location_data_blobs.total_size; + + // rjf: serialize location into location data + RDIM_Location *src_location = loccase->location; + { + // rjf: nil location + if(src_location == 0) + { + rdim_str8_list_push_align(scratch.arena, &location_data_blobs, 8); + rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_lit("\0")); + } + + // rjf: valid location + else switch(src_location->kind) + { + // rjf: catchall unsupported case + default: + { + rdim_str8_list_push_align(scratch.arena, &location_data_blobs, 8); + rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_lit("\0")); + }break; + + // rjf: bytecode streams + case RDI_LocationKind_AddrBytecodeStream: + case RDI_LocationKind_ValBytecodeStream: + { + rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, rdim_str8_struct(&src_location->kind))); + for(RDIM_EvalBytecodeOp *op_node = src_location->bytecode.first_op; + op_node != 0; + op_node = op_node->next) + { + RDI_U8 op_data[9]; + op_data[0] = op_node->op; + rdim_memcpy(op_data + 1, &op_node->p, op_node->p_size); + RDIM_String8 op_data_str = rdim_str8(op_data, 1 + op_node->p_size); + rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, op_data_str)); + } + { + RDI_U64 data = 0; + RDIM_String8 data_str = rdim_str8((RDI_U8 *)&data, 1); + rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, data_str)); + } + }break; + + // rjf: simple addr+off cases + case RDI_LocationKind_AddrRegPlusU16: + case RDI_LocationKind_AddrAddrRegPlusU16: + { + RDI_LocationRegPlusU16 loc = {0}; + loc.kind = src_location->kind; + loc.reg_code = src_location->reg_code; + loc.offset = src_location->offset; + rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, rdim_str8_struct(&loc))); + }break; + + // rjf: register cases + case RDI_LocationKind_ValReg: + { + RDI_LocationReg loc = {0}; + loc.kind = src_location->kind; + loc.reg_code = src_location->reg_code; + rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, rdim_str8_struct(&loc))); + }break; + } + } + } + RDI_U64 location_block_idx_opl = dst_location_block_idx; + + //- rjf: fill local + RDI_Local *dst_local = &locals[dst_local_idx]; + dst_local->kind = src_local->kind; + dst_local->name_string_idx = rdim_bake_idx_from_string(strings, src_local->name); + dst_local->type_idx = (RDI_U32)rdim_idx_from_type(src_local->type); // TODO(rjf): @u64_to_u32 + dst_local->location_first = (RDI_U32)location_block_idx_first; // TODO(rjf): @u64_to_u32 + dst_local->location_opl = (RDI_U32)location_block_idx_opl; // TODO(rjf): @u64_to_u32 + } + RDI_U64 local_idx_opl = dst_local_idx; + + //- rjf: fill scope + dst_scope->proc_idx = (RDI_U32)rdim_idx_from_symbol(src_scope->symbol); // TODO(rjf): @u64_to_u32 + dst_scope->parent_scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope->parent_scope); // TODO(rjf): @u64_to_u32 + dst_scope->first_child_scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope->first_child); // TODO(rjf): @u64_to_u32 + dst_scope->next_sibling_scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope->next_sibling); // TODO(rjf): @u64_to_u32 + dst_scope->voff_range_first = (RDI_U32)voff_idx_first; // TODO(rjf): @u64_to_u32 + dst_scope->voff_range_opl = (RDI_U32)voff_idx_opl; // TODO(rjf): @u64_to_u32 + dst_scope->local_first = (RDI_U32)local_idx_first; // TODO(rjf): @u64_to_u32 + dst_scope->local_count = (RDI_U32)(local_idx_opl - local_idx_first); // TODO(rjf): @u64_to_u32 + } + } + } + + //////////////////////////// + //- rjf: build flattened location data + // + RDIM_String8 location_data_blob = {0}; + RDIM_ProfScope("build flattened location data") + { + location_data_blob = rdim_str8_list_join(arena, &location_data_blobs, rdim_str8_lit("")); + } + + //////////////////////////// + //- rjf: fill result + // + RDIM_ScopeBakeResult result = {0}; + result.scopes = scopes; + result.scopes_count = src->total_count+1; + result.scope_voffs = scope_voffs; + result.scope_voffs_count = src->scope_voff_count+1; + result.locals = locals; + result.locals_count = src->local_count+1; + result.location_blocks = location_blocks; + result.location_blocks_count = src->location_count+1; + result.location_data = location_data_blob.str; + result.location_data_size = location_data_blob.size; + rdim_scratch_end(scratch); + return result; +} + +RDI_PROC RDIM_ScopeVMapBakeResult +rdim_bake_scope_vmap(RDIM_Arena *arena, RDIM_ScopeChunkList *src) +{ + RDIM_BakeVMap scope_vmap = {0}; + { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + // rjf: allocate keys/markers + RDI_U64 marker_count = src->scope_voff_count; + RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); + RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); + + // rjf: fill + { + RDIM_SortKey *key_ptr = keys; + RDIM_VMapMarker *marker_ptr = markers; + for(RDIM_ScopeChunkNode *chunk_n = src->first; chunk_n != 0; chunk_n = chunk_n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < chunk_n->count; chunk_idx += 1) + { + RDIM_Scope *src_scope = &chunk_n->v[chunk_idx]; + RDI_U32 scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope); // TODO(rjf): @u64_to_u32 + for(RDIM_Rng1U64Node *n = src_scope->voff_ranges.first; n != 0; n = n->next) + { + key_ptr->key = n->v.min; + key_ptr->val = marker_ptr; + marker_ptr->idx = scope_idx; + marker_ptr->begin_range = 1; + key_ptr += 1; + marker_ptr += 1; + + key_ptr->key = n->v.max; + key_ptr->val = marker_ptr; + marker_ptr->idx = scope_idx; + marker_ptr->begin_range = 0; + key_ptr += 1; + marker_ptr += 1; + } + } + } + } + + // rjf: produce vmap + scope_vmap = rdim_bake_vmap_from_markers(arena, markers, keys, marker_count); + rdim_scratch_end(scratch); + } + RDIM_ScopeVMapBakeResult result = {scope_vmap}; + return result; +} + +RDI_PROC RDIM_TopLevelNameMapBakeResult +rdim_bake_name_maps_top_level(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT]) +{ + RDI_NameMap *dst_maps = rdim_push_array(arena, RDI_NameMap, RDI_NameMapKind_COUNT); + { + RDI_U64 dst_map_idx = 0; + RDI_U64 dst_map_bucket_idx = 0; + RDI_U64 dst_map_node_idx = 0; + for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); + k < RDI_NameMapKind_COUNT; + k = (RDI_NameMapKind)(k+1)) + { + RDI_NameMap *dst_map = &dst_maps[dst_map_idx]; + RDIM_BakeNameMap *src_map = name_maps[k]; + dst_map->bucket_base_idx = (RDI_U32)dst_map_bucket_idx; // TODO(rjf): @u64_to_u32 + dst_map->node_base_idx = (RDI_U32)dst_map_node_idx; // TODO(rjf): @u64_to_u32 + dst_map->bucket_count = (RDI_U32)src_map->name_count; // TODO(rjf): @u64_to_u32 + dst_map->node_count = (RDI_U32)src_map->name_count; // TODO(rjf): @u64_to_u32 + dst_map_idx += 1; + dst_map_bucket_idx += dst_map->bucket_count; + dst_map_node_idx += dst_map->node_count; + } + } + RDIM_TopLevelNameMapBakeResult result = {0}; + result.name_maps = dst_maps; + result.name_maps_count = RDI_NameMapKind_COUNT; + return result; +} + +RDI_PROC RDIM_FilePathBakeResult +rdim_bake_file_paths(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree) +{ + RDI_U32 dst_nodes_count = path_tree->count; + RDI_FilePathNode *dst_nodes = rdim_push_array(arena, RDI_FilePathNode, dst_nodes_count); + { + RDI_U32 dst_node_idx = 0; + for(RDIM_BakePathNode *src_node = path_tree->first; + src_node != 0; + src_node = src_node->next_order, dst_node_idx += 1) + { + RDI_FilePathNode *dst_node = &dst_nodes[dst_node_idx]; + dst_node->name_string_idx = rdim_bake_idx_from_string(strings, src_node->name); + dst_node->source_file_idx = rdim_idx_from_src_file(src_node->src_file); + if(src_node->parent != 0) + { + dst_node->parent_path_node = src_node->parent->idx; + } + if(src_node->first_child != 0) + { + dst_node->first_child = src_node->first_child->idx; + } + if(src_node->next_sibling != 0) + { + dst_node->next_sibling = src_node->next_sibling->idx; + } + } + } + RDIM_FilePathBakeResult result = {0}; + result.nodes = dst_nodes; + result.nodes_count = dst_nodes_count; + return result; +} + +RDI_PROC RDIM_StringBakeResult +rdim_bake_strings(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings) +{ + RDIM_BakeSectionList sections = {0}; + RDI_U32 *str_offs = rdim_push_array_no_zero(arena, RDI_U32, strings->total_count + 1); + RDI_U32 off_cursor = 0; + { + RDI_U32 *off_ptr = str_offs; + *off_ptr = 0; + off_ptr += 1; + for(RDI_U64 slot_idx = 0; slot_idx < strings->slots_count; slot_idx += 1) + { + for(RDIM_BakeStringChunkNode *n = strings->slots[slot_idx].first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) + { + RDIM_BakeString *bake_string = &n->v[chunk_idx]; + *off_ptr = off_cursor; + off_cursor += bake_string->string.size; + off_ptr += 1; + } + } + } + } + RDI_U8 *buf = rdim_push_array(arena, RDI_U8, off_cursor); + { + RDI_U8 *ptr = buf; + for(RDI_U64 slot_idx = 0; slot_idx < strings->slots_count; slot_idx += 1) + { + for(RDIM_BakeStringChunkNode *n = strings->slots[slot_idx].first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) + { + RDIM_BakeString *bake_string = &n->v[chunk_idx]; + rdim_memcpy(ptr, bake_string->string.str, bake_string->string.size); + ptr += bake_string->string.size; + } + } + } + } + RDIM_StringBakeResult result = {0}; + result.string_offs = str_offs; + result.string_offs_count = strings->total_count+1; + result.string_data = buf; + result.string_data_size = off_cursor; + return result; +} + +RDI_PROC RDIM_IndexRunBakeResult +rdim_bake_index_runs(RDIM_Arena *arena, RDIM_BakeIdxRunMap *idx_runs) +{ + RDI_U32 *idx_data = rdim_push_array_no_zero(arena, RDI_U32, idx_runs->idx_count); + { + RDI_U32 *out_ptr = idx_data; + RDI_U32 *opl = out_ptr + idx_runs->idx_count; + for(RDIM_BakeIdxRunNode *node = idx_runs->order_first; + node != 0 && out_ptr < opl; + node = node->order_next) + { + rdim_memcpy(out_ptr, node->idx_run, sizeof(*node->idx_run)*node->count); + out_ptr += node->count; + } + } + RDIM_IndexRunBakeResult result = {0}; + result.idx_runs = idx_data; + result.idx_count = idx_runs->idx_count; + return result; +} + //////////////////////////////// //~ rjf: [Baking] Build Artifacts -> Data Section Lists @@ -3321,7 +4556,6 @@ rdim_bake_top_level_name_map_section_list_from_params_maps(RDIM_Arena *arena, RD RDI_NameMap *dst_map = &dst_maps[dst_map_idx]; RDIM_BakeNameMap *src_map = name_maps[k]; if(src_map == 0 || src_map->name_count == 0) { continue; } - dst_map->kind = k; dst_map->bucket_base_idx = (RDI_U32)dst_map_bucket_idx; // TODO(rjf): @u64_to_u32 dst_map->node_base_idx = (RDI_U32)dst_map_node_idx; // TODO(rjf): @u64_to_u32 dst_map->bucket_count = (RDI_U32)src_map->name_count; // TODO(rjf): @u64_to_u32 diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index 4b2466c0..cb34676a 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -1430,13 +1430,8 @@ RDI_PROC RDIM_BakePathTree *rdim_bake_path_tree_from_params(RDIM_Arena *arena, R //////////////////////////////// //~ rjf: [Baking] Build Artifacts -> Baked Versions -// TODO(rjf): -// -// separate category of partial/joinable/slice-based baking functions -// (distinct from necessarily serial, top-level, non-trivially-joinable -// paths) can go here - this includes things like the "parallel-for" -// style filling of various tables, but it does not include things like -// vmap building. +//- rjf: partial/joinable baking functions +RDI_PROC RDIM_NameMapBakeResult rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *src, RDI_U64 base_node_idx); //- rjf: independent (top-level, global) baking functions RDI_PROC RDIM_TopLevelInfoBakeResult rdim_bake_top_level_info(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_TopLevelInfo *src); @@ -1454,7 +1449,6 @@ RDI_PROC RDIM_ProcedureBakeResult rdim_bake_procedures(RDIM_Arena *arena, RDI_PROC RDIM_ScopeBakeResult rdim_bake_scopes(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_ScopeChunkList *src); RDI_PROC RDIM_ScopeVMapBakeResult rdim_bake_scope_vmap(RDIM_Arena *arena, RDIM_ScopeChunkList *src); RDI_PROC RDIM_TopLevelNameMapBakeResult rdim_bake_name_maps_top_level(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT]); -RDI_PROC RDIM_NameMapBakeResult rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *src, RDI_U64 base_node_idx); RDI_PROC RDIM_FilePathBakeResult rdim_bake_file_paths(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree); RDI_PROC RDIM_StringBakeResult rdim_bake_strings(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings); RDI_PROC RDIM_IndexRunBakeResult rdim_bake_index_runs(RDIM_Arena *arena, RDIM_BakeIdxRunMap *idx_runs); diff --git a/src/raddbg/raddbg.h b/src/raddbg/raddbg.h index 4c065424..cd01b5d0 100644 --- a/src/raddbg/raddbg.h +++ b/src/raddbg/raddbg.h @@ -4,6 +4,8 @@ //////////////////////////////// //~ rjf: Frontend/UI Pass Tasks // +// [ ] mouse-driven way to complete file/folder selection, or more generally +// query completion // [ ] display threads at their last exception address, rather than current // rip, if applicable // diff --git a/src/rdi_format/rdi_format.mdesk b/src/rdi_format/rdi_format.mdesk index e3e902b6..26f6e51e 100644 --- a/src/rdi_format/rdi_format.mdesk +++ b/src/rdi_format/rdi_format.mdesk @@ -1352,7 +1352,6 @@ RDI_NameMapKindTable: @table(name type desc) RDI_NameMapMemberTable: { - {kind RDI_NameMapKind ""} {bucket_base_idx RDI_U32 ""} {node_base_idx RDI_U32 ""} {bucket_count RDI_U32 ""} From 2c4c9e9d75a42bac83944c088bbbc8f0f9f11263 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 6 Jun 2024 16:50:02 -0700 Subject: [PATCH 14/44] rdi make: xfer over per-name-map building path --- src/lib_rdi_make/rdi_make.c | 99 +++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index 371b0707..17130e91 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -2190,6 +2190,105 @@ RDI_PROC RDIM_NameMapBakeResult rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *src, RDI_U64 base_node_idx) { RDIM_NameMapBakeResult result = {0}; + if(src->name_count != 0) + { + RDI_U32 baked_buckets_count = src->name_count; + RDI_U32 baked_nodes_count = src->name_count; + RDI_NameMapBucket *baked_buckets = rdim_push_array(arena, RDI_NameMapBucket, baked_buckets_count); + RDI_NameMapNode *baked_nodes = rdim_push_array_no_zero(arena, RDI_NameMapNode, baked_nodes_count); + { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + // rjf: setup the final bucket layouts + typedef struct RDIM_NameMapSemiNode RDIM_NameMapSemiNode; + struct RDIM_NameMapSemiNode + { + RDIM_NameMapSemiNode *next; + RDIM_BakeNameMapNode *node; + }; + typedef struct RDIM_NameMapSemiBucket RDIM_NameMapSemiBucket; + struct RDIM_NameMapSemiBucket + { + RDIM_NameMapSemiNode *first; + RDIM_NameMapSemiNode *last; + RDI_U64 count; + }; + RDIM_NameMapSemiBucket *sbuckets = rdim_push_array(scratch.arena, RDIM_NameMapSemiBucket, baked_buckets_count); + for(RDIM_BakeNameMapNode *node = src->first; + node != 0; + node = node->order_next) + { + RDI_U64 hash = rdi_hash(node->string.str, node->string.size); + RDI_U64 bi = hash%baked_buckets_count; + RDIM_NameMapSemiNode *snode = rdim_push_array(scratch.arena, RDIM_NameMapSemiNode, 1); + SLLQueuePush(sbuckets[bi].first, sbuckets[bi].last, snode); + snode->node = node; + sbuckets[bi].count += 1; + } + + // rjf: convert to serialized buckets & nodes + { + RDI_NameMapBucket *bucket_ptr = baked_buckets; + RDI_NameMapNode *node_ptr = baked_nodes; + for(RDI_U32 i = 0; i < baked_buckets_count; i += 1, bucket_ptr += 1) + { + bucket_ptr->first_node = (RDI_U32)(node_ptr - baked_nodes); + bucket_ptr->node_count = sbuckets[i].count; + for(RDIM_NameMapSemiNode *snode = sbuckets[i].first; + snode != 0; + snode = snode->next) + { + RDIM_BakeNameMapNode *node = snode->node; + + // rjf: cons name and index(es) + RDI_U32 string_idx = rdim_bake_idx_from_string(strings, node->string); + RDI_U32 match_count = node->val_count; + RDI_U32 idx = 0; + if(match_count == 1) + { + idx = node->val_first->val[0]; + } + else + { + RDI_U64 temp_pos = rdim_arena_pos(scratch.arena); + RDI_U32 *idx_run = rdim_push_array_no_zero(scratch.arena, RDI_U32, match_count); + RDI_U32 *idx_ptr = idx_run; + for(RDIM_BakeNameMapValNode *idxnode = node->val_first; + idxnode != 0; + idxnode = idxnode->next) + { + for(RDI_U32 i = 0; i < sizeof(idxnode->val)/sizeof(idxnode->val[0]); i += 1) + { + if(idxnode->val[i] == 0) + { + goto dblbreak; + } + *idx_ptr = idxnode->val[i]; + idx_ptr += 1; + } + } + dblbreak:; + idx = rdim_bake_idx_from_idx_run(idx_runs, idx_run, match_count); + rdim_arena_pop_to(scratch.arena, temp_pos); + } + + // rjf: write to node + node_ptr->string_idx = string_idx; + node_ptr->match_count = match_count; + node_ptr->match_idx_or_idx_run_first = idx; + node_ptr += 1; + } + } + } + rdim_scratch_end(scratch); + } + + // rjf: sections for buckets/nodes + result.buckets = baked_buckets; + result.buckets_count = baked_buckets_count; + result.nodes = baked_nodes; + result.nodes_count = baked_nodes_count; + } return result; } From d931aed462568fe37128466083b225568eaef7be Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 6 Jun 2024 17:13:44 -0700 Subject: [PATCH 15/44] checkpoint on new baking implementation --- src/lib_rdi_make/rdi_make.h | 16 ++++- src/rdi_from_pdb/rdi_from_pdb.c | 103 ++++++++++++++++---------------- src/rdi_from_pdb/rdi_from_pdb.h | 16 ++--- 3 files changed, 70 insertions(+), 65 deletions(-) diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index cb34676a..04e12a75 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -1219,6 +1219,15 @@ struct RDIM_IndexRunBakeResult RDI_U64 idx_count; }; +//////////////////////////////// +//~ rjf: Serializing Types + +typedef struct RDIM_SerializeParams RDIM_SerializeParams; +struct RDIM_SerializeParams +{ + RDIM_String8 section_data[RDI_SectionKind_COUNT]; +}; + //////////////////////////////// //~ rjf: Basic Helpers @@ -1256,8 +1265,9 @@ RDI_PROC RDIM_String8 rdim_str8_copy(RDIM_Arena *arena, RDIM_String8 src); RDI_PROC RDIM_String8 rdim_str8f(RDIM_Arena *arena, char *fmt, ...); RDI_PROC RDIM_String8 rdim_str8fv(RDIM_Arena *arena, char *fmt, va_list args); RDI_PROC RDI_S32 rdim_str8_match(RDIM_String8 a, RDIM_String8 b, RDIM_StringMatchFlags flags); -#define rdim_str8_lit(S) rdim_str8((RDI_U8*)(S), sizeof(S) - 1) -#define rdim_str8_struct(S) rdim_str8((RDI_U8*)(S), sizeof(*(S))) +#define rdim_str8_lit(S) rdim_str8((RDI_U8*)(S), sizeof(S) - 1) +#define rdim_str8_struct(S) rdim_str8((RDI_U8*)(S), sizeof(*(S))) +#define rdim_str8_struct_array(S, C) rdim_str8((RDI_U8*)(S), sizeof(*(S)) * (C)) //- rjf: string lists RDI_PROC void rdim_str8_list_push(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 string); @@ -1456,6 +1466,7 @@ RDI_PROC RDIM_IndexRunBakeResult rdim_bake_index_runs(RDIM_Arena *arena, //////////////////////////////// //~ rjf: [Baking] Build Artifacts -> Data Section Lists +#if 0 //- rjf: top-level info RDI_PROC RDIM_BakeSectionList rdim_bake_top_level_info_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); @@ -1510,6 +1521,7 @@ RDI_PROC RDIM_BakeSectionList rdim_bake_string_section_list_from_string_map(RDIM //- rjf: index runs RDI_PROC RDIM_BakeSectionList rdim_bake_idx_run_section_list_from_idx_run_map(RDIM_Arena *arena, RDIM_BakeIdxRunMap *idx_runs); +#endif //////////////////////////////// //~ rjf: [Serializing] Baked Data Section List -> Serialized Binary Strings diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index efa8a18e..d0c8afc4 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -3704,18 +3704,18 @@ internal TS_TASK_FUNCTION_DEF(p2r_build_bake_name_map_task__entry_point) internal TS_TASK_FUNCTION_DEF(p2r_bake_units_task__entry_point) { - P2R_BakeUnitsTopLevelIn *in = (P2R_BakeUnitsTopLevelIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake units") *s = rdim_bake_unit_section_list_from_params(arena, in->strings, in->path_tree, in->params); - return s; + P2R_BakeUnitsIn *in = (P2R_BakeUnitsIn *)p; + RDIM_UnitBakeResult *out = push_array(arena, RDIM_UnitBakeResult, 1); + ProfScope("bake units") *out = rdim_bake_units(arena, in->strings, in->path_tree, in->units); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_unit_vmap_task__entry_point) { P2R_BakeUnitVMapIn *in = (P2R_BakeUnitVMapIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake unit vmap") *s = rdim_bake_unit_vmap_section_list_from_params(arena, in->params); - return s; + RDIM_UnitVMapBakeResult *out = push_array(arena, RDIM_UnitVMapBakeResult, 1); + ProfScope("bake unit vmap") *out = rdim_bake_unit_vmap(arena, in->units); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_src_files_task__entry_point) @@ -3831,14 +3831,15 @@ internal P2R_Bake2Serialize * p2r_bake(Arena *arena, P2R_Convert2Bake *in) { Temp scratch = scratch_begin(&arena, 1); - RDIM_BakeParams *params = &in->bake_params; - RDIM_BakeSectionList sections = {0}; + RDIM_BakeParams *in_params = &in->bake_params; + P2R_Bake2Serialize *out = push_array(arena, P2R_Bake2Serialize, 1); + RDIM_SerializeParams *out_params = &out->serialize_params; //- rjf: kick off line tables baking TS_Ticket bake_line_tables_ticket = {0}; { P2R_BakeLineTablesIn *in = push_array(scratch.arena, P2R_BakeLineTablesIn, 1); - in->params = params; + in->params = in_params; bake_line_tables_ticket = ts_kickoff(p2r_bake_line_tables_task__entry_point, 0, in); } @@ -3846,14 +3847,14 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) RDIM_BakePathTree *path_tree = 0; ProfScope("build interned path tree") { - path_tree = rdim_bake_path_tree_from_params(arena, params); + path_tree = rdim_bake_path_tree_from_params(arena, in_params); } //- rjf: kick off string map building tasks - RDIM_BakeStringMapTopology bake_string_map_topology = {(params->procedures.total_count*1 + - params->global_variables.total_count*1 + - params->thread_variables.total_count*1 + - params->types.total_count/2)}; + RDIM_BakeStringMapTopology bake_string_map_topology = {(in_params->procedures.total_count*1 + + in_params->global_variables.total_count*1 + + in_params->thread_variables.total_count*1 + + in_params->types.total_count/2)}; RDIM_BakeStringMapLoose **bake_string_maps__in_progress = push_array(scratch.arena, RDIM_BakeStringMapLoose *, ts_thread_count()); TS_TicketList bake_string_map_build_tickets = {0}; { @@ -3863,7 +3864,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) P2R_BakeSrcFilesStringsIn *in = push_array(scratch.arena, P2R_BakeSrcFilesStringsIn, 1); in->top = &bake_string_map_topology; in->maps = bake_string_maps__in_progress; - in->list = ¶ms->src_files; + in->list = &in_params->src_files; ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_src_files_strings_task__entry_point, 0, in)); } @@ -3873,14 +3874,14 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) P2R_BakeUnitsStringsIn *in = push_array(scratch.arena, P2R_BakeUnitsStringsIn, 1); in->top = &bake_string_map_topology; in->maps = bake_string_maps__in_progress; - in->list = ¶ms->units; + in->list = &in_params->units; ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_units_strings_task__entry_point, 0, in)); } // rjf: types ProfScope("kick off types string map build tasks") { - for(RDIM_TypeChunkNode *chunk = params->types.first; chunk != 0; chunk = chunk->next) + for(RDIM_TypeChunkNode *chunk = in_params->types.first; chunk != 0; chunk = chunk->next) { U64 items_per_task = Min(4096, chunk->count); U64 tasks_per_this_chunk = (chunk->count+items_per_task-1)/items_per_task; @@ -3901,7 +3902,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) // rjf: UDTs ProfScope("kick off udts string map build tasks") { - for(RDIM_UDTChunkNode *chunk = params->udts.first; chunk != 0; chunk = chunk->next) + for(RDIM_UDTChunkNode *chunk = in_params->udts.first; chunk != 0; chunk = chunk->next) { U64 items_per_task = Min(4096, chunk->count); U64 tasks_per_this_chunk = (chunk->count+items_per_task-1)/items_per_task; @@ -3924,9 +3925,9 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) { RDIM_SymbolChunkList *symbol_lists[] = { - ¶ms->global_variables, - ¶ms->thread_variables, - ¶ms->procedures, + &in_params->global_variables, + &in_params->thread_variables, + &in_params->procedures, }; for(U64 list_idx = 0; list_idx < ArrayCount(symbol_lists); list_idx += 1) { @@ -3952,7 +3953,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) // rjf: scope chunks ProfScope("kick off scope chunks string map build tasks") { - for(RDIM_ScopeChunkNode *chunk = params->scopes.first; chunk != 0; chunk = chunk->next) + for(RDIM_ScopeChunkNode *chunk = in_params->scopes.first; chunk != 0; chunk = chunk->next) { U64 items_per_task = Min(4096, chunk->count); U64 tasks_per_this_chunk = (chunk->count+items_per_task-1)/items_per_task; @@ -3979,7 +3980,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) k = (RDI_NameMapKind)(k+1)) { build_bake_name_map_in[k].k = k; - build_bake_name_map_in[k].params = params; + build_bake_name_map_in[k].params = in_params; build_bake_name_map_ticket[k] = ts_kickoff(p2r_build_bake_name_map_task__entry_point, 0, &build_bake_name_map_in[k]); } @@ -4020,8 +4021,8 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) } // rjf: insert small top-level stuff - rdim_bake_string_map_loose_push_top_level_info(arena, &bake_string_map_topology, unsorted_bake_string_map, ¶ms->top_level_info); - rdim_bake_string_map_loose_push_binary_sections(arena, &bake_string_map_topology, unsorted_bake_string_map, ¶ms->binary_sections); + rdim_bake_string_map_loose_push_top_level_info(arena, &bake_string_map_topology, unsorted_bake_string_map, &in_params->top_level_info); + rdim_bake_string_map_loose_push_binary_sections(arena, &bake_string_map_topology, unsorted_bake_string_map, &in_params->binary_sections); rdim_bake_string_map_loose_push_path_tree(arena, &bake_string_map_topology, unsorted_bake_string_map, path_tree); } @@ -4068,25 +4069,25 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) ProfEnd(); //- rjf: kick off pass 2 tasks - P2R_BakeUnitsTopLevelIn bake_units_top_level_in = {&bake_strings, path_tree, params}; - TS_Ticket bake_units_top_level_ticket = ts_kickoff(p2r_bake_units_task__entry_point, 0, &bake_units_top_level_in); - P2R_BakeUnitVMapIn bake_unit_vmap_in = {params}; + P2R_BakeUnitsIn bake_units_top_level_in = {&bake_strings, path_tree, &in_params->units}; + TS_Ticket bake_units_ticket = ts_kickoff(p2r_bake_units_task__entry_point, 0, &bake_units_top_level_in); + P2R_BakeUnitVMapIn bake_unit_vmap_in = {&in_params->units}; TS_Ticket bake_unit_vmap_ticket = ts_kickoff(p2r_bake_unit_vmap_task__entry_point, 0, &bake_unit_vmap_in); - P2R_BakeSrcFilesIn bake_src_files_in = {&bake_strings, path_tree, params}; + P2R_BakeSrcFilesIn bake_src_files_in = {&bake_strings, path_tree, in_params}; TS_Ticket bake_src_files_ticket = ts_kickoff(p2r_bake_src_files_task__entry_point, 0, &bake_src_files_in); - P2R_BakeUDTsIn bake_udts_in = {&bake_strings, params}; + P2R_BakeUDTsIn bake_udts_in = {&bake_strings, in_params}; TS_Ticket bake_udts_ticket = ts_kickoff(p2r_bake_udts_task__entry_point, 0, &bake_udts_in); - P2R_BakeGlobalVariablesIn bake_global_variables_in = {&bake_strings, params}; + P2R_BakeGlobalVariablesIn bake_global_variables_in = {&bake_strings, in_params}; TS_Ticket bake_global_variables_ticket = ts_kickoff(p2r_bake_global_variables_task__entry_point, 0, &bake_global_variables_in); - P2R_BakeGlobalVMapIn bake_global_vmap_in = {params}; + P2R_BakeGlobalVMapIn bake_global_vmap_in = {in_params}; TS_Ticket bake_global_vmap_ticket = ts_kickoff(p2r_bake_global_vmap_task__entry_point, 0, &bake_global_vmap_in); - P2R_BakeThreadVariablesIn bake_thread_variables_in = {&bake_strings, params}; + P2R_BakeThreadVariablesIn bake_thread_variables_in = {&bake_strings, in_params}; TS_Ticket bake_thread_variables_ticket = ts_kickoff(p2r_bake_thread_variables_task__entry_point, 0, &bake_thread_variables_in); - P2R_BakeProceduresIn bake_procedures_in = {&bake_strings, params}; + P2R_BakeProceduresIn bake_procedures_in = {&bake_strings, in_params}; TS_Ticket bake_procedures_ticket = ts_kickoff(p2r_bake_procedures_task__entry_point, 0, &bake_procedures_in); - P2R_BakeScopesIn bake_scopes_in = {&bake_strings, params}; + P2R_BakeScopesIn bake_scopes_in = {&bake_strings, in_params}; TS_Ticket bake_scopes_ticket = ts_kickoff(p2r_bake_scopes_task__entry_point, 0, &bake_scopes_in); - P2R_BakeScopeVMapIn bake_scope_vmap_in = {params}; + P2R_BakeScopeVMapIn bake_scope_vmap_in = {in_params}; TS_Ticket bake_scope_vmap_ticket = ts_kickoff(p2r_bake_scope_vmap_task__entry_point, 0, &bake_scope_vmap_in); P2R_BakeFilePathsIn bake_file_paths_in = {&bake_strings, path_tree}; TS_Ticket bake_file_paths_ticket = ts_kickoff(p2r_bake_file_paths_task__entry_point, 0, &bake_file_paths_in); @@ -4096,15 +4097,15 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) //- rjf: top-level info ProfScope("top level info") { - RDIM_BakeSectionList s = rdim_bake_top_level_info_section_list_from_params(arena, &bake_strings, params); - rdim_bake_section_list_concat_in_place(§ions, &s); + RDIM_TopLevelInfoBakeResult bake = rdim_bake_top_level_info(arena, &bake_strings, &in_params->top_level_info); + out_params->section_data[RDI_SectionKind_TopLevelInfo] = rdim_str8_struct(bake.top_level_info); } //- rjf: binary sections ProfScope("binary sections") { - RDIM_BakeSectionList s = rdim_bake_binary_section_section_list_from_params(arena, &bake_strings, params); - rdim_bake_section_list_concat_in_place(§ions, &s); + RDIM_BinarySectionBakeResult bake = rdim_bake_binary_sections(arena, &bake_strings, &in_params->binary_sections); + out_params->section_data[RDI_SectionKind_BinarySections] = rdim_str8_struct_array(bake.binary_sections, bake.binary_sections_count); } //- rjf: join name map building tasks @@ -4123,11 +4124,11 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) RDIM_BakeIdxRunMap *idx_runs = 0; ProfScope("build interned idx run map") { - idx_runs = rdim_bake_idx_run_map_from_params(arena, name_maps, params); + idx_runs = rdim_bake_idx_run_map_from_params(arena, name_maps, in_params); } //- rjf: kick off pass 3 tasks - P2R_BakeTypeNodesIn bake_type_nodes_in = {&bake_strings, idx_runs, params}; + P2R_BakeTypeNodesIn bake_type_nodes_in = {&bake_strings, idx_runs, in_params}; TS_Ticket bake_type_nodes_ticket = ts_kickoff(p2r_bake_type_nodes_task__entry_point, 0, &bake_type_nodes_in); TS_TicketList bake_name_maps_tickets = {0}; for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); @@ -4141,7 +4142,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) P2R_BakeNameMapIn *in = push_array(scratch.arena, P2R_BakeNameMapIn, 1); in->strings = &bake_strings; in->idx_runs = idx_runs; - in->params = params; + in->params = in_params; in->kind = k; in->map = name_maps[k]; ts_ticket_list_push(scratch.arena, &bake_name_maps_tickets, ts_kickoff(p2r_bake_name_map_task__entry_point, 0, in)); @@ -4152,22 +4153,22 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) //- rjf: bake top-level name maps section ProfScope("top level name maps section") { - RDIM_BakeSectionList s = rdim_bake_top_level_name_map_section_list_from_params_maps(arena, &bake_strings, idx_runs, params, name_maps); - rdim_bake_section_list_concat_in_place(§ions, &s); + RDIM_TopLevelNameMapBakeResult bake = rdim_bake_name_maps_top_level(arena, &bake_strings, idx_runs, name_maps); + out_params->section_data[RDI_SectionKind_NameMaps] = rdim_str8_struct_array(bake.name_maps, bake.name_maps_count); } //- rjf: join top-level units info ProfScope("top-level units info") { - RDIM_BakeSectionList *s = ts_join_struct(bake_units_top_level_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); + RDIM_UnitBakeResult *bake = ts_join_struct(bake_units_ticket, max_U64, RDIM_UnitBakeResult); + out_params->section_data[RDI_SectionKind_Units] = rdim_str8_struct_array(bake->units, bake->units_count); } //- rjf: join unit vmap ProfScope("unit vmap") { - RDIM_BakeSectionList *s = ts_join_struct(bake_unit_vmap_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); + RDIM_UnitVMapBakeResult *bake = ts_join_struct(bake_unit_vmap_ticket, max_U64, RDIM_UnitVMapBakeResult); + out_params->section_data[RDI_SectionKind_UnitVMap] = rdim_str8_struct_array(bake->vmap.vmap, bake->vmap.count+1); } //- rjf: join source files @@ -4272,8 +4273,6 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) } //- rjf: fill & return - P2R_Bake2Serialize *out = push_array(arena, P2R_Bake2Serialize, 1); - out->sections = sections; scratch_end(scratch); return out; } diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index a16bce83..e0e40a7d 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -55,7 +55,7 @@ struct P2R_Convert2Bake typedef struct P2R_Bake2Serialize P2R_Bake2Serialize; struct P2R_Bake2Serialize { - RDIM_BakeSectionList sections; + RDIM_SerializeParams serialize_params; }; //////////////////////////////// @@ -400,24 +400,18 @@ struct P2R_BuildBakeNameMapIn //- rjf: debug info baking task types -typedef struct P2R_BakeUnitsTopLevelIn P2R_BakeUnitsTopLevelIn; -struct P2R_BakeUnitsTopLevelIn +typedef struct P2R_BakeUnitsIn P2R_BakeUnitsIn; +struct P2R_BakeUnitsIn { RDIM_BakeStringMapTight *strings; RDIM_BakePathTree *path_tree; - RDIM_BakeParams *params; -}; - -typedef struct P2R_BakeUnitIn P2R_BakeUnitIn; -struct P2R_BakeUnitIn -{ - RDIM_Unit *unit; + RDIM_UnitChunkList *units; }; typedef struct P2R_BakeUnitVMapIn P2R_BakeUnitVMapIn; struct P2R_BakeUnitVMapIn { - RDIM_BakeParams *params; + RDIM_UnitChunkList *units; }; typedef struct P2R_BakeSrcFilesIn P2R_BakeSrcFilesIn; From 431884dce8b483383589f042ee2c6cc535d89970 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 7 Jun 2024 11:03:00 -0700 Subject: [PATCH 16/44] rdi_make, rdi_from_pdb: complete next pass over new serialization/compression interface, including for new top-level-only name map data sections; eliminate determinism issues from string map build (task dispatch was busted) --- project.4coder | 2 +- src/lib_rdi_make/rdi_make.c | 147 ++++++ src/lib_rdi_make/rdi_make.h | 59 ++- src/raddbg/raddbg_main.c | 17 +- .../rdi_breakpad_from_pdb_main.c | 26 +- src/rdi_dump/rdi_dump_main.c | 5 +- src/rdi_from_pdb/rdi_from_pdb.c | 489 ++++++++---------- src/rdi_from_pdb/rdi_from_pdb.h | 34 +- src/rdi_from_pdb/rdi_from_pdb_main.c | 17 +- 9 files changed, 483 insertions(+), 313 deletions(-) diff --git a/project.4coder b/project.4coder index 5c0032f8..28e00d14 100644 --- a/project.4coder +++ b/project.4coder @@ -56,7 +56,7 @@ commands = }, .rjf_f2 = { - .win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main.rdi && rdi_dump mule_main.rdi > mule_main.dump && popd", + .win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main_1.rdi && rdi_dump --only:strings mule_main_1.rdi > mule_main_1.dump && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main_2.rdi && rdi_dump --only:strings mule_main_2.rdi > mule_main_2.dump && diff mule_main_1.dump mule_main_2.dump && popd", .linux = "", .out = "*compilation*", .footer_panel = true, diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index 17130e91..4e507fd2 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -2292,6 +2292,44 @@ rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_Bak return result; } +//- rjf: partial bakes -> final bake functions + +RDI_PROC RDIM_NameMapBakeResult +rdim_name_map_bake_results_combine(RDIM_Arena *arena, RDIM_NameMapBakeResult *results, RDI_U64 results_count) +{ + RDIM_NameMapBakeResult result = {0}; + { + //- rjf: count needed # of buckets/nodes + RDI_U64 all_buckets_count = 0; + RDI_U64 all_nodes_count = 0; + for(RDI_U64 idx = 0; idx < results_count; idx += 1) + { + all_buckets_count += results[idx].buckets_count; + all_nodes_count += results[idx].nodes_count; + } + + //- rjf: allocate outputs + result.buckets_count = all_buckets_count; + result.buckets = rdim_push_array_no_zero(arena, RDI_NameMapBucket, result.buckets_count); + result.nodes_count = all_nodes_count; + result.nodes = rdim_push_array_no_zero(arena, RDI_NameMapNode, result.nodes_count); + + //- rjf: fill outputs + { + RDI_U64 buckets_off = 0; + RDI_U64 nodes_off = 0; + for(RDI_U64 idx = 0; idx < results_count; idx += 1) + { + rdim_memcpy(result.buckets + buckets_off, results[idx].buckets, sizeof(result.buckets[0])*results[idx].buckets_count); + rdim_memcpy(result.nodes + nodes_off, results[idx].nodes, sizeof(result.nodes[0])*results[idx].nodes_count); + buckets_off += results[idx].buckets_count; + nodes_off += results[idx].nodes_count; + } + } + } + return result; +} + //- rjf: independent (top-level, global) baking functions RDI_PROC RDIM_TopLevelInfoBakeResult @@ -3515,9 +3553,114 @@ rdim_bake_index_runs(RDIM_Arena *arena, RDIM_BakeIdxRunMap *idx_runs) return result; } +//////////////////////////////// +//~ rjf: [Serializing] Bake Results -> String Blobs + +RDI_PROC RDIM_SerializedSection +rdim_serialized_section_make_unpacked(void *data, RDI_U64 size) +{ + RDIM_SerializedSection s; + rdim_memzero_struct(&s); + s.data = data; + s.encoded_size = s.unpacked_size = size; + s.encoding = RDI_SectionEncoding_Unpacked; + return s; +} + +RDI_PROC RDIM_SerializedSectionBundle +rdim_serialized_section_bundle_from_bake_results(RDIM_BakeResults *results) +{ + RDIM_SerializedSectionBundle bundle; + rdim_memzero_struct(&bundle); + bundle.sections[RDI_SectionKind_TopLevelInfo] = rdim_serialized_section_make_unpacked_struct(results->top_level_info.top_level_info); + bundle.sections[RDI_SectionKind_StringData] = rdim_serialized_section_make_unpacked_array(results->strings.string_data, results->strings.string_data_size); + bundle.sections[RDI_SectionKind_StringTable] = rdim_serialized_section_make_unpacked_array(results->strings.string_offs, results->strings.string_offs_count); + bundle.sections[RDI_SectionKind_IndexRuns] = rdim_serialized_section_make_unpacked_array(results->idx_runs.idx_runs, results->idx_runs.idx_count); + bundle.sections[RDI_SectionKind_BinarySections] = rdim_serialized_section_make_unpacked_array(results->binary_sections.binary_sections, results->binary_sections.binary_sections_count); + bundle.sections[RDI_SectionKind_FilePathNodes] = rdim_serialized_section_make_unpacked_array(results->file_paths.nodes, results->file_paths.nodes_count); + bundle.sections[RDI_SectionKind_SourceFiles] = rdim_serialized_section_make_unpacked_array(results->src_files.source_files, results->src_files.source_files_count); + bundle.sections[RDI_SectionKind_LineTables] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_tables, results->line_tables.line_tables_count); + bundle.sections[RDI_SectionKind_LineInfoVOffs] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_table_voffs, results->line_tables.line_table_voffs_count); + bundle.sections[RDI_SectionKind_LineInfoLines] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_table_lines, results->line_tables.line_table_lines_count); + bundle.sections[RDI_SectionKind_LineInfoColumns] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_table_columns, results->line_tables.line_table_columns_count); + bundle.sections[RDI_SectionKind_SourceLineMaps] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_maps, results->src_files.source_line_maps_count); + bundle.sections[RDI_SectionKind_SourceLineMapNumbers] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_map_nums, results->src_files.source_line_map_nums_count); + bundle.sections[RDI_SectionKind_SourceLineMapRanges] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_map_rngs, results->src_files.source_line_map_rngs_count); + bundle.sections[RDI_SectionKind_SourceLineMapVOffs] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_map_voffs, results->src_files.source_line_map_voffs_count); + bundle.sections[RDI_SectionKind_Units] = rdim_serialized_section_make_unpacked_array(results->units.units, results->units.units_count); + bundle.sections[RDI_SectionKind_UnitVMap] = rdim_serialized_section_make_unpacked_array(results->unit_vmap.vmap.vmap, results->unit_vmap.vmap.count+1); + bundle.sections[RDI_SectionKind_TypeNodes] = rdim_serialized_section_make_unpacked_array(results->type_nodes.type_nodes, results->type_nodes.type_nodes_count); + bundle.sections[RDI_SectionKind_UDTs] = rdim_serialized_section_make_unpacked_array(results->udts.udts, results->udts.udts_count); + bundle.sections[RDI_SectionKind_Members] = rdim_serialized_section_make_unpacked_array(results->udts.members, results->udts.members_count); + bundle.sections[RDI_SectionKind_EnumMembers] = rdim_serialized_section_make_unpacked_array(results->udts.enum_members, results->udts.enum_members_count); + bundle.sections[RDI_SectionKind_GlobalVariables] = rdim_serialized_section_make_unpacked_array(results->global_variables.global_variables, results->global_variables.global_variables_count); + bundle.sections[RDI_SectionKind_GlobalVMap] = rdim_serialized_section_make_unpacked_array(results->global_vmap.vmap.vmap, results->global_vmap.vmap.count+1); + bundle.sections[RDI_SectionKind_ThreadVariables] = rdim_serialized_section_make_unpacked_array(results->thread_variables.thread_variables, results->thread_variables.thread_variables_count); + bundle.sections[RDI_SectionKind_Procedures] = rdim_serialized_section_make_unpacked_array(results->procedures.procedures, results->procedures.procedures_count); + bundle.sections[RDI_SectionKind_Scopes] = rdim_serialized_section_make_unpacked_array(results->scopes.scopes, results->scopes.scopes_count); + bundle.sections[RDI_SectionKind_ScopeVOffData] = rdim_serialized_section_make_unpacked_array(results->scopes.scope_voffs, results->scopes.scope_voffs_count); + bundle.sections[RDI_SectionKind_ScopeVMap] = rdim_serialized_section_make_unpacked_array(results->scope_vmap.vmap.vmap, results->scope_vmap.vmap.count+1); + bundle.sections[RDI_SectionKind_InlineSites] = rdim_serialized_section_make_unpacked(0, 0); + bundle.sections[RDI_SectionKind_Locals] = rdim_serialized_section_make_unpacked_array(results->scopes.locals, results->scopes.locals_count); + bundle.sections[RDI_SectionKind_LocationBlocks] = rdim_serialized_section_make_unpacked_array(results->scopes.location_blocks, results->scopes.location_blocks_count); + bundle.sections[RDI_SectionKind_LocationData] = rdim_serialized_section_make_unpacked_array(results->scopes.location_data, results->scopes.location_data_size); + bundle.sections[RDI_SectionKind_NameMaps] = rdim_serialized_section_make_unpacked_array(results->top_level_name_maps.name_maps, results->top_level_name_maps.name_maps_count); + bundle.sections[RDI_SectionKind_NameMapBuckets] = rdim_serialized_section_make_unpacked_array(results->name_maps.buckets, results->name_maps.buckets_count); + bundle.sections[RDI_SectionKind_NameMapNodes] = rdim_serialized_section_make_unpacked_array(results->name_maps.nodes, results->name_maps.nodes_count); + return bundle; +} + +RDI_PROC RDIM_String8List +rdim_file_blobs_from_section_bundle(RDIM_Arena *arena, RDIM_SerializedSectionBundle *bundle) +{ + RDIM_String8List strings; + rdim_memzero_struct(&strings); + { + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); + + // rjf: push empty header & data section table + RDI_Header *rdi_header = rdim_push_array(arena, RDI_Header, 1); + RDI_Section *rdi_sections = rdim_push_array(arena, RDI_Section, RDI_SectionKind_COUNT); + rdim_str8_list_push(arena, &strings, rdim_str8_struct(rdi_header)); + rdim_str8_list_push_align(arena, &strings, 8); + U32 data_section_off = (U32)strings.total_size; + rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)rdi_sections, sizeof(RDI_Section)*RDI_SectionKind_COUNT)); + + // rjf: fill baked header + { + rdi_header->magic = RDI_MAGIC_CONSTANT; + rdi_header->encoding_version = RDI_ENCODING_VERSION; + rdi_header->data_section_off = data_section_off; + rdi_header->data_section_count = RDI_SectionKind_COUNT; + } + + // rjf: fill baked data section table + for(RDI_SectionKind k = RDI_SectionKind_NULL; k < RDI_SectionKind_COUNT; k += 1) + { + RDI_Section *dst = rdi_sections+k; + U64 data_section_off = 0; + if(bundle->sections[k].encoded_size != 0) + { + rdim_str8_list_push_align(arena, &strings, 8); + data_section_off = strings.total_size; + rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)bundle->sections[k].data, bundle->sections[k].encoded_size)); + } + dst->encoding = bundle->sections[k].encoding; + dst->off = data_section_off; + dst->encoded_size = bundle->sections[k].encoded_size; + dst->unpacked_size = bundle->sections[k].unpacked_size; + } + + rdim_scratch_end(scratch); + } + return strings; +} + //////////////////////////////// //~ rjf: [Baking] Build Artifacts -> Data Section Lists +#if 0 + //- rjf: top-level info RDI_PROC RDIM_BakeSectionList @@ -4876,9 +5019,12 @@ rdim_bake_idx_run_section_list_from_idx_run_map(RDIM_Arena *arena, RDIM_BakeIdxR return sections; } +#endif + //////////////////////////////// //~ rjf: [Serializing] Baked Data Section List -> Serialized Binary Strings +#if 0 RDI_PROC RDIM_String8List rdim_serialized_strings_from_params_bake_section_list(RDIM_Arena *arena, RDIM_BakeParams *params, RDIM_BakeSectionList *sections) { @@ -4947,3 +5093,4 @@ rdim_serialized_strings_from_params_bake_section_list(RDIM_Arena *arena, RDIM_Ba } return strings; } +#endif diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index 04e12a75..328a9793 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -1219,13 +1219,46 @@ struct RDIM_IndexRunBakeResult RDI_U64 idx_count; }; -//////////////////////////////// -//~ rjf: Serializing Types - -typedef struct RDIM_SerializeParams RDIM_SerializeParams; -struct RDIM_SerializeParams +typedef struct RDIM_BakeResults RDIM_BakeResults; +struct RDIM_BakeResults { - RDIM_String8 section_data[RDI_SectionKind_COUNT]; + RDIM_TopLevelInfoBakeResult top_level_info; + RDIM_BinarySectionBakeResult binary_sections; + RDIM_UnitBakeResult units; + RDIM_UnitVMapBakeResult unit_vmap; + RDIM_SrcFileBakeResult src_files; + RDIM_LineTableBakeResult line_tables; + RDIM_TypeNodeBakeResult type_nodes; + RDIM_UDTBakeResult udts; + RDIM_GlobalVariableBakeResult global_variables; + RDIM_GlobalVMapBakeResult global_vmap; + RDIM_ThreadVariableBakeResult thread_variables; + RDIM_ProcedureBakeResult procedures; + RDIM_ScopeBakeResult scopes; + RDIM_ScopeVMapBakeResult scope_vmap; + RDIM_TopLevelNameMapBakeResult top_level_name_maps; + RDIM_NameMapBakeResult name_maps; + RDIM_FilePathBakeResult file_paths; + RDIM_StringBakeResult strings; + RDIM_IndexRunBakeResult idx_runs; +}; + +//////////////////////////////// +//~ rjf: Serialization Types + +typedef struct RDIM_SerializedSection RDIM_SerializedSection; +struct RDIM_SerializedSection +{ + void *data; + RDI_U64 encoded_size; + RDI_U64 unpacked_size; + RDI_SectionEncoding encoding; +}; + +typedef struct RDIM_SerializedSectionBundle RDIM_SerializedSectionBundle; +struct RDIM_SerializedSectionBundle +{ + RDIM_SerializedSection sections[RDI_SectionKind_COUNT]; }; //////////////////////////////// @@ -1443,6 +1476,9 @@ RDI_PROC RDIM_BakePathTree *rdim_bake_path_tree_from_params(RDIM_Arena *arena, R //- rjf: partial/joinable baking functions RDI_PROC RDIM_NameMapBakeResult rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *src, RDI_U64 base_node_idx); +//- rjf: partial bakes -> final bake functions +RDI_PROC RDIM_NameMapBakeResult rdim_name_map_bake_results_combine(RDIM_Arena *arena, RDIM_NameMapBakeResult *results, RDI_U64 results_count); + //- rjf: independent (top-level, global) baking functions RDI_PROC RDIM_TopLevelInfoBakeResult rdim_bake_top_level_info(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_TopLevelInfo *src); RDI_PROC RDIM_BinarySectionBakeResult rdim_bake_binary_sections(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BinarySectionList *src); @@ -1463,6 +1499,15 @@ RDI_PROC RDIM_FilePathBakeResult rdim_bake_file_paths(RDIM_Arena *arena, RDI_PROC RDIM_StringBakeResult rdim_bake_strings(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings); RDI_PROC RDIM_IndexRunBakeResult rdim_bake_index_runs(RDIM_Arena *arena, RDIM_BakeIdxRunMap *idx_runs); +//////////////////////////////// +//~ rjf: [Serializing] Bake Results -> String Blobs + +RDI_PROC RDIM_SerializedSection rdim_serialized_section_make_unpacked(void *data, RDI_U64 size); +#define rdim_serialized_section_make_unpacked_struct(ptr) rdim_serialized_section_make_unpacked((ptr), sizeof(*(ptr))) +#define rdim_serialized_section_make_unpacked_array(ptr, count) rdim_serialized_section_make_unpacked((ptr), sizeof(*(ptr))*(count)) +RDI_PROC RDIM_SerializedSectionBundle rdim_serialized_section_bundle_from_bake_results(RDIM_BakeResults *results); +RDI_PROC RDIM_String8List rdim_file_blobs_from_section_bundle(RDIM_Arena *arena, RDIM_SerializedSectionBundle *bundle); + //////////////////////////////// //~ rjf: [Baking] Build Artifacts -> Data Section Lists @@ -1526,6 +1571,8 @@ RDI_PROC RDIM_BakeSectionList rdim_bake_idx_run_section_list_from_idx_run_map(RD //////////////////////////////// //~ rjf: [Serializing] Baked Data Section List -> Serialized Binary Strings +#if 0 RDI_PROC RDIM_String8List rdim_serialized_strings_from_params_bake_section_list(RDIM_Arena *arena, RDIM_BakeParams *params, RDIM_BakeSectionList *sections); +#endif #endif // RDI_MAKE_H diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index d9892de7..9db07fce 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -515,21 +515,30 @@ entry_point(CmdLine *cmd_line) bake2srlz = p2r_bake(scratch.arena, convert2bake); } + //- rjf: serialize + P2R_Serialize2File *srlz2file = 0; + ProfScope("serialize") + { + srlz2file = push_array(scratch.arena, P2R_Serialize2File, 1); + srlz2file->bundle = rdim_serialized_section_bundle_from_bake_results(&bake2srlz->bake_results); + } + //- rjf: compress - P2R_Bake2Serialize *bake2srlz_compressed = bake2srlz; + P2R_Serialize2File *srlz2file_compressed = srlz2file; if(cmd_line_has_flag(cmd_line, str8_lit("compress"))) ProfScope("compress") { - bake2srlz_compressed = p2r_compress(scratch.arena, bake2srlz); + srlz2file_compressed = push_array(scratch.arena, P2R_Serialize2File, 1); + srlz2file_compressed = p2r_compress(scratch.arena, srlz2file); } //- rjf: serialize - String8List serialize_out = rdim_serialized_strings_from_params_bake_section_list(scratch.arena, &convert2bake->bake_params, &bake2srlz_compressed->sections); + String8List blobs = rdim_file_blobs_from_section_bundle(scratch.arena, &srlz2file_compressed->bundle); //- rjf: write if(out_file_is_good) { U64 off = 0; - for(String8Node *n = serialize_out.first; n != 0; n = n->next) + for(String8Node *n = blobs.first; n != 0; n = n->next) { os_file_write(out_file, r1u64(off, off+n->string.size), n->string.str); off += n->string.size; diff --git a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c index 8a125b47..b1578399 100644 --- a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c +++ b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c @@ -26,7 +26,7 @@ #include "base/base_inc.h" #include "os/os_inc.h" #include "task_system/task_system.h" -#include "rdi_make_local/rdi_make_local.h" +#include "rdi_make/rdi_make_local.h" #include "coff/coff.h" #include "codeview/codeview.h" #include "codeview/codeview_stringize.h" @@ -39,7 +39,7 @@ #include "base/base_inc.c" #include "os/os_inc.c" #include "task_system/task_system.c" -#include "rdi_make_local/rdi_make_local.c" +#include "rdi_make/rdi_make_local.c" #include "coff/coff.c" #include "codeview/codeview.c" #include "codeview/codeview_stringize.c" @@ -56,7 +56,7 @@ typedef struct P2B_BakeUnitVMapIn P2B_BakeUnitVMapIn; struct P2B_BakeUnitVMapIn { - RDIM_BakeParams *params; + RDIM_UnitChunkList *units; }; typedef struct P2B_BakeUnitVMapOut P2B_BakeUnitVMapOut; @@ -70,21 +70,9 @@ internal TS_TASK_FUNCTION_DEF(p2b_bake_unit_vmap_task__entry_point) { P2B_BakeUnitVMapIn *in = (P2B_BakeUnitVMapIn *)p; P2B_BakeUnitVMapOut *out = push_array(arena, P2B_BakeUnitVMapOut, 1); - RDIM_BakeSectionList sections = rdim_bake_unit_vmap_section_list_from_params(arena, in->params); - RDIM_BakeSection *vmap_section = 0; - for(RDIM_BakeSectionNode *n = sections.first; n != 0 && vmap_section == 0; n = n->next) - { - switch(n->v.tag) - { - default:{}break; - case RDI_SectionKind_UnitVmap:{vmap_section = &n->v;}break; - } - } - if(vmap_section != 0) - { - out->vmap_entries = (RDI_VMapEntry *)vmap_section->data; - out->vmap_entries_count = vmap_section->unpacked_size/sizeof(RDI_VMapEntry); - } + RDIM_UnitVMapBakeResult bake = rdim_bake_unit_vmap(arena, in->units); + out->vmap_entries = bake.vmap.vmap; + out->vmap_entries_count = bake.vmap.count+1; return out; } @@ -251,7 +239,7 @@ entry_point(CmdLine *cmdline) P2B_BakeUnitVMapIn bake_unit_vmap_in = {params}; TS_Ticket bake_unit_vmap_ticket = ts_kickoff(p2b_bake_unit_vmap_task__entry_point, 0, &bake_unit_vmap_in); - //- rjf: kick off per-unit baking + //- rjf: kick off per-line-table baking P2B_BakeUnitIn *bake_units_in = push_array(arena, P2B_BakeUnitIn, params->units.total_count+1); TS_Ticket *bake_units_tickets = push_array(arena, TS_Ticket, params->units.total_count+1); { diff --git a/src/rdi_dump/rdi_dump_main.c b/src/rdi_dump/rdi_dump_main.c index 3e26bdb6..3aa06373 100644 --- a/src/rdi_dump/rdi_dump_main.c +++ b/src/rdi_dump/rdi_dump_main.c @@ -74,9 +74,9 @@ entry_point(CmdLine *cmd_line) // rjf: extract input file path input_name = str8_list_first(&cmd_line->inputs); - // rjf: extract dump options + // rjf: extract "only" options { - String8List dump_options = cmd_line_strings(cmd_line, str8_lit("dump")); + String8List dump_options = cmd_line_strings(cmd_line, str8_lit("only")); if(dump_options.first != 0) { dump_flags = 0; @@ -101,6 +101,7 @@ entry_point(CmdLine *cmd_line) 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; } + else if(str8_match(n->string, str8_lit("strings"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_Strings; } } } } diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index d0c8afc4..41591105 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -3628,9 +3628,9 @@ internal TS_TASK_FUNCTION_DEF(p2r_bake_scopes_strings_task__entry_point) internal TS_TASK_FUNCTION_DEF(p2r_bake_line_tables_task__entry_point) { P2R_BakeLineTablesIn *in = (P2R_BakeLineTablesIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake line tables") *s = rdim_bake_line_table_section_list_from_params(arena, in->params); - return s; + RDIM_LineTableBakeResult *out = push_array(arena, RDIM_LineTableBakeResult, 1); + ProfScope("bake line tables") *out = rdim_bake_line_tables(arena, in->line_tables); + return out; } #undef p2r_make_string_map_if_needed @@ -3721,81 +3721,81 @@ internal TS_TASK_FUNCTION_DEF(p2r_bake_unit_vmap_task__entry_point) internal TS_TASK_FUNCTION_DEF(p2r_bake_src_files_task__entry_point) { P2R_BakeSrcFilesIn *in = (P2R_BakeSrcFilesIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake src files") *s = rdim_bake_src_file_section_list_from_params(arena, in->strings, in->path_tree, in->params); - return s; + RDIM_SrcFileBakeResult *out = push_array(arena, RDIM_SrcFileBakeResult, 1); + ProfScope("bake src files") *out = rdim_bake_src_files(arena, in->strings, in->path_tree, in->src_files); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_udts_task__entry_point) { P2R_BakeUDTsIn *in = (P2R_BakeUDTsIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake udts") *s = rdim_bake_udt_section_list_from_params(arena, in->strings, in->params); - return s; + RDIM_UDTBakeResult *out = push_array(arena, RDIM_UDTBakeResult, 1); + ProfScope("bake udts") *out = rdim_bake_udts(arena, in->strings, in->udts); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_global_variables_task__entry_point) { P2R_BakeGlobalVariablesIn *in = (P2R_BakeGlobalVariablesIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake global variables") *s = rdim_bake_global_variable_section_list_from_params(arena, in->strings, in->params); - return s; + RDIM_GlobalVariableBakeResult *out = push_array(arena, RDIM_GlobalVariableBakeResult, 1); + ProfScope("bake global variables") *out = rdim_bake_global_variables(arena, in->strings, in->global_variables); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_global_vmap_task__entry_point) { P2R_BakeGlobalVMapIn *in = (P2R_BakeGlobalVMapIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake global vmap") *s = rdim_bake_global_vmap_section_list_from_params(arena, in->params); - return s; + RDIM_GlobalVMapBakeResult *out = push_array(arena, RDIM_GlobalVMapBakeResult, 1); + ProfScope("bake global vmap") *out = rdim_bake_global_vmap(arena, in->global_variables); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_thread_variables_task__entry_point) { P2R_BakeThreadVariablesIn *in = (P2R_BakeThreadVariablesIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake thread variables") *s = rdim_bake_thread_variable_section_list_from_params(arena, in->strings, in->params); - return s; + RDIM_ThreadVariableBakeResult *out = push_array(arena, RDIM_ThreadVariableBakeResult, 1); + ProfScope("bake thread variables") *out = rdim_bake_thread_variables(arena, in->strings, in->thread_variables); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_procedures_task__entry_point) { P2R_BakeProceduresIn *in = (P2R_BakeProceduresIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake procedures") *s = rdim_bake_procedure_section_list_from_params(arena, in->strings, in->params); - return s; + RDIM_ProcedureBakeResult *out = push_array(arena, RDIM_ProcedureBakeResult, 1); + ProfScope("bake procedures") *out = rdim_bake_procedures(arena, in->strings, in->procedures); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_scopes_task__entry_point) { P2R_BakeScopesIn *in = (P2R_BakeScopesIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake scopes") *s = rdim_bake_scope_section_list_from_params(arena, in->strings, in->params); - return s; + RDIM_ScopeBakeResult *out = push_array(arena, RDIM_ScopeBakeResult, 1); + ProfScope("bake scopes") *out = rdim_bake_scopes(arena, in->strings, in->scopes); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_scope_vmap_task__entry_point) { P2R_BakeScopeVMapIn *in = (P2R_BakeScopeVMapIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake scope vmap") *s = rdim_bake_scope_vmap_section_list_from_params(arena, in->params); - return s; + RDIM_ScopeVMapBakeResult *out = push_array(arena, RDIM_ScopeVMapBakeResult, 1); + ProfScope("bake scope vmap") *out = rdim_bake_scope_vmap(arena, in->scopes); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_file_paths_task__entry_point) { P2R_BakeFilePathsIn *in = (P2R_BakeFilePathsIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake file paths") *s = rdim_bake_file_path_section_list_from_path_tree(arena, in->strings, in->path_tree); - return s; + RDIM_FilePathBakeResult *out = push_array(arena, RDIM_FilePathBakeResult, 1); + ProfScope("bake file paths") *out = rdim_bake_file_paths(arena, in->strings, in->path_tree); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_strings_task__entry_point) { P2R_BakeStringsIn *in = (P2R_BakeStringsIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake strings") *s = rdim_bake_string_section_list_from_string_map(arena, in->strings); - return s; + RDIM_StringBakeResult *out = push_array(arena, RDIM_StringBakeResult, 1); + ProfScope("bake strings") *out = rdim_bake_strings(arena, in->strings); + return out; } //- rjf: pass 3: idx-run-map-dependent debug info stream builds @@ -3803,25 +3803,25 @@ internal TS_TASK_FUNCTION_DEF(p2r_bake_strings_task__entry_point) internal TS_TASK_FUNCTION_DEF(p2r_bake_type_nodes_task__entry_point) { P2R_BakeTypeNodesIn *in = (P2R_BakeTypeNodesIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake type nodes") *s = rdim_bake_type_node_section_list_from_params(arena, in->strings, in->idx_runs, in->params); - return s; + RDIM_TypeNodeBakeResult *out = push_array(arena, RDIM_TypeNodeBakeResult, 1); + ProfScope("bake type nodes") *out = rdim_bake_types(arena, in->strings, in->idx_runs, in->types); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_name_map_task__entry_point) { P2R_BakeNameMapIn *in = (P2R_BakeNameMapIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake name map %i", in->kind) *s = rdim_bake_name_map_section_list_from_params_kind_map(arena, in->strings, in->idx_runs, in->params, in->kind, in->map); - return s; + RDIM_NameMapBakeResult *out = push_array(arena, RDIM_NameMapBakeResult, 1); + ProfScope("bake name map %i", in->kind) *out = rdim_bake_name_map(arena, in->strings, in->idx_runs, in->map, in->base_node_idx); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_idx_runs_task__entry_point) { P2R_BakeIdxRunsIn *in = (P2R_BakeIdxRunsIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake idx runs") *s = rdim_bake_idx_run_section_list_from_idx_run_map(arena, in->idx_runs); - return s; + RDIM_IndexRunBakeResult *out = push_array(arena, RDIM_IndexRunBakeResult, 1); + ProfScope("bake idx runs") *out = rdim_bake_index_runs(arena, in->idx_runs); + return out; } //////////////////////////////// @@ -3833,24 +3833,30 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) Temp scratch = scratch_begin(&arena, 1); RDIM_BakeParams *in_params = &in->bake_params; P2R_Bake2Serialize *out = push_array(arena, P2R_Bake2Serialize, 1); - RDIM_SerializeParams *out_params = &out->serialize_params; + RDIM_BakeResults *out_results = &out->bake_results; + ////////////////////////////// //- rjf: kick off line tables baking + // TS_Ticket bake_line_tables_ticket = {0}; { P2R_BakeLineTablesIn *in = push_array(scratch.arena, P2R_BakeLineTablesIn, 1); - in->params = in_params; + in->line_tables = &in_params->line_tables; bake_line_tables_ticket = ts_kickoff(p2r_bake_line_tables_task__entry_point, 0, in); } + ////////////////////////////// //- rjf: build interned path tree + // RDIM_BakePathTree *path_tree = 0; ProfScope("build interned path tree") { path_tree = rdim_bake_path_tree_from_params(arena, in_params); } + ////////////////////////////// //- rjf: kick off string map building tasks + // RDIM_BakeStringMapTopology bake_string_map_topology = {(in_params->procedures.total_count*1 + in_params->global_variables.total_count*1 + in_params->thread_variables.total_count*1 + @@ -3881,42 +3887,64 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) // rjf: types ProfScope("kick off types string map build tasks") { - for(RDIM_TypeChunkNode *chunk = in_params->types.first; chunk != 0; chunk = chunk->next) + U64 items_per_task = 4096; + U64 num_tasks = (in_params->types.total_count+items_per_task-1)/items_per_task; + RDIM_TypeChunkNode *chunk = in_params->types.first; + U64 chunk_off = 0; + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) { - U64 items_per_task = Min(4096, chunk->count); - U64 tasks_per_this_chunk = (chunk->count+items_per_task-1)/items_per_task; - for(U64 task_idx = 0; task_idx < tasks_per_this_chunk; task_idx += 1) + P2R_BakeTypesStringsIn *in = push_array(scratch.arena, P2R_BakeTypesStringsIn, 1); + in->top = &bake_string_map_topology; + in->maps = bake_string_maps__in_progress; + U64 items_left = items_per_task; + for(;chunk != 0 && items_left > 0;) { - P2R_BakeTypesStringsIn *in = push_array(scratch.arena, P2R_BakeTypesStringsIn, 1); - in->top = &bake_string_map_topology; - in->maps = bake_string_maps__in_progress; + U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); P2R_BakeTypesStringsInNode *n = push_array(scratch.arena, P2R_BakeTypesStringsInNode, 1); SLLQueuePush(in->first, in->last, n); - n->v = chunk->v + task_idx*items_per_task; - n->count = Min(items_per_task, chunk->count - task_idx*items_per_task); - ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_types_strings_task__entry_point, 0, in)); + n->v = chunk->v + chunk_off; + n->count = items_in_this_chunk; + chunk_off += items_in_this_chunk; + items_left -= items_in_this_chunk; + if(chunk_off >= chunk->count) + { + chunk = chunk->next; + chunk_off = 0; + } } + ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_types_strings_task__entry_point, 0, in)); } } // rjf: UDTs ProfScope("kick off udts string map build tasks") { - for(RDIM_UDTChunkNode *chunk = in_params->udts.first; chunk != 0; chunk = chunk->next) + U64 items_per_task = 4096; + U64 num_tasks = (in_params->udts.total_count+items_per_task-1)/items_per_task; + RDIM_UDTChunkNode *chunk = in_params->udts.first; + U64 chunk_off = 0; + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) { - U64 items_per_task = Min(4096, chunk->count); - U64 tasks_per_this_chunk = (chunk->count+items_per_task-1)/items_per_task; - for(U64 task_idx = 0; task_idx < tasks_per_this_chunk; task_idx += 1) + P2R_BakeUDTsStringsIn *in = push_array(scratch.arena, P2R_BakeUDTsStringsIn, 1); + in->top = &bake_string_map_topology; + in->maps = bake_string_maps__in_progress; + U64 items_left = items_per_task; + for(;chunk != 0 && items_left > 0;) { - P2R_BakeUDTsStringsIn *in = push_array(scratch.arena, P2R_BakeUDTsStringsIn, 1); - in->top = &bake_string_map_topology; - in->maps = bake_string_maps__in_progress; + U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); P2R_BakeUDTsStringsInNode *n = push_array(scratch.arena, P2R_BakeUDTsStringsInNode, 1); SLLQueuePush(in->first, in->last, n); - n->v = chunk->v + task_idx*items_per_task; - n->count = Min(items_per_task, chunk->count - task_idx*items_per_task); - ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_udts_strings_task__entry_point, 0, in)); + n->v = chunk->v + chunk_off; + n->count = items_in_this_chunk; + chunk_off += items_in_this_chunk; + items_left -= items_in_this_chunk; + if(chunk_off >= chunk->count) + { + chunk = chunk->next; + chunk_off = 0; + } } + ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_udts_strings_task__entry_point, 0, in)); } } @@ -3931,21 +3959,32 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) }; for(U64 list_idx = 0; list_idx < ArrayCount(symbol_lists); list_idx += 1) { - for(RDIM_SymbolChunkNode *chunk = symbol_lists[list_idx]->first; chunk != 0; chunk = chunk->next) + U64 items_per_task = 4096; + U64 num_tasks = (symbol_lists[list_idx]->total_count+items_per_task-1)/items_per_task; + RDIM_SymbolChunkNode *chunk = symbol_lists[list_idx]->first; + U64 chunk_off = 0; + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) { - U64 items_per_task = Min(4096, chunk->count); - U64 tasks_per_this_chunk = (chunk->count+items_per_task-1)/items_per_task; - for(U64 task_idx = 0; task_idx < tasks_per_this_chunk; task_idx += 1) + P2R_BakeSymbolsStringsIn *in = push_array(scratch.arena, P2R_BakeSymbolsStringsIn, 1); + in->top = &bake_string_map_topology; + in->maps = bake_string_maps__in_progress; + U64 items_left = items_per_task; + for(;chunk != 0 && items_left > 0;) { - P2R_BakeSymbolsStringsIn *in = push_array(scratch.arena, P2R_BakeSymbolsStringsIn, 1); - in->top = &bake_string_map_topology; - in->maps = bake_string_maps__in_progress; + U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); P2R_BakeSymbolsStringsInNode *n = push_array(scratch.arena, P2R_BakeSymbolsStringsInNode, 1); SLLQueuePush(in->first, in->last, n); - n->v = chunk->v + task_idx*items_per_task; - n->count = Min(items_per_task, chunk->count - task_idx*items_per_task); - ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_symbols_strings_task__entry_point, 0, in)); + n->v = chunk->v + chunk_off; + n->count = items_in_this_chunk; + chunk_off += items_in_this_chunk; + items_left -= items_in_this_chunk; + if(chunk_off >= chunk->count) + { + chunk = chunk->next; + chunk_off = 0; + } } + ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_symbols_strings_task__entry_point, 0, in)); } } } @@ -3953,26 +3992,39 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) // rjf: scope chunks ProfScope("kick off scope chunks string map build tasks") { - for(RDIM_ScopeChunkNode *chunk = in_params->scopes.first; chunk != 0; chunk = chunk->next) + U64 items_per_task = 4096; + U64 num_tasks = (in_params->scopes.total_count+items_per_task-1)/items_per_task; + RDIM_ScopeChunkNode *chunk = in_params->scopes.first; + U64 chunk_off = 0; + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) { - U64 items_per_task = Min(4096, chunk->count); - U64 tasks_per_this_chunk = (chunk->count+items_per_task-1)/items_per_task; - for(U64 task_idx = 0; task_idx < tasks_per_this_chunk; task_idx += 1) + P2R_BakeScopesStringsIn *in = push_array(scratch.arena, P2R_BakeScopesStringsIn, 1); + in->top = &bake_string_map_topology; + in->maps = bake_string_maps__in_progress; + U64 items_left = items_per_task; + for(;chunk != 0 && items_left > 0;) { - P2R_BakeScopesStringsIn *in = push_array(scratch.arena, P2R_BakeScopesStringsIn, 1); - in->top = &bake_string_map_topology; - in->maps = bake_string_maps__in_progress; + U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); P2R_BakeScopesStringsInNode *n = push_array(scratch.arena, P2R_BakeScopesStringsInNode, 1); SLLQueuePush(in->first, in->last, n); - n->v = chunk->v + task_idx*items_per_task; - n->count = Min(items_per_task, chunk->count - task_idx*items_per_task); - ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_scopes_strings_task__entry_point, 0, in)); + n->v = chunk->v + chunk_off; + n->count = items_in_this_chunk; + chunk_off += items_in_this_chunk; + items_left -= items_in_this_chunk; + if(chunk_off >= chunk->count) + { + chunk = chunk->next; + chunk_off = 0; + } } + ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_scopes_strings_task__entry_point, 0, in)); } } } + ////////////////////////////// //- rjf: kick off name map building tasks + // P2R_BuildBakeNameMapIn build_bake_name_map_in[RDI_NameMapKind_COUNT] = {0}; TS_Ticket build_bake_name_map_ticket[RDI_NameMapKind_COUNT] = {0}; for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); @@ -3984,7 +4036,9 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) build_bake_name_map_ticket[k] = ts_kickoff(p2r_build_bake_name_map_task__entry_point, 0, &build_bake_name_map_in[k]); } + ////////////////////////////// //- rjf: join string map building tasks + // ProfScope("join string map building tasks") { for(TS_TicketNode *n = bake_string_map_build_tickets.first; n != 0; n = n->next) @@ -3993,7 +4047,9 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) } } + ////////////////////////////// //- rjf: produce joined string map + // RDIM_BakeStringMapLoose *unsorted_bake_string_map = rdim_bake_string_map_loose_make(arena, &bake_string_map_topology); ProfScope("produce joined string map") { @@ -4026,7 +4082,9 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) rdim_bake_string_map_loose_push_path_tree(arena, &bake_string_map_topology, unsorted_bake_string_map, path_tree); } + ////////////////////////////// //- rjf: kick off string map sorting tasks + // TS_TicketList sort_bake_string_map_task_tickets = {0}; RDIM_BakeStringMapLoose *sorted_bake_string_map__in_progress = rdim_bake_string_map_loose_make(arena, &bake_string_map_topology); { @@ -4050,7 +4108,9 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) } } + ////////////////////////////// //- rjf: join string map sorting tasks + // ProfScope("join string map sorting tasks") { for(TS_TicketNode *n = sort_bake_string_map_task_tickets.first; n != 0; n = n->next) @@ -4060,7 +4120,9 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) } RDIM_BakeStringMapLoose *sorted_bake_string_map = sorted_bake_string_map__in_progress; + ////////////////////////////// //- rjf: build finalized string map + // ProfBegin("build finalized string map base indices"); RDIM_BakeStringMapBaseIndices bake_string_map_base_idxes = rdim_bake_string_map_base_indices_from_map_loose(arena, &bake_string_map_topology, sorted_bake_string_map); ProfEnd(); @@ -4068,47 +4130,37 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) RDIM_BakeStringMapTight bake_strings = rdim_bake_string_map_tight_from_loose(arena, &bake_string_map_topology, &bake_string_map_base_idxes, sorted_bake_string_map); ProfEnd(); + ////////////////////////////// //- rjf: kick off pass 2 tasks + // P2R_BakeUnitsIn bake_units_top_level_in = {&bake_strings, path_tree, &in_params->units}; TS_Ticket bake_units_ticket = ts_kickoff(p2r_bake_units_task__entry_point, 0, &bake_units_top_level_in); P2R_BakeUnitVMapIn bake_unit_vmap_in = {&in_params->units}; TS_Ticket bake_unit_vmap_ticket = ts_kickoff(p2r_bake_unit_vmap_task__entry_point, 0, &bake_unit_vmap_in); - P2R_BakeSrcFilesIn bake_src_files_in = {&bake_strings, path_tree, in_params}; + P2R_BakeSrcFilesIn bake_src_files_in = {&bake_strings, path_tree, &in_params->src_files}; TS_Ticket bake_src_files_ticket = ts_kickoff(p2r_bake_src_files_task__entry_point, 0, &bake_src_files_in); - P2R_BakeUDTsIn bake_udts_in = {&bake_strings, in_params}; + P2R_BakeUDTsIn bake_udts_in = {&bake_strings, &in_params->udts}; TS_Ticket bake_udts_ticket = ts_kickoff(p2r_bake_udts_task__entry_point, 0, &bake_udts_in); - P2R_BakeGlobalVariablesIn bake_global_variables_in = {&bake_strings, in_params}; + P2R_BakeGlobalVariablesIn bake_global_variables_in = {&bake_strings, &in_params->global_variables}; TS_Ticket bake_global_variables_ticket = ts_kickoff(p2r_bake_global_variables_task__entry_point, 0, &bake_global_variables_in); - P2R_BakeGlobalVMapIn bake_global_vmap_in = {in_params}; + P2R_BakeGlobalVMapIn bake_global_vmap_in = {&in_params->global_variables}; TS_Ticket bake_global_vmap_ticket = ts_kickoff(p2r_bake_global_vmap_task__entry_point, 0, &bake_global_vmap_in); - P2R_BakeThreadVariablesIn bake_thread_variables_in = {&bake_strings, in_params}; + P2R_BakeThreadVariablesIn bake_thread_variables_in = {&bake_strings, &in_params->thread_variables}; TS_Ticket bake_thread_variables_ticket = ts_kickoff(p2r_bake_thread_variables_task__entry_point, 0, &bake_thread_variables_in); - P2R_BakeProceduresIn bake_procedures_in = {&bake_strings, in_params}; + P2R_BakeProceduresIn bake_procedures_in = {&bake_strings, &in_params->procedures}; TS_Ticket bake_procedures_ticket = ts_kickoff(p2r_bake_procedures_task__entry_point, 0, &bake_procedures_in); - P2R_BakeScopesIn bake_scopes_in = {&bake_strings, in_params}; + P2R_BakeScopesIn bake_scopes_in = {&bake_strings, &in_params->scopes}; TS_Ticket bake_scopes_ticket = ts_kickoff(p2r_bake_scopes_task__entry_point, 0, &bake_scopes_in); - P2R_BakeScopeVMapIn bake_scope_vmap_in = {in_params}; + P2R_BakeScopeVMapIn bake_scope_vmap_in = {&in_params->scopes}; TS_Ticket bake_scope_vmap_ticket = ts_kickoff(p2r_bake_scope_vmap_task__entry_point, 0, &bake_scope_vmap_in); P2R_BakeFilePathsIn bake_file_paths_in = {&bake_strings, path_tree}; TS_Ticket bake_file_paths_ticket = ts_kickoff(p2r_bake_file_paths_task__entry_point, 0, &bake_file_paths_in); P2R_BakeStringsIn bake_strings_in = {&bake_strings}; TS_Ticket bake_strings_ticket = ts_kickoff(p2r_bake_strings_task__entry_point, 0, &bake_strings_in); - //- rjf: top-level info - ProfScope("top level info") - { - RDIM_TopLevelInfoBakeResult bake = rdim_bake_top_level_info(arena, &bake_strings, &in_params->top_level_info); - out_params->section_data[RDI_SectionKind_TopLevelInfo] = rdim_str8_struct(bake.top_level_info); - } - - //- rjf: binary sections - ProfScope("binary sections") - { - RDIM_BinarySectionBakeResult bake = rdim_bake_binary_sections(arena, &bake_strings, &in_params->binary_sections); - out_params->section_data[RDI_SectionKind_BinarySections] = rdim_str8_struct_array(bake.binary_sections, bake.binary_sections_count); - } - + ////////////////////////////// //- rjf: join name map building tasks + // RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT] = {0}; ProfScope("join name map building tasks") { @@ -4120,159 +4172,88 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) } } + ////////////////////////////// //- rjf: build interned idx run map + // RDIM_BakeIdxRunMap *idx_runs = 0; ProfScope("build interned idx run map") { idx_runs = rdim_bake_idx_run_map_from_params(arena, name_maps, in_params); } + ////////////////////////////// + //- rjf: do small top-level bakes + // + ProfScope("top level info") out_results->top_level_info = rdim_bake_top_level_info(arena, &bake_strings, &in_params->top_level_info); + ProfScope("binary sections") out_results->binary_sections = rdim_bake_binary_sections(arena, &bake_strings, &in_params->binary_sections); + ProfScope("top level name maps section") out_results->top_level_name_maps = rdim_bake_name_maps_top_level(arena, &bake_strings, idx_runs, name_maps); + + ////////////////////////////// //- rjf: kick off pass 3 tasks - P2R_BakeTypeNodesIn bake_type_nodes_in = {&bake_strings, idx_runs, in_params}; + // + P2R_BakeTypeNodesIn bake_type_nodes_in = {&bake_strings, idx_runs, &in_params->types}; TS_Ticket bake_type_nodes_ticket = ts_kickoff(p2r_bake_type_nodes_task__entry_point, 0, &bake_type_nodes_in); - TS_TicketList bake_name_maps_tickets = {0}; - for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); - k < RDI_NameMapKind_COUNT; - k = (RDI_NameMapKind)(k+1)) + TS_Ticket bake_name_maps_tickets[RDI_NameMapKind_COUNT] = {0}; { - if(name_maps[k] == 0 || name_maps[k]->name_count == 0) + U64 base_node_idx = 0; + for(EachNonZeroEnumVal(RDI_NameMapKind, k)) { - continue; + if(name_maps[k] == 0 || name_maps[k]->name_count == 0) + { + continue; + } + P2R_BakeNameMapIn *in = push_array(scratch.arena, P2R_BakeNameMapIn, 1); + in->strings = &bake_strings; + in->idx_runs = idx_runs; + in->map = name_maps[k]; + in->base_node_idx = base_node_idx; + in->kind = k; + bake_name_maps_tickets[k] = ts_kickoff(p2r_bake_name_map_task__entry_point, 0, in); + base_node_idx += name_maps[k]->name_count; } - P2R_BakeNameMapIn *in = push_array(scratch.arena, P2R_BakeNameMapIn, 1); - in->strings = &bake_strings; - in->idx_runs = idx_runs; - in->params = in_params; - in->kind = k; - in->map = name_maps[k]; - ts_ticket_list_push(scratch.arena, &bake_name_maps_tickets, ts_kickoff(p2r_bake_name_map_task__entry_point, 0, in)); } P2R_BakeIdxRunsIn bake_idx_runs_in = {idx_runs}; TS_Ticket bake_idx_runs_ticket = ts_kickoff(p2r_bake_idx_runs_task__entry_point, 0, &bake_idx_runs_in); - //- rjf: bake top-level name maps section - ProfScope("top level name maps section") - { - RDIM_TopLevelNameMapBakeResult bake = rdim_bake_name_maps_top_level(arena, &bake_strings, idx_runs, name_maps); - out_params->section_data[RDI_SectionKind_NameMaps] = rdim_str8_struct_array(bake.name_maps, bake.name_maps_count); - } + ////////////////////////////// + //- rjf: join remaining completed bakes + // + ProfScope("top-level units info") out_results->units = *ts_join_struct(bake_units_ticket, max_U64, RDIM_UnitBakeResult); + ProfScope("unit vmap") out_results->unit_vmap = *ts_join_struct(bake_unit_vmap_ticket, max_U64, RDIM_UnitVMapBakeResult); + ProfScope("source files") out_results->src_files = *ts_join_struct(bake_src_files_ticket, max_U64, RDIM_SrcFileBakeResult); + ProfScope("UDTs") out_results->udts = *ts_join_struct(bake_udts_ticket, max_U64, RDIM_UDTBakeResult); + ProfScope("global variables") out_results->global_variables = *ts_join_struct(bake_global_variables_ticket, max_U64, RDIM_GlobalVariableBakeResult); + ProfScope("global vmap") out_results->global_vmap = *ts_join_struct(bake_global_vmap_ticket, max_U64, RDIM_GlobalVMapBakeResult); + ProfScope("thread variables") out_results->thread_variables = *ts_join_struct(bake_thread_variables_ticket, max_U64, RDIM_ThreadVariableBakeResult); + ProfScope("procedures") out_results->procedures = *ts_join_struct(bake_procedures_ticket, max_U64, RDIM_ProcedureBakeResult); + ProfScope("scopes") out_results->scopes = *ts_join_struct(bake_scopes_ticket, max_U64, RDIM_ScopeBakeResult); + ProfScope("scope vmap") out_results->scope_vmap = *ts_join_struct(bake_scope_vmap_ticket, max_U64, RDIM_ScopeVMapBakeResult); + ProfScope("file paths") out_results->file_paths = *ts_join_struct(bake_file_paths_ticket, max_U64, RDIM_FilePathBakeResult); + ProfScope("strings") out_results->strings = *ts_join_struct(bake_strings_ticket, max_U64, RDIM_StringBakeResult); + ProfScope("type nodes") out_results->type_nodes = *ts_join_struct(bake_type_nodes_ticket, max_U64, RDIM_TypeNodeBakeResult); + ProfScope("idx runs") out_results->idx_runs = *ts_join_struct(bake_idx_runs_ticket, max_U64, RDIM_IndexRunBakeResult); + ProfScope("line tables") out_results->line_tables = *ts_join_struct(bake_line_tables_ticket, max_U64, RDIM_LineTableBakeResult); - //- rjf: join top-level units info - ProfScope("top-level units info") + ////////////////////////////// + //- rjf: join individual name map bakes + // + RDIM_NameMapBakeResult name_map_bakes[RDI_NameMapKind_COUNT] = {0}; + ProfScope("name maps") { - RDIM_UnitBakeResult *bake = ts_join_struct(bake_units_ticket, max_U64, RDIM_UnitBakeResult); - out_params->section_data[RDI_SectionKind_Units] = rdim_str8_struct_array(bake->units, bake->units_count); - } - - //- rjf: join unit vmap - ProfScope("unit vmap") - { - RDIM_UnitVMapBakeResult *bake = ts_join_struct(bake_unit_vmap_ticket, max_U64, RDIM_UnitVMapBakeResult); - out_params->section_data[RDI_SectionKind_UnitVMap] = rdim_str8_struct_array(bake->vmap.vmap, bake->vmap.count+1); - } - - //- rjf: join source files - ProfScope("source files") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_src_files_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join UDTs - ProfScope("UDTs") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_udts_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join global variables - ProfScope("global variables") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_global_variables_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join global vmap - ProfScope("global vmap") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_global_vmap_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join thread variables - ProfScope("thread variables") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_thread_variables_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join procedures - ProfScope("procedures") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_procedures_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join scopes - ProfScope("scopes") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_scopes_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join scope vmap - ProfScope("scope vmap") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_scope_vmap_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join file paths - ProfScope("file paths") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_file_paths_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join strings - ProfScope("strings") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_strings_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join type nodes - ProfScope("type nodes") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_type_nodes_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join name maps - ProfScope("name map") - { - for(TS_TicketNode *n = bake_name_maps_tickets.first; n != 0; n = n->next) + for(EachNonZeroEnumVal(RDI_NameMapKind, k)) { - RDIM_BakeSectionList *s = ts_join_struct(n->v, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); + name_map_bakes[k] = *ts_join_struct(bake_name_maps_tickets[k], max_U64, RDIM_NameMapBakeResult); } } - //- rjf: join index runs - ProfScope("idx runs") + ////////////////////////////// + //- rjf: join all individual name map bakes + // + ProfScope("join all name map bakes into final name map bake") { - RDIM_BakeSectionList *s = ts_join_struct(bake_idx_runs_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); + out_results->name_maps = rdim_name_map_bake_results_combine(arena, name_map_bakes, ArrayCount(name_map_bakes)); } - //- rjf: join line tables - ProfScope("line tables") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_line_tables_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: fill & return scratch_end(scratch); return out; } @@ -4280,11 +4261,10 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) //////////////////////////////// //~ rjf: Top-Level Compression Entry Point -internal P2R_Bake2Serialize * -p2r_compress(Arena *arena, P2R_Bake2Serialize *in) +internal P2R_Serialize2File * +p2r_compress(Arena *arena, P2R_Serialize2File *in) { - RDIM_BakeSectionList prepack_sections = in->sections; - RDIM_BakeSectionList postpack_sections = {0}; + P2R_Serialize2File *out = push_array(arena, P2R_Serialize2File, 1); { //- rjf: set up compression context rr_lzb_simple_context ctx = {0}; @@ -4292,18 +4272,11 @@ p2r_compress(Arena *arena, P2R_Bake2Serialize *in) ctx.m_hashTable = push_array(arena, U16, 1<next) + for(EachEnumVal(RDI_SectionKind, k)) { - RDIM_BakeSection *src = &src_n->v; - - // rjf: push new section - RDIM_BakeSection *dst = rdim_bake_section_list_push(arena, &postpack_sections); - - // rjf: unpack uncompressed section info - void *data = src->data; - RDI_SectionEncoding encoding = src->encoding; - RDI_U64 encoded_size = src->encoded_size; - RDI_U64 unpacked_size = src->unpacked_size; + RDIM_SerializedSection *src = &in->bundle.sections[k]; + RDIM_SerializedSection *dst = &out->bundle.sections[k]; + MemoryCopyStruct(dst, src); // rjf: determine if this section should be compressed B32 should_compress = 1; @@ -4312,22 +4285,12 @@ p2r_compress(Arena *arena, P2R_Bake2Serialize *in) if(should_compress) { MemoryZero(ctx.m_hashTable, sizeof(U16)*(1<data = push_array_no_zero(arena, U8, src->encoded_size); + dst->encoded_size = rr_lzb_simple_encode_veryfast(&ctx, src->data, src->encoded_size, dst->data); + dst->unpacked_size = src->encoded_size; + dst->encoding = RDI_SectionEncoding_LZB; } - - // rjf: fill - dst->data = data; - dst->encoding = encoding; - dst->encoded_size = encoded_size; - dst->unpacked_size = unpacked_size; - dst->tag = src->tag; - dst->tag_idx = src->tag_idx; } } - P2R_Bake2Serialize *out = push_array(arena, P2R_Bake2Serialize, 1); - out->sections = postpack_sections; return out; } diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index e0e40a7d..bcbf6cd3 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -55,7 +55,13 @@ struct P2R_Convert2Bake typedef struct P2R_Bake2Serialize P2R_Bake2Serialize; struct P2R_Bake2Serialize { - RDIM_SerializeParams serialize_params; + RDIM_BakeResults bake_results; +}; + +typedef struct P2R_Serialize2File P2R_Serialize2File; +struct P2R_Serialize2File +{ + RDIM_SerializedSectionBundle bundle; }; //////////////////////////////// @@ -269,7 +275,7 @@ struct P2R_SymbolStreamConvertOut typedef struct P2R_BakeLineTablesIn P2R_BakeLineTablesIn; struct P2R_BakeLineTablesIn { - RDIM_BakeParams *params; + RDIM_LineTableChunkList *line_tables; }; //- rjf: string map baking task types @@ -419,54 +425,54 @@ struct P2R_BakeSrcFilesIn { RDIM_BakeStringMapTight *strings; RDIM_BakePathTree *path_tree; - RDIM_BakeParams *params; + RDIM_SrcFileChunkList *src_files; }; typedef struct P2R_BakeUDTsIn P2R_BakeUDTsIn; struct P2R_BakeUDTsIn { RDIM_BakeStringMapTight *strings; - RDIM_BakeParams *params; + RDIM_UDTChunkList *udts; }; typedef struct P2R_BakeGlobalVariablesIn P2R_BakeGlobalVariablesIn; struct P2R_BakeGlobalVariablesIn { RDIM_BakeStringMapTight *strings; - RDIM_BakeParams *params; + RDIM_SymbolChunkList *global_variables; }; typedef struct P2R_BakeGlobalVMapIn P2R_BakeGlobalVMapIn; struct P2R_BakeGlobalVMapIn { - RDIM_BakeParams *params; + RDIM_SymbolChunkList *global_variables; }; typedef struct P2R_BakeThreadVariablesIn P2R_BakeThreadVariablesIn; struct P2R_BakeThreadVariablesIn { RDIM_BakeStringMapTight *strings; - RDIM_BakeParams *params; + RDIM_SymbolChunkList *thread_variables; }; typedef struct P2R_BakeProceduresIn P2R_BakeProceduresIn; struct P2R_BakeProceduresIn { RDIM_BakeStringMapTight *strings; - RDIM_BakeParams *params; + RDIM_SymbolChunkList *procedures; }; typedef struct P2R_BakeScopesIn P2R_BakeScopesIn; struct P2R_BakeScopesIn { RDIM_BakeStringMapTight *strings; - RDIM_BakeParams *params; + RDIM_ScopeChunkList *scopes; }; typedef struct P2R_BakeScopeVMapIn P2R_BakeScopeVMapIn; struct P2R_BakeScopeVMapIn { - RDIM_BakeParams *params; + RDIM_ScopeChunkList *scopes; }; typedef struct P2R_BakeFilePathsIn P2R_BakeFilePathsIn; @@ -487,7 +493,7 @@ struct P2R_BakeTypeNodesIn { RDIM_BakeStringMapTight *strings; RDIM_BakeIdxRunMap *idx_runs; - RDIM_BakeParams *params; + RDIM_TypeChunkList *types; }; typedef struct P2R_BakeNameMapIn P2R_BakeNameMapIn; @@ -495,9 +501,9 @@ struct P2R_BakeNameMapIn { RDIM_BakeStringMapTight *strings; RDIM_BakeIdxRunMap *idx_runs; - RDIM_BakeParams *params; - RDI_NameMapKind kind; RDIM_BakeNameMap *map; + U64 base_node_idx; + RDI_NameMapKind kind; }; typedef struct P2R_BakeIdxRunsIn P2R_BakeIdxRunsIn; @@ -628,6 +634,6 @@ internal P2R_Bake2Serialize *p2r_bake(Arena *arena, P2R_Convert2Bake *in); //////////////////////////////// //~ rjf: Top-Level Compression Entry Point -internal P2R_Bake2Serialize *p2r_compress(Arena *arena, P2R_Bake2Serialize *in); +internal P2R_Serialize2File *p2r_compress(Arena *arena, P2R_Serialize2File *in); #endif // RDI_FROM_PDB_H diff --git a/src/rdi_from_pdb/rdi_from_pdb_main.c b/src/rdi_from_pdb/rdi_from_pdb_main.c index e3c72c9a..50fd0a88 100644 --- a/src/rdi_from_pdb/rdi_from_pdb_main.c +++ b/src/rdi_from_pdb/rdi_from_pdb_main.c @@ -98,22 +98,31 @@ entry_point(CmdLine *cmdline) bake2srlz = p2r_bake(arena, convert2bake); } + //- rjf: serialize + P2R_Serialize2File *srlz2file = 0; + ProfScope("serialize") + { + srlz2file = push_array(arena, P2R_Serialize2File, 1); + srlz2file->bundle = rdim_serialized_section_bundle_from_bake_results(&bake2srlz->bake_results); + } + //- rjf: compress - P2R_Bake2Serialize *bake2srlz_compressed = bake2srlz; + P2R_Serialize2File *srlz2file_compressed = srlz2file; if(cmd_line_has_flag(cmdline, str8_lit("compress"))) ProfScope("compress") { - bake2srlz_compressed = p2r_compress(arena, bake2srlz); + srlz2file_compressed = push_array(arena, P2R_Serialize2File, 1); + srlz2file_compressed = p2r_compress(arena, srlz2file); } //- rjf: serialize - String8List serialize_out = rdim_serialized_strings_from_params_bake_section_list(arena, &convert2bake->bake_params, &bake2srlz_compressed->sections); + String8List blobs = rdim_file_blobs_from_section_bundle(arena, &srlz2file_compressed->bundle); //- rjf: write ProfScope("write") { OS_Handle output_file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Write, user2convert->output_name); U64 off = 0; - for(String8Node *n = serialize_out.first; n != 0; n = n->next) + for(String8Node *n = blobs.first; n != 0; n = n->next) { os_file_write(output_file, r1u64(off, off+n->string.size), n->string.str); off += n->string.size; From b48fcea28a0115a6d6dc14c00903f0689a092ee6 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 7 Jun 2024 11:07:58 -0700 Subject: [PATCH 17/44] fix fuzzy search layer for new table extraction code --- project.4coder | 2 +- src/fuzzy_search/fuzzy_search.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/project.4coder b/project.4coder index 28e00d14..c1283b5d 100644 --- a/project.4coder +++ b/project.4coder @@ -56,7 +56,7 @@ commands = }, .rjf_f2 = { - .win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main_1.rdi && rdi_dump --only:strings mule_main_1.rdi > mule_main_1.dump && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main_2.rdi && rdi_dump --only:strings mule_main_2.rdi > mule_main_2.dump && diff mule_main_1.dump mule_main_2.dump && popd", + .win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main_1.rdi && rdi_dump mule_main_1.rdi > mule_main_1.dump && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main_2.rdi && rdi_dump mule_main_2.rdi > mule_main_2.dump && diff mule_main_1.dump mule_main_2.dump && popd", .linux = "", .out = "*compilation*", .footer_panel = true, diff --git a/src/fuzzy_search/fuzzy_search.c b/src/fuzzy_search/fuzzy_search.c index 49f2bbe9..7744e2f0 100644 --- a/src/fuzzy_search/fuzzy_search.c +++ b/src/fuzzy_search/fuzzy_search.c @@ -452,7 +452,7 @@ fzy_search_thread__entry_point(void *p) U64 element_size = rdi_section_element_size_table[section_kind]; for(U64 idx = 1; task_is_good && idx < element_count; idx += 1) { - void *element = (U8 *)(*(void **)table_base) + element_size*idx; + void *element = (U8 *)table_base + element_size*idx; U32 *name_idx_ptr = (U32 *)((U8 *)element + element_name_idx_off); if(params.target == FZY_Target_UDTs) { From 8f03fb0cc565af2613dd28db43b080f7a7b35562 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 7 Jun 2024 11:17:11 -0700 Subject: [PATCH 18/44] eliminate base node idx from per-node info; nodes can be stored all relative to their name map's base indices, and this is naturally applied on lookup, no need to bake it in --- src/lib_rdi_make/rdi_make.c | 8 +++----- src/lib_rdi_make/rdi_make.h | 2 +- src/rdi_from_pdb/rdi_from_pdb.c | 5 +---- src/rdi_from_pdb/rdi_from_pdb.h | 1 - 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index 4e507fd2..b8dee044 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -2187,7 +2187,7 @@ rdim_bake_path_tree_from_params(RDIM_Arena *arena, RDIM_BakeParams *params) //- rjf: partial/joinable baking functions RDI_PROC RDIM_NameMapBakeResult -rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *src, RDI_U64 base_node_idx) +rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *src) { RDIM_NameMapBakeResult result = {0}; if(src->name_count != 0) @@ -2232,7 +2232,7 @@ rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_Bak RDI_NameMapNode *node_ptr = baked_nodes; for(RDI_U32 i = 0; i < baked_buckets_count; i += 1, bucket_ptr += 1) { - bucket_ptr->first_node = (RDI_U32)(node_ptr - baked_nodes); + bucket_ptr->first_node = (RDI_U32)((RDI_U64)(node_ptr - baked_nodes)); bucket_ptr->node_count = sbuckets[i].count; for(RDIM_NameMapSemiNode *snode = sbuckets[i].first; snode != 0; @@ -3426,20 +3426,18 @@ rdim_bake_name_maps_top_level(RDIM_Arena *arena, RDIM_BakeStringMapTight *string { RDI_NameMap *dst_maps = rdim_push_array(arena, RDI_NameMap, RDI_NameMapKind_COUNT); { - RDI_U64 dst_map_idx = 0; RDI_U64 dst_map_bucket_idx = 0; RDI_U64 dst_map_node_idx = 0; for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); k < RDI_NameMapKind_COUNT; k = (RDI_NameMapKind)(k+1)) { - RDI_NameMap *dst_map = &dst_maps[dst_map_idx]; + RDI_NameMap *dst_map = &dst_maps[k]; RDIM_BakeNameMap *src_map = name_maps[k]; dst_map->bucket_base_idx = (RDI_U32)dst_map_bucket_idx; // TODO(rjf): @u64_to_u32 dst_map->node_base_idx = (RDI_U32)dst_map_node_idx; // TODO(rjf): @u64_to_u32 dst_map->bucket_count = (RDI_U32)src_map->name_count; // TODO(rjf): @u64_to_u32 dst_map->node_count = (RDI_U32)src_map->name_count; // TODO(rjf): @u64_to_u32 - dst_map_idx += 1; dst_map_bucket_idx += dst_map->bucket_count; dst_map_node_idx += dst_map->node_count; } diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index 328a9793..da4d0ee2 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -1474,7 +1474,7 @@ RDI_PROC RDIM_BakePathTree *rdim_bake_path_tree_from_params(RDIM_Arena *arena, R //~ rjf: [Baking] Build Artifacts -> Baked Versions //- rjf: partial/joinable baking functions -RDI_PROC RDIM_NameMapBakeResult rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *src, RDI_U64 base_node_idx); +RDI_PROC RDIM_NameMapBakeResult rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *src); //- rjf: partial bakes -> final bake functions RDI_PROC RDIM_NameMapBakeResult rdim_name_map_bake_results_combine(RDIM_Arena *arena, RDIM_NameMapBakeResult *results, RDI_U64 results_count); diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index 41591105..e5141165 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -3812,7 +3812,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_bake_name_map_task__entry_point) { P2R_BakeNameMapIn *in = (P2R_BakeNameMapIn *)p; RDIM_NameMapBakeResult *out = push_array(arena, RDIM_NameMapBakeResult, 1); - ProfScope("bake name map %i", in->kind) *out = rdim_bake_name_map(arena, in->strings, in->idx_runs, in->map, in->base_node_idx); + ProfScope("bake name map %i", in->kind) *out = rdim_bake_name_map(arena, in->strings, in->idx_runs, in->map); return out; } @@ -4195,7 +4195,6 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) TS_Ticket bake_type_nodes_ticket = ts_kickoff(p2r_bake_type_nodes_task__entry_point, 0, &bake_type_nodes_in); TS_Ticket bake_name_maps_tickets[RDI_NameMapKind_COUNT] = {0}; { - U64 base_node_idx = 0; for(EachNonZeroEnumVal(RDI_NameMapKind, k)) { if(name_maps[k] == 0 || name_maps[k]->name_count == 0) @@ -4206,10 +4205,8 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) in->strings = &bake_strings; in->idx_runs = idx_runs; in->map = name_maps[k]; - in->base_node_idx = base_node_idx; in->kind = k; bake_name_maps_tickets[k] = ts_kickoff(p2r_bake_name_map_task__entry_point, 0, in); - base_node_idx += name_maps[k]->name_count; } } P2R_BakeIdxRunsIn bake_idx_runs_in = {idx_runs}; diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index bcbf6cd3..9e92e208 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -502,7 +502,6 @@ struct P2R_BakeNameMapIn RDIM_BakeStringMapTight *strings; RDIM_BakeIdxRunMap *idx_runs; RDIM_BakeNameMap *map; - U64 base_node_idx; RDI_NameMapKind kind; }; From 8c63478d9b08e3e6fe7b66c645b3aac47ecf2197 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 7 Jun 2024 11:17:48 -0700 Subject: [PATCH 19/44] rdi_make: eliminate old baking/serializing code --- src/lib_rdi_make/rdi_make.c | 1439 ----------------------------------- src/lib_rdi_make/rdi_make.h | 67 -- 2 files changed, 1506 deletions(-) diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index b8dee044..1bd3a998 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -3653,1442 +3653,3 @@ rdim_file_blobs_from_section_bundle(RDIM_Arena *arena, RDIM_SerializedSectionBun } return strings; } - -//////////////////////////////// -//~ rjf: [Baking] Build Artifacts -> Data Section Lists - -#if 0 - -//- rjf: top-level info - -RDI_PROC RDIM_BakeSectionList -rdim_bake_top_level_info_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params) -{ - RDIM_BakeSectionList sections = {0}; - RDI_TopLevelInfo *dst_tli = rdim_push_array(arena, RDI_TopLevelInfo, 1); - RDIM_TopLevelInfo *src_tli = ¶ms->top_level_info; - dst_tli->arch = src_tli->arch; - dst_tli->exe_name_string_idx = rdim_bake_idx_from_string(strings, src_tli->exe_name); - dst_tli->exe_hash = src_tli->exe_hash; - dst_tli->voff_max = src_tli->voff_max; - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_tli, sizeof(*dst_tli), RDI_SectionKind_TopLevelInfo, 0); - return sections; -} - -//- rjf: binary sections - -RDI_PROC RDIM_BakeSectionList -rdim_bake_binary_section_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params) -{ - RDIM_BakeSectionList sections = {0}; - RDIM_BinarySectionList *src_list = ¶ms->binary_sections; - RDI_BinarySection *dst_base = rdim_push_array(arena, RDI_BinarySection, src_list->count+1); - U64 dst_idx = 1; - for(RDIM_BinarySectionNode *src_n = src_list->first; src_n != 0; src_n = src_n->next, dst_idx += 1) - { - RDIM_BinarySection *src = &src_n->v; - RDI_BinarySection *dst = &dst_base[dst_idx]; - dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->flags = src->flags; - dst->voff_first = src->voff_first; - dst->voff_opl = src->voff_opl; - dst->foff_first = src->foff_first; - dst->foff_opl = src->foff_opl; - } - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_base, sizeof(*dst_base)*dst_idx, RDI_SectionKind_BinarySections, 0); - return sections; -} - -//- rjf: units - -RDI_PROC RDIM_BakeSectionList -rdim_bake_unit_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params) -{ - RDIM_BakeSectionList sections = {0}; - RDI_Unit *dst_base = rdim_push_array(arena, RDI_Unit, params->units.total_count+1); - RDI_U64 dst_idx = 1; - for(RDIM_UnitChunkNode *src_n = params->units.first; src_n != 0; src_n = src_n->next) - { - for(RDI_U64 src_chunk_idx = 0; src_chunk_idx < src_n->count; src_chunk_idx += 1, dst_idx += 1) - { - RDIM_Unit *src = &src_n->v[src_chunk_idx]; - RDI_Unit *dst = &dst_base[dst_idx]; - dst->unit_name_string_idx = rdim_bake_idx_from_string(strings, src->unit_name); - dst->compiler_name_string_idx = rdim_bake_idx_from_string(strings, src->compiler_name); - dst->source_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->source_file); - dst->object_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->object_file); - dst->archive_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->archive_file); - dst->build_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->build_path); - dst->language = src->language; - dst->line_table_idx = (RDI_U32)rdim_idx_from_line_table(src->line_table); // TODO(rjf): @u64_to_u32 - } - } - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_base, sizeof(*dst_base)*dst_idx, RDI_SectionKind_Units, 0); - return sections; -} - -//- rjf: unit vmap - -RDI_PROC RDIM_BakeSectionList -rdim_bake_unit_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params) -{ - //- rjf: build vmap from unit voff ranges - RDIM_BakeVMap unit_vmap = {0}; - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - // rjf: count voff ranges - RDI_U64 voff_range_count = 0; - for(RDIM_UnitChunkNode *n = params->units.first; n != 0; n = n->next) - { - for(RDI_U64 idx = 0; idx < n->count; idx += 1) - { - RDIM_Unit *unit = &n->v[idx]; - voff_range_count += unit->voff_ranges.count; - } - } - - // rjf: count necessary markers - RDI_U64 marker_count = voff_range_count*2; - - // rjf: build keys/markers arrays - RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); - RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); - { - RDIM_SortKey *key_ptr = keys; - RDIM_VMapMarker *marker_ptr = markers; - RDI_U32 unit_idx = 1; - for(RDIM_UnitChunkNode *unit_chunk_n = params->units.first; - unit_chunk_n != 0; - unit_chunk_n = unit_chunk_n->next) - { - for(RDI_U64 idx = 0; idx < unit_chunk_n->count; idx += 1) - { - RDIM_Unit *unit = &unit_chunk_n->v[idx]; - for(RDIM_Rng1U64Node *n = unit->voff_ranges.first; n != 0; n = n->next) - { - RDIM_Rng1U64 range = n->v; - if(range.min < range.max) - { - key_ptr->key = range.min; - key_ptr->val = marker_ptr; - marker_ptr->idx = unit_idx; - marker_ptr->begin_range = 1; - key_ptr += 1; - marker_ptr += 1; - - key_ptr->key = range.max; - key_ptr->val = marker_ptr; - marker_ptr->idx = unit_idx; - marker_ptr->begin_range = 0; - key_ptr += 1; - marker_ptr += 1; - } - } - unit_idx += 1; - } - } - } - - // rjf: keys/markers -> unit vmap - unit_vmap = rdim_bake_vmap_from_markers(arena, markers, keys, marker_count); - rdim_scratch_end(scratch); - } - - //- rjf: build section - RDIM_BakeSectionList sections = {0}; - RDI_U64 unit_vmap_size = sizeof(unit_vmap.vmap[0])*(unit_vmap.count+1); - rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_vmap.vmap, unit_vmap_size, RDI_SectionKind_UnitVMap, 0); - return sections; -} - -//- rjf: source files - -RDI_PROC RDIM_BakeSectionList -rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params) -{ - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - RDIM_BakeSectionList sections = {0}; - - //////////////////////////// - //- rjf: iterate all source files, fill serialized version, fill line maps, fill line map tables - // - typedef struct RDIM_DataNode RDIM_DataNode; - struct RDIM_DataNode - { - RDIM_DataNode *next; - void *data; - RDI_U64 size; - }; - RDI_U32 dst_files_count = params->src_files.total_count + 1; - RDI_U32 dst_maps_count = params->src_files.source_line_map_count + 1; - RDI_SourceFile *dst_files = rdim_push_array(arena, RDI_SourceFile, dst_files_count); - RDI_SourceLineMap *dst_maps = rdim_push_array(arena, RDI_SourceLineMap, dst_maps_count); - RDIM_DataNode *first_dst_nums_node = 0; - RDIM_DataNode *last_dst_nums_node = 0; - RDIM_DataNode *first_dst_rngs_node = 0; - RDIM_DataNode *last_dst_rngs_node = 0; - RDIM_DataNode *first_dst_voffs_node = 0; - RDIM_DataNode *last_dst_voffs_node = 0; - RDI_U64 dst_nums_idx = 0; - RDI_U64 dst_rngs_idx = 0; - RDI_U64 dst_voffs_idx = 0; - RDI_U32 dst_file_idx = 1; - RDI_U32 dst_map_idx = 1; - for(RDIM_SrcFileChunkNode *chunk_n = params->src_files.first; - chunk_n != 0; - chunk_n = chunk_n->next) - { - for(RDI_U64 idx = 0; idx < chunk_n->count; idx += 1, dst_file_idx += 1) - { - RDIM_SrcFile *src_file = &chunk_n->v[idx]; - RDI_SourceFile *dst_file = &dst_files[dst_file_idx]; - - //////////////////////// - //- rjf: produce combined source file line info - // - RDI_U32 *src_file_line_nums = 0; - RDI_U32 *src_file_line_ranges = 0; - RDI_U64 *src_file_voffs = 0; - RDI_U32 src_file_line_count = 0; - RDI_U32 src_file_voff_count = 0; - { - //- rjf: gather line number map - typedef struct RDIM_SrcLineMapVoffBlock RDIM_SrcLineMapVoffBlock; - struct RDIM_SrcLineMapVoffBlock - { - RDIM_SrcLineMapVoffBlock *next; - RDI_U64 voff; - }; - typedef struct RDIM_SrcLineMapBucket RDIM_SrcLineMapBucket; - struct RDIM_SrcLineMapBucket - { - RDIM_SrcLineMapBucket *order_next; - RDIM_SrcLineMapBucket *hash_next; - RDI_U32 line_num; - RDIM_SrcLineMapVoffBlock *first_voff_block; - RDIM_SrcLineMapVoffBlock *last_voff_block; - RDI_U64 voff_count; - }; - RDIM_SrcLineMapBucket *first_bucket = 0; - RDIM_SrcLineMapBucket *last_bucket = 0; - RDI_U64 line_hash_slots_count = 2048; - RDIM_SrcLineMapBucket **line_hash_slots = rdim_push_array(scratch.arena, RDIM_SrcLineMapBucket *, line_hash_slots_count); - RDI_U64 line_count = 0; - RDI_U64 voff_count = 0; - RDI_U64 max_line_num = 0; - { - for(RDIM_SrcFileLineMapFragment *map_fragment = src_file->first_line_map_fragment; - map_fragment != 0; - map_fragment = map_fragment->next) - { - RDIM_LineSequence *sequence = map_fragment->seq; - RDI_U64 *seq_voffs = sequence->voffs; - RDI_U32 *seq_line_nums = sequence->line_nums; - RDI_U64 seq_line_count = sequence->line_count; - for(RDI_U64 i = 0; i < seq_line_count; i += 1) - { - RDI_U32 line_num = seq_line_nums[i]; - RDI_U64 voff = seq_voffs[i]; - RDI_U64 line_hash_slot_idx = line_num%line_hash_slots_count; - - // rjf: update unique voff counter & max line number - voff_count += 1; - max_line_num = Max(max_line_num, line_num); - - // rjf: find match - RDIM_SrcLineMapBucket *match = 0; - { - for(RDIM_SrcLineMapBucket *node = line_hash_slots[line_hash_slot_idx]; - node != 0; - node = node->hash_next) - { - if(node->line_num == line_num) - { - match = node; - break; - } - } - } - - // rjf: introduce new map if no match - if(match == 0) - { - match = rdim_push_array(scratch.arena, RDIM_SrcLineMapBucket, 1); - RDIM_SLLQueuePush_N(first_bucket, last_bucket, match, order_next); - RDIM_SLLStackPush_N(line_hash_slots[line_hash_slot_idx], match, hash_next); - match->line_num = line_num; - line_count += 1; - } - - // rjf: insert new voff - { - RDIM_SrcLineMapVoffBlock *block = rdim_push_array(scratch.arena, RDIM_SrcLineMapVoffBlock, 1); - RDIM_SLLQueuePush(match->first_voff_block, match->last_voff_block, block); - match->voff_count += 1; - block->voff = voff; - } - } - } - } - - //- rjf: bake sortable keys array - RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, line_count); - { - RDIM_SortKey *key_ptr = keys; - for(RDIM_SrcLineMapBucket *node = first_bucket; - node != 0; - node = node->order_next, key_ptr += 1){ - key_ptr->key = node->line_num; - key_ptr->val = node; - } - } - - //- rjf: sort keys array - RDIM_SortKey *sorted_keys = rdim_sort_key_array(scratch.arena, keys, line_count); - - //- rjf: bake result - RDI_U32 *line_nums = rdim_push_array_no_zero(scratch.arena, RDI_U32, line_count); - RDI_U32 *line_ranges = rdim_push_array_no_zero(scratch.arena, RDI_U32, line_count + 1); - RDI_U64 *voffs = rdim_push_array_no_zero(scratch.arena, RDI_U64, voff_count); - { - RDI_U64 *voff_ptr = voffs; - for(RDI_U32 i = 0; i < line_count; i += 1) - { - line_nums[i] = sorted_keys[i].key; - line_ranges[i] = (RDI_U32)(voff_ptr - voffs); // TODO(rjf): @u64_to_u32 - RDIM_SrcLineMapBucket *bucket = (RDIM_SrcLineMapBucket*)sorted_keys[i].val; - for(RDIM_SrcLineMapVoffBlock *node = bucket->first_voff_block; node != 0; node = node->next) - { - *voff_ptr = node->voff; - voff_ptr += 1; - } - } - line_ranges[line_count] = voff_count; - } - - //- rjf: fill output - src_file_line_nums = line_nums; - src_file_line_ranges = line_ranges; - src_file_line_count = line_count; - src_file_voffs = voffs; - src_file_voff_count = voff_count; - } - - //////////////////////// - //- rjf: grab & fill the next line map, if this file has one - // - RDI_SourceLineMap *dst_map = 0; - if(src_file->first_line_map_fragment != 0) - { - dst_map = &dst_maps[dst_map_idx]; - dst_map_idx += 1; - dst_map->line_count = (RDI_U32)src_file_line_count; // TODO(rjf): @u64_to_u32 - dst_map->voff_count = (RDI_U32)src_file_voff_count; // TODO(rjf): @u64_to_u32 - dst_map->line_map_nums_base_idx = (RDI_U32)dst_nums_idx; // TODO(rjf): @u64_to_u32 - dst_map->line_map_range_base_idx = (RDI_U32)dst_rngs_idx; // TODO(rjf): @u64_to_u32 - dst_map->line_map_voff_base_idx = (RDI_U32)dst_voffs_idx; // TODO(rjf): @u64_to_u32 - } - - //////////////////////// - //- rjf: gather line map data chunks for later collation & storage into their own top-level sections - // - { - RDIM_DataNode *dst_num_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); - RDIM_SLLQueuePush(first_dst_nums_node, last_dst_nums_node, dst_num_node); - dst_num_node->data = src_file_line_nums; - dst_num_node->size = sizeof(RDI_U32)*src_file_line_count; - RDIM_DataNode *dst_rng_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); - RDIM_SLLQueuePush(first_dst_rngs_node, last_dst_rngs_node, dst_rng_node); - dst_rng_node->data = src_file_line_ranges; - dst_rng_node->size = sizeof(RDI_U32)*(src_file_line_count+1); - RDIM_DataNode *dst_voff_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); - RDIM_SLLQueuePush(first_dst_voffs_node, last_dst_voffs_node, dst_voff_node); - dst_voff_node->data = src_file_voffs; - dst_voff_node->size = sizeof(RDI_U64)*(src_file_voff_count); - dst_nums_idx += src_file_line_count; - dst_rngs_idx += src_file_line_count+1; - dst_voffs_idx+= src_file_voff_count; - } - - //////////////////////// - //- rjf: fill file info - // - dst_file->file_path_node_idx = rdim_bake_path_node_idx_from_string(path_tree, src_file->normal_full_path); - dst_file->normal_full_path_string_idx = rdim_bake_idx_from_string(strings, src_file->normal_full_path); - dst_file->source_line_map_idx = (RDI_U32)(dst_map ? (dst_map - dst_maps) : 0); - } - } - - //////////////////////////// - //- rjf: coalesce source line map data blobs - // - RDI_U32 *source_line_map_nums = rdim_push_array_no_zero(arena, RDI_U32, dst_nums_idx); - RDI_U32 *source_line_map_rngs = rdim_push_array_no_zero(arena, RDI_U32, dst_rngs_idx); - RDI_U64 *source_line_map_voffs= rdim_push_array_no_zero(arena, RDI_U64, dst_voffs_idx); - { - RDI_U64 num_idx = 0; - RDI_U64 rng_idx = 0; - RDI_U64 voff_idx= 0; - for(RDIM_DataNode *num_n = first_dst_nums_node; num_n != 0; num_n = num_n->next) - { - rdim_memcpy(source_line_map_nums+num_idx, num_n->data, num_n->size); - num_idx += num_n->size/sizeof(RDI_U32); - } - for(RDIM_DataNode *rng_n = first_dst_rngs_node; rng_n != 0; rng_n = rng_n->next) - { - rdim_memcpy(source_line_map_rngs+rng_idx, rng_n->data, rng_n->size); - rng_idx += rng_n->size/sizeof(RDI_U32); - } - for(RDIM_DataNode *voff_n = first_dst_voffs_node; voff_n != 0; voff_n = voff_n->next) - { - rdim_memcpy(source_line_map_voffs+voff_idx, voff_n->data, voff_n->size); - voff_idx += voff_n->size/sizeof(RDI_U64); - } - } - - //////////////////////////// - //- rjf: build sections - // - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_files, sizeof(RDI_SourceFile)*dst_files_count, RDI_SectionKind_SourceFiles, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_maps, sizeof(RDI_SourceLineMap)*dst_maps_count, RDI_SectionKind_SourceLineMaps, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, source_line_map_nums, sizeof(RDI_U32)*dst_nums_idx, RDI_SectionKind_SourceLineMapNumbers, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, source_line_map_rngs, sizeof(RDI_U32)*dst_rngs_idx, RDI_SectionKind_SourceLineMapRanges, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, source_line_map_voffs,sizeof(RDI_U64)*dst_voffs_idx, RDI_SectionKind_SourceLineMapVOffs, 0); - - rdim_scratch_end(scratch); - return sections; -} - -//- rjf: line tables - -RDI_PROC RDIM_BakeSectionList -rdim_bake_line_table_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params) -{ - //- rjf: build all combined line info - RDI_LineTable *dst_line_tables = push_array(arena, RDI_LineTable, params->line_tables.total_count+1); - RDI_U64 *dst_line_voffs = push_array(arena, RDI_U64, params->line_tables.total_line_count + 2*params->line_tables.total_seq_count); - RDI_Line *dst_lines = push_array(arena, RDI_Line, params->line_tables.total_line_count + params->line_tables.total_seq_count); - RDI_Column *dst_cols = push_array(arena, RDI_Column, 1); - { - RDI_U64 dst_table_idx = 1; - RDI_U64 dst_voff_idx = 0; - RDI_U64 dst_line_idx = 0; - RDI_U64 dst_col_idx = 0; - for(RDIM_LineTableChunkNode *src_n = params->line_tables.first; src_n != 0; src_n = src_n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < src_n->count; chunk_idx += 1) - { - RDIM_LineTable *src_line_table = &src_n->v[chunk_idx]; - RDI_LineTable *dst_line_table = &dst_line_tables[dst_table_idx]; - - //- rjf: fill combined line table info - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - //- rjf: gather up all line info into two arrays: - // - // [1] keys: sortable array; pairs voffs with line info records; null records are sequence enders - // [2] recs: contains all the source coordinates for a range of voffs - // - typedef struct RDIM_LineRec RDIM_LineRec; - struct RDIM_LineRec - { - RDI_U32 file_id; - RDI_U32 line_num; - RDI_U16 col_first; - RDI_U16 col_opl; - }; - RDI_U64 line_count = src_line_table->line_count; - RDI_U64 seq_count = src_line_table->seq_count; - RDI_U64 key_count = line_count + seq_count; - RDIM_SortKey *line_keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, key_count); - RDIM_LineRec *line_recs = rdim_push_array_no_zero(scratch.arena, RDIM_LineRec, line_count); - { - RDIM_SortKey *key_ptr = line_keys; - RDIM_LineRec *rec_ptr = line_recs; - for(RDIM_LineSequenceNode *seq_n = src_line_table->first_seq; seq_n != 0; seq_n = seq_n->next) - { - RDIM_LineSequence *seq = &seq_n->v; - for(RDI_U64 line_idx = 0; line_idx < seq->line_count; line_idx += 1) - { - key_ptr->key = seq->voffs[line_idx]; - key_ptr->val = rec_ptr; - key_ptr += 1; - rec_ptr->file_id = (RDI_U32)rdim_idx_from_src_file(seq->src_file); // TODO(rjf): @u64_to_u32 - rec_ptr->line_num = seq->line_nums[line_idx]; - if(seq->col_nums != 0) - { - rec_ptr->col_first = seq->col_nums[line_idx*2]; - rec_ptr->col_opl = seq->col_nums[line_idx*2 + 1]; - } - rec_ptr += 1; - } - key_ptr->key = seq->voffs[seq->line_count]; - key_ptr->val = 0; - key_ptr += 1; - } - } - - //- rjf: sort - RDIM_SortKey *sorted_line_keys = 0; - RDIM_ProfScope("sort") - { - sorted_line_keys = rdim_sort_key_array(scratch.arena, line_keys, key_count); - } - - // TODO(rjf): do a pass over sorted keys to make sure duplicate keys - // are sorted with null record first, and no more than one null - // record and one non-null record - - //- rjf: arrange output - RDI_U64 *arranged_voffs = dst_line_voffs + dst_voff_idx; - RDI_Line *arranged_lines = dst_lines + dst_line_idx; - RDIM_ProfScope("arrange output") - { - for(RDI_U64 i = 0; i < key_count; i += 1) - { - arranged_voffs[i] = sorted_line_keys[i].key; - } - arranged_voffs[key_count] = ~0ull; - for(RDI_U64 i = 0; i < key_count; i += 1) - { - RDIM_LineRec *rec = (RDIM_LineRec*)sorted_line_keys[i].val; - if(rec != 0) - { - arranged_lines[i].file_idx = rec->file_id; - arranged_lines[i].line_num = rec->line_num; - } - else - { - arranged_lines[i].file_idx = 0; - arranged_lines[i].line_num = 0; - } - } - } - - rdim_scratch_end(scratch); - } - - //- rjf: fill destination table - dst_line_table->voffs_base_idx = (RDI_U32)dst_voff_idx; // TODO(rjf): @u64_to_u32 - dst_line_table->lines_base_idx = (RDI_U32)dst_line_idx; // TODO(rjf): @u64_to_u32 - dst_line_table->cols_base_idx = (RDI_U32)dst_col_idx; // TODO(rjf): @u64_to_u32 - dst_line_table->lines_count = (RDI_U32)src_line_table->line_count + src_line_table->seq_count; // TODO(rjf): @u64_to_u32 - - //- rjf: increment - dst_table_idx += 1; - dst_voff_idx += src_line_table->line_count + 2*src_line_table->seq_count; - dst_line_idx += src_line_table->line_count + src_line_table->seq_count; - } - } - } - - //- rjf: produce sections - RDIM_BakeSectionList sections = {0}; - { - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_line_tables, sizeof(RDI_LineTable)*params->line_tables.total_count, RDI_SectionKind_LineTables, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_line_voffs, sizeof(RDI_U64) * (params->line_tables.total_line_count + params->line_tables.total_seq_count), RDI_SectionKind_LineInfoVOffs, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_lines, sizeof(RDI_Line) * (params->line_tables.total_line_count + params->line_tables.total_seq_count), RDI_SectionKind_LineInfoLines, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_cols, sizeof(RDI_Column) * params->line_tables.total_col_count, RDI_SectionKind_LineInfoColumns, 0); - } - return sections; -} - -//- rjf: type nodes - -RDI_PROC RDIM_BakeSectionList -rdim_bake_type_node_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeParams *params) -{ - //- rjf: build all type nodes - RDI_TypeNode *type_nodes = push_array(arena, RDI_TypeNode, params->types.total_count+1); - RDIM_ProfScope("push all type nodes") - { - RDI_U32 dst_idx = 1; - for(RDIM_TypeChunkNode *n = params->types.first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) - { - RDIM_Type *src = &n->v[chunk_idx]; - RDI_TypeNode *dst = &type_nodes[dst_idx]; - - //- rjf: fill shared type node info - dst->kind = src->kind; - dst->flags = (RDI_U16)src->flags; // TODO(rjf): @u32_to_u16 - dst->byte_size = src->byte_size; - - //- rjf: fill built-in-only type node info - if(RDI_TypeKind_FirstBuiltIn <= dst->kind && dst->kind <= RDI_TypeKind_LastBuiltIn) - { - dst->built_in.name_string_idx = rdim_bake_idx_from_string(strings, src->name); - } - - //- rjf: fill constructed type node info - else if(RDI_TypeKind_FirstConstructed <= dst->kind && dst->kind <= RDI_TypeKind_LastConstructed) - { - dst->constructed.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 - dst->constructed.count = src->count; - if(dst->kind == RDI_TypeKind_Function || dst->kind == RDI_TypeKind_Method) - { - RDI_U32 param_idx_run_count = src->count; - RDI_U32 *param_idx_run = rdim_push_array_no_zero(arena, RDI_U32, param_idx_run_count); - for(RDI_U32 idx = 0; idx < param_idx_run_count; idx += 1) - { - param_idx_run[idx] = (RDI_U32)rdim_idx_from_type(src->param_types[idx]); // TODO(rjf): @u64_to_u32 - } - dst->constructed.param_idx_run_first = rdim_bake_idx_from_idx_run(idx_runs, param_idx_run, param_idx_run_count); - } - else if(dst->kind == RDI_TypeKind_MemberPtr) - { - // TODO(rjf): member pointers not currently supported. - } - } - - //- rjf: fill user-defined-type info - else if(RDI_TypeKind_FirstUserDefined <= dst->kind && dst->kind <= RDI_TypeKind_LastUserDefined) - { - dst->user_defined.name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->user_defined.udt_idx = (RDI_U32)rdim_idx_from_udt(src->udt); // TODO(rjf): @u64_to_u32 - dst->user_defined.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 - } - - //- rjf: fill bitfield info - else if(dst->kind == RDI_TypeKind_Bitfield) - { - dst->bitfield.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 - dst->bitfield.off = src->off; - dst->bitfield.size = src->count; - } - } - } - } - - - //- rjf: build sections - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, type_nodes, sizeof(RDI_TypeNode)*(params->types.total_count+1), RDI_SectionKind_TypeNodes, 0); - return sections; -} - -//- rjf: UDTs - -RDI_PROC RDIM_BakeSectionList -rdim_bake_udt_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params) -{ - //- rjf: build tables - RDI_UDT * udts = push_array(arena, RDI_UDT, params->udts.total_count+1); - RDI_Member * members = push_array(arena, RDI_Member, params->udts.total_member_count+1); - RDI_EnumMember *enum_members = push_array(arena, RDI_EnumMember, params->udts.total_enum_val_count+1); - { - RDI_U32 dst_udt_idx = 1; - RDI_U32 dst_member_idx = 1; - RDI_U32 dst_enum_member_idx = 1; - for(RDIM_UDTChunkNode *n = params->udts.first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_udt_idx += 1) - { - RDIM_UDT *src_udt = &n->v[chunk_idx]; - RDI_UDT *dst_udt = &udts[dst_udt_idx]; - - //- rjf: fill basics - dst_udt->self_type_idx = (RDI_U32)rdim_idx_from_type(src_udt->self_type); // TODO(rjf): @u64_to_u32 - dst_udt->file_idx = (RDI_U32)rdim_idx_from_src_file(src_udt->src_file); // TODO(rjf): @u64_to_u32 - dst_udt->line = src_udt->line; - dst_udt->col = src_udt->col; - - //- rjf: fill members - if(src_udt->member_count != 0) - { - dst_udt->member_first = dst_member_idx; - dst_udt->member_count = src_udt->member_count; - for(RDIM_UDTMember *src_member = src_udt->first_member; - src_member != 0; - src_member = src_member->next, dst_member_idx += 1) - { - RDI_Member *dst_member = &members[dst_member_idx]; - dst_member->kind = src_member->kind; - dst_member->name_string_idx = rdim_bake_idx_from_string(strings, src_member->name); - dst_member->type_idx = (RDI_U32)rdim_idx_from_type(src_member->type); // TODO(rjf): @u64_to_u32 - dst_member->off = src_member->off; - } - } - - //- rjf: fill enum members - else if(src_udt->enum_val_count != 0) - { - dst_udt->flags |= RDI_UDTFlag_EnumMembers; - dst_udt->member_first = dst_enum_member_idx; - dst_udt->member_count = src_udt->enum_val_count; - for(RDIM_UDTEnumVal *src_member = src_udt->first_enum_val; - src_member != 0; - src_member = src_member->next, dst_enum_member_idx += 1) - { - RDI_EnumMember *dst_member = &enum_members[dst_enum_member_idx]; - dst_member->name_string_idx = rdim_bake_idx_from_string(strings, src_member->name); - dst_member->val = src_member->val; - } - } - } - } - } - - //- rjf: build sections - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, udts, sizeof(RDI_UDT) * (params->udts.total_count+1), RDI_SectionKind_UDTs, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, members , sizeof(RDI_Member) * (params->udts.total_member_count+1), RDI_SectionKind_Members, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, enum_members, sizeof(RDI_EnumMember) * (params->udts.total_enum_val_count+1), RDI_SectionKind_EnumMembers, 0); - return sections; -} - -//- rjf: global variables - -RDI_PROC RDIM_BakeSectionList -rdim_bake_global_variable_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params) -{ - //- rjf: build all global variables - RDI_GlobalVariable *global_variables = push_array(arena, RDI_GlobalVariable, params->global_variables.total_count+1); - { - RDI_U32 dst_idx = 1; - for(RDIM_SymbolChunkNode *n = params->global_variables.first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) - { - RDIM_Symbol *src = &n->v[chunk_idx]; - RDI_GlobalVariable *dst = &global_variables[dst_idx]; - dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->voff = src->offset; - dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 - if(src->is_extern) - { - dst->link_flags |= RDI_LinkFlag_External; - } - if(src->container_type != 0) - { - dst->link_flags |= RDI_LinkFlag_TypeScoped; - dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 - } - else if(src->container_symbol != 0) - { - dst->link_flags |= RDI_LinkFlag_ProcScoped; - dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 - } - } - } - } - - //- rjf: build sections - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, global_variables, sizeof(RDI_GlobalVariable)*(params->global_variables.total_count+1), RDI_SectionKind_GlobalVariables, 0); - return sections; -} - -//- rjf: global vmap - -RDI_PROC RDIM_BakeSectionList -rdim_bake_global_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params) -{ - //- rjf: build global vmap - RDIM_BakeVMap global_vmap = {0}; - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - //- rjf: allocate keys/markers - RDI_U64 marker_count = params->global_variables.total_count*2; - RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); - RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); - - //- rjf: fill - { - RDIM_SortKey *key_ptr = keys; - RDIM_VMapMarker *marker_ptr = markers; - - // rjf: fill actual globals - for(RDIM_SymbolChunkNode *n = params->global_variables.first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) - { - RDIM_Symbol *global_var = &n->v[chunk_idx]; - RDI_U32 global_var_idx = (RDI_U32)rdim_idx_from_symbol(global_var); // TODO(rjf): @u64_to_u32 - RDI_U64 global_var_size = global_var->type ? global_var->type->byte_size : 1; - - RDI_U64 first = global_var->offset; - RDI_U64 opl = first + global_var_size; - - key_ptr->key = first; - key_ptr->val = marker_ptr; - marker_ptr->idx = global_var_idx; - marker_ptr->begin_range = 1; - key_ptr += 1; - marker_ptr += 1; - - key_ptr->key = opl; - key_ptr->val = marker_ptr; - marker_ptr->idx = global_var_idx; - marker_ptr->begin_range = 0; - key_ptr += 1; - marker_ptr += 1; - } - } - - // rjf: fill nil global - { - RDI_U32 global_idx = 0; - RDI_U64 first = 0; - RDI_U64 opl = 0xffffffffffffffffull; - key_ptr->key = first; - key_ptr->val = marker_ptr; - marker_ptr->idx = global_idx; - marker_ptr->begin_range = 1; - key_ptr += 1; - marker_ptr += 1; - key_ptr->key = opl; - key_ptr->val = marker_ptr; - marker_ptr->idx = global_idx; - marker_ptr->begin_range = 0; - key_ptr += 1; - marker_ptr += 1; - } - } - - // rjf: construct vmap - global_vmap = rdim_bake_vmap_from_markers(arena, markers, keys, marker_count); - - rdim_scratch_end(scratch); - } - - //- rjf: build sections - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, global_vmap.vmap, sizeof(RDI_VMapEntry)*(global_vmap.count+1), RDI_SectionKind_GlobalVMap, 0); - return sections; -} - -//- rjf: thread variables - -RDI_PROC RDIM_BakeSectionList -rdim_bake_thread_variable_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params) -{ - //- rjf: build all thread variables - RDI_ThreadVariable *thread_variables = push_array(arena, RDI_ThreadVariable, params->thread_variables.total_count+1); - { - RDI_U32 dst_idx = 1; - for(RDIM_SymbolChunkNode *n = params->thread_variables.first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) - { - RDIM_Symbol *src = &n->v[chunk_idx]; - RDI_ThreadVariable *dst = &thread_variables[dst_idx]; - dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->tls_off = (RDI_U32)src->offset; // TODO(rjf): @u64_to_u32 - dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); - if(src->is_extern) - { - dst->link_flags |= RDI_LinkFlag_External; - } - if(src->container_type != 0) - { - dst->link_flags |= RDI_LinkFlag_TypeScoped; - dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 - } - else if(src->container_symbol != 0) - { - dst->link_flags |= RDI_LinkFlag_ProcScoped; - dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 - } - } - } - } - - //- rjf: build sections - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, thread_variables, sizeof(RDI_ThreadVariable)*(params->thread_variables.total_count+1), RDI_SectionKind_ThreadVariables, 0); - return sections; -} - -//- rjf: procedures - -RDI_PROC RDIM_BakeSectionList -rdim_bake_procedure_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params) -{ - //- rjf: build all procedures - RDI_Procedure *procedures = push_array(arena, RDI_Procedure, params->procedures.total_count+1); - { - RDI_U32 dst_idx = 1; - for(RDIM_SymbolChunkNode *n = params->procedures.first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) - { - RDIM_Symbol *src = &n->v[chunk_idx]; - RDI_Procedure *dst = &procedures[dst_idx]; - dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->link_name_string_idx = rdim_bake_idx_from_string(strings, src->link_name); - if(src->is_extern) - { - dst->link_flags |= RDI_LinkFlag_External; - } - if(src->container_type != 0) - { - dst->link_flags |= RDI_LinkFlag_TypeScoped; - dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 - } - else if(src->container_symbol != 0) - { - dst->link_flags |= RDI_LinkFlag_ProcScoped; - dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 - } - dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 - dst->root_scope_idx = (RDI_U32)rdim_idx_from_scope(src->root_scope); // TODO(rjf): @u64_to_u32 - } - } - } - - //- rjf: build sections - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, procedures, sizeof(RDI_Procedure)*(params->procedures.total_count+1), RDI_SectionKind_Procedures, 0); - return sections; -} - -//- rjf: scopes - -RDI_PROC RDIM_BakeSectionList -rdim_bake_scope_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params) -{ - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - //////////////////////////// - //- rjf: build all scopes, scope voffs, locals, and location blocks - // - RDI_Scope * scopes = rdim_push_array(arena, RDI_Scope, params->scopes.total_count+1); - RDI_U64 * scope_voffs = rdim_push_array(arena, RDI_U64, params->scopes.scope_voff_count+1); - RDI_Local * locals = rdim_push_array(arena, RDI_Local, params->scopes.local_count+1); - RDI_LocationBlock * location_blocks = rdim_push_array(arena, RDI_LocationBlock, params->scopes.location_count+1); - RDIM_String8List location_data_blobs = {0}; - RDIM_ProfScope("build all scopes, scope voffs, locals, and location blocks") - { - RDI_U64 dst_scope_idx = 1; - RDI_U64 dst_scope_voff_idx = 1; - RDI_U64 dst_local_idx = 1; - RDI_U64 dst_location_block_idx = 1; - for(RDIM_ScopeChunkNode *chunk_n = params->scopes.first; chunk_n != 0; chunk_n = chunk_n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < chunk_n->count; chunk_idx += 1, dst_scope_idx += 1) - { - RDIM_Scope *src_scope = &chunk_n->v[chunk_idx]; - RDI_Scope *dst_scope = &scopes[dst_scope_idx]; - - //- rjf: push scope's voffs - RDI_U64 voff_idx_first = dst_scope_voff_idx; - { - for(RDIM_Rng1U64Node *n = src_scope->voff_ranges.first; n != 0; n = n->next) - { - scope_voffs[dst_scope_voff_idx] = n->v.min; - dst_scope_voff_idx += 1; - scope_voffs[dst_scope_voff_idx] = n->v.max; - dst_scope_voff_idx += 1; - } - } - RDI_U64 voff_idx_opl = dst_scope_voff_idx; - - //- rjf: push locals - RDI_U64 local_idx_first = dst_local_idx; - for(RDIM_Local *src_local = src_scope->first_local; - src_local != 0; - src_local = src_local->next, dst_local_idx += 1) - { - //- rjf: push local's locations - RDI_U64 location_block_idx_first = dst_location_block_idx; - for(RDIM_LocationCase *loccase = src_local->locset.first_location_case; - loccase != 0; - loccase = loccase->next, dst_location_block_idx += 1) - { - // rjf: fill location block - RDI_LocationBlock *dst_locblock = &location_blocks[dst_location_block_idx]; - dst_locblock->scope_off_first = loccase->voff_range.min; - dst_locblock->scope_off_opl = loccase->voff_range.max; - dst_locblock->location_data_off = location_data_blobs.total_size; - - // rjf: serialize location into location data - RDIM_Location *src_location = loccase->location; - { - // rjf: nil location - if(src_location == 0) - { - rdim_str8_list_push_align(scratch.arena, &location_data_blobs, 8); - rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_lit("\0")); - } - - // rjf: valid location - else switch(src_location->kind) - { - // rjf: catchall unsupported case - default: - { - rdim_str8_list_push_align(scratch.arena, &location_data_blobs, 8); - rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_lit("\0")); - }break; - - // rjf: bytecode streams - case RDI_LocationKind_AddrBytecodeStream: - case RDI_LocationKind_ValBytecodeStream: - { - rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, rdim_str8_struct(&src_location->kind))); - for(RDIM_EvalBytecodeOp *op_node = src_location->bytecode.first_op; - op_node != 0; - op_node = op_node->next) - { - RDI_U8 op_data[9]; - op_data[0] = op_node->op; - rdim_memcpy(op_data + 1, &op_node->p, op_node->p_size); - RDIM_String8 op_data_str = rdim_str8(op_data, 1 + op_node->p_size); - rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, op_data_str)); - } - { - RDI_U64 data = 0; - RDIM_String8 data_str = rdim_str8((RDI_U8 *)&data, 1); - rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, data_str)); - } - }break; - - // rjf: simple addr+off cases - case RDI_LocationKind_AddrRegPlusU16: - case RDI_LocationKind_AddrAddrRegPlusU16: - { - RDI_LocationRegPlusU16 loc = {0}; - loc.kind = src_location->kind; - loc.reg_code = src_location->reg_code; - loc.offset = src_location->offset; - rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, rdim_str8_struct(&loc))); - }break; - - // rjf: register cases - case RDI_LocationKind_ValReg: - { - RDI_LocationReg loc = {0}; - loc.kind = src_location->kind; - loc.reg_code = src_location->reg_code; - rdim_str8_list_push(scratch.arena, &location_data_blobs, rdim_str8_copy(scratch.arena, rdim_str8_struct(&loc))); - }break; - } - } - } - RDI_U64 location_block_idx_opl = dst_location_block_idx; - - //- rjf: fill local - RDI_Local *dst_local = &locals[dst_local_idx]; - dst_local->kind = src_local->kind; - dst_local->name_string_idx = rdim_bake_idx_from_string(strings, src_local->name); - dst_local->type_idx = (RDI_U32)rdim_idx_from_type(src_local->type); // TODO(rjf): @u64_to_u32 - dst_local->location_first = (RDI_U32)location_block_idx_first; // TODO(rjf): @u64_to_u32 - dst_local->location_opl = (RDI_U32)location_block_idx_opl; // TODO(rjf): @u64_to_u32 - } - RDI_U64 local_idx_opl = dst_local_idx; - - //- rjf: fill scope - dst_scope->proc_idx = (RDI_U32)rdim_idx_from_symbol(src_scope->symbol); // TODO(rjf): @u64_to_u32 - dst_scope->parent_scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope->parent_scope); // TODO(rjf): @u64_to_u32 - dst_scope->first_child_scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope->first_child); // TODO(rjf): @u64_to_u32 - dst_scope->next_sibling_scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope->next_sibling); // TODO(rjf): @u64_to_u32 - dst_scope->voff_range_first = (RDI_U32)voff_idx_first; // TODO(rjf): @u64_to_u32 - dst_scope->voff_range_opl = (RDI_U32)voff_idx_opl; // TODO(rjf): @u64_to_u32 - dst_scope->local_first = (RDI_U32)local_idx_first; // TODO(rjf): @u64_to_u32 - dst_scope->local_count = (RDI_U32)(local_idx_opl - local_idx_first); // TODO(rjf): @u64_to_u32 - } - } - } - - //////////////////////////// - //- rjf: build flattened location data - // - RDIM_String8 location_data_blob = {0}; - RDIM_ProfScope("build flattened location data") - { - location_data_blob = rdim_str8_list_join(arena, &location_data_blobs, rdim_str8_lit("")); - } - - //////////////////////////// - //- rjf: push all sections - // - RDIM_BakeSectionList sections = {0}; - RDIM_ProfScope("push all symbol info sections") - { - rdim_bake_section_list_push_new_unpacked(arena, §ions, scopes, sizeof(RDI_Scope) * (params->scopes.total_count+1), RDI_SectionKind_Scopes, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, scope_voffs, sizeof(RDI_U64) * (params->scopes.scope_voff_count+1), RDI_SectionKind_ScopeVOffData, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, locals, sizeof(RDI_Local) * (params->scopes.local_count+1), RDI_SectionKind_Locals, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, location_blocks, sizeof(RDI_LocationBlock) * (params->scopes.location_count+1), RDI_SectionKind_LocationBlocks, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, location_data_blob.str, location_data_blob.size, RDI_SectionKind_LocationData, 0); - } - rdim_scratch_end(scratch); - return sections; -} - -//- rjf: scope vmap - -RDI_PROC RDIM_BakeSectionList -rdim_bake_scope_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params) -{ - //- rjf: build scope vmap - RDIM_BakeVMap scope_vmap = {0}; - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - // rjf: allocate keys/markers - RDI_U64 marker_count = params->scopes.scope_voff_count; - RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); - RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); - - // rjf: fill - { - RDIM_SortKey *key_ptr = keys; - RDIM_VMapMarker *marker_ptr = markers; - for(RDIM_ScopeChunkNode *chunk_n = params->scopes.first; chunk_n != 0; chunk_n = chunk_n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < chunk_n->count; chunk_idx += 1) - { - RDIM_Scope *src_scope = &chunk_n->v[chunk_idx]; - RDI_U32 scope_idx = (RDI_U32)rdim_idx_from_scope(src_scope); // TODO(rjf): @u64_to_u32 - for(RDIM_Rng1U64Node *n = src_scope->voff_ranges.first; n != 0; n = n->next) - { - key_ptr->key = n->v.min; - key_ptr->val = marker_ptr; - marker_ptr->idx = scope_idx; - marker_ptr->begin_range = 1; - key_ptr += 1; - marker_ptr += 1; - - key_ptr->key = n->v.max; - key_ptr->val = marker_ptr; - marker_ptr->idx = scope_idx; - marker_ptr->begin_range = 0; - key_ptr += 1; - marker_ptr += 1; - } - } - } - } - - // rjf: produce vmap - scope_vmap = rdim_bake_vmap_from_markers(arena, markers, keys, marker_count); - rdim_scratch_end(scratch); - } - - //- rjf: build sections - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, scope_vmap.vmap, sizeof(RDI_VMapEntry)*(scope_vmap.count+1), RDI_SectionKind_ScopeVMap, 0); - return sections; -} - -//- rjf: name maps - -RDI_PROC RDIM_BakeSectionList -rdim_bake_top_level_name_map_section_list_from_params_maps(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeParams *params, RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT]) -{ - RDIM_BakeSectionList sections = {0}; - - //- rjf: allocate & fill baked name maps - RDI_NameMap *dst_maps = rdim_push_array(arena, RDI_NameMap, RDI_NameMapKind_COUNT); - { - RDI_U64 dst_map_idx = 0; - RDI_U64 dst_map_bucket_idx = 0; - RDI_U64 dst_map_node_idx = 0; - for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); - k < RDI_NameMapKind_COUNT; - k = (RDI_NameMapKind)(k+1)) - { - RDI_NameMap *dst_map = &dst_maps[dst_map_idx]; - RDIM_BakeNameMap *src_map = name_maps[k]; - if(src_map == 0 || src_map->name_count == 0) { continue; } - dst_map->bucket_base_idx = (RDI_U32)dst_map_bucket_idx; // TODO(rjf): @u64_to_u32 - dst_map->node_base_idx = (RDI_U32)dst_map_node_idx; // TODO(rjf): @u64_to_u32 - dst_map->bucket_count = (RDI_U32)src_map->name_count; // TODO(rjf): @u64_to_u32 - dst_map->node_count = (RDI_U32)src_map->name_count; // TODO(rjf): @u64_to_u32 - dst_map_idx += 1; - } - } - - // rjf: push section for all name maps - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_maps, sizeof(RDI_NameMap)*RDI_NameMapKind_COUNT, RDI_SectionKind_NameMaps, 0); - return sections; -} - -RDI_PROC RDIM_BakeSectionList -rdim_bake_name_map_section_list_from_params_kind_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeParams *params, RDI_NameMapKind k, RDIM_BakeNameMap *map) -{ - RDIM_BakeSectionList sections = {0}; - if(map != 0 && map->name_count != 0) - { - RDI_U32 baked_buckets_count = map->name_count; - RDI_U32 baked_nodes_count = map->name_count; - RDI_NameMapBucket *baked_buckets = rdim_push_array(arena, RDI_NameMapBucket, baked_buckets_count); - RDI_NameMapNode *baked_nodes = rdim_push_array_no_zero(arena, RDI_NameMapNode, baked_nodes_count); - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - // rjf: setup the final bucket layouts - typedef struct RDIM_NameMapSemiNode RDIM_NameMapSemiNode; - struct RDIM_NameMapSemiNode - { - RDIM_NameMapSemiNode *next; - RDIM_BakeNameMapNode *node; - }; - typedef struct RDIM_NameMapSemiBucket RDIM_NameMapSemiBucket; - struct RDIM_NameMapSemiBucket - { - RDIM_NameMapSemiNode *first; - RDIM_NameMapSemiNode *last; - RDI_U64 count; - }; - RDIM_NameMapSemiBucket *sbuckets = rdim_push_array(scratch.arena, RDIM_NameMapSemiBucket, baked_buckets_count); - for(RDIM_BakeNameMapNode *node = map->first; - node != 0; - node = node->order_next) - { - RDI_U64 hash = rdi_hash(node->string.str, node->string.size); - RDI_U64 bi = hash%baked_buckets_count; - RDIM_NameMapSemiNode *snode = rdim_push_array(scratch.arena, RDIM_NameMapSemiNode, 1); - SLLQueuePush(sbuckets[bi].first, sbuckets[bi].last, snode); - snode->node = node; - sbuckets[bi].count += 1; - } - - // rjf: convert to serialized buckets & nodes - { - RDI_NameMapBucket *bucket_ptr = baked_buckets; - RDI_NameMapNode *node_ptr = baked_nodes; - for(RDI_U32 i = 0; i < baked_buckets_count; i += 1, bucket_ptr += 1) - { - bucket_ptr->first_node = (RDI_U32)(node_ptr - baked_nodes); - bucket_ptr->node_count = sbuckets[i].count; - for(RDIM_NameMapSemiNode *snode = sbuckets[i].first; - snode != 0; - snode = snode->next) - { - RDIM_BakeNameMapNode *node = snode->node; - - // rjf: cons name and index(es) - RDI_U32 string_idx = rdim_bake_idx_from_string(strings, node->string); - RDI_U32 match_count = node->val_count; - RDI_U32 idx = 0; - if(match_count == 1) - { - idx = node->val_first->val[0]; - } - else - { - RDI_U64 temp_pos = rdim_arena_pos(scratch.arena); - RDI_U32 *idx_run = rdim_push_array_no_zero(scratch.arena, RDI_U32, match_count); - RDI_U32 *idx_ptr = idx_run; - for(RDIM_BakeNameMapValNode *idxnode = node->val_first; - idxnode != 0; - idxnode = idxnode->next) - { - for(RDI_U32 i = 0; i < sizeof(idxnode->val)/sizeof(idxnode->val[0]); i += 1) - { - if(idxnode->val[i] == 0) - { - goto dblbreak; - } - *idx_ptr = idxnode->val[i]; - idx_ptr += 1; - } - } - dblbreak:; - idx = rdim_bake_idx_from_idx_run(idx_runs, idx_run, match_count); - rdim_arena_pop_to(scratch.arena, temp_pos); - } - - // rjf: write to node - node_ptr->string_idx = string_idx; - node_ptr->match_count = match_count; - node_ptr->match_idx_or_idx_run_first = idx; - node_ptr += 1; - } - } - } - rdim_scratch_end(scratch); - } - - // rjf: sections for buckets/nodes - rdim_bake_section_list_push_new_unpacked(arena, §ions, baked_buckets, sizeof(RDI_NameMapBucket)* baked_buckets_count, RDI_SectionKind_NameMapBuckets, (RDI_U64)k); - rdim_bake_section_list_push_new_unpacked(arena, §ions, baked_nodes, sizeof(RDI_NameMapNode) * baked_nodes_count, RDI_SectionKind_NameMapNodes, (RDI_U64)k); - } - return sections; -} - -//- rjf: file paths - -RDI_PROC RDIM_BakeSectionList -rdim_bake_file_path_section_list_from_path_tree(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree) -{ - RDI_U32 dst_nodes_count = path_tree->count; - RDI_FilePathNode *dst_nodes = rdim_push_array(arena, RDI_FilePathNode, dst_nodes_count); - { - RDI_U32 dst_node_idx = 0; - for(RDIM_BakePathNode *src_node = path_tree->first; - src_node != 0; - src_node = src_node->next_order, dst_node_idx += 1) - { - RDI_FilePathNode *dst_node = &dst_nodes[dst_node_idx]; - dst_node->name_string_idx = rdim_bake_idx_from_string(strings, src_node->name); - dst_node->source_file_idx = rdim_idx_from_src_file(src_node->src_file); - if(src_node->parent != 0) - { - dst_node->parent_path_node = src_node->parent->idx; - } - if(src_node->first_child != 0) - { - dst_node->first_child = src_node->first_child->idx; - } - if(src_node->next_sibling != 0) - { - dst_node->next_sibling = src_node->next_sibling->idx; - } - } - } - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_nodes, sizeof(RDI_FilePathNode)*dst_nodes_count, RDI_SectionKind_FilePathNodes, 0); - return sections; -} - -//- rjf: strings - -RDI_PROC RDIM_BakeSectionList -rdim_bake_string_section_list_from_string_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings) -{ - RDIM_BakeSectionList sections = {0}; - RDI_U32 *str_offs = rdim_push_array_no_zero(arena, RDI_U32, strings->total_count + 1); - RDI_U32 off_cursor = 0; - { - RDI_U32 *off_ptr = str_offs; - *off_ptr = 0; - off_ptr += 1; - for(RDI_U64 slot_idx = 0; slot_idx < strings->slots_count; slot_idx += 1) - { - for(RDIM_BakeStringChunkNode *n = strings->slots[slot_idx].first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) - { - RDIM_BakeString *bake_string = &n->v[chunk_idx]; - *off_ptr = off_cursor; - off_cursor += bake_string->string.size; - off_ptr += 1; - } - } - } - } - RDI_U8 *buf = rdim_push_array(arena, RDI_U8, off_cursor); - { - RDI_U8 *ptr = buf; - for(RDI_U64 slot_idx = 0; slot_idx < strings->slots_count; slot_idx += 1) - { - for(RDIM_BakeStringChunkNode *n = strings->slots[slot_idx].first; n != 0; n = n->next) - { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) - { - RDIM_BakeString *bake_string = &n->v[chunk_idx]; - rdim_memcpy(ptr, bake_string->string.str, bake_string->string.size); - ptr += bake_string->string.size; - } - } - } - } - rdim_bake_section_list_push_new_unpacked(arena, §ions, str_offs, sizeof(RDI_U32)*(strings->total_count+1), RDI_SectionKind_StringTable, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, buf, off_cursor, RDI_SectionKind_StringData, 0); - return sections; -} - -//- rjf: index runs - -RDI_PROC RDIM_BakeSectionList -rdim_bake_idx_run_section_list_from_idx_run_map(RDIM_Arena *arena, RDIM_BakeIdxRunMap *idx_runs) -{ - RDIM_BakeSectionList sections = {0}; - RDI_U32 *idx_data = rdim_push_array_no_zero(arena, RDI_U32, idx_runs->idx_count); - { - RDI_U32 *out_ptr = idx_data; - RDI_U32 *opl = out_ptr + idx_runs->idx_count; - for(RDIM_BakeIdxRunNode *node = idx_runs->order_first; - node != 0 && out_ptr < opl; - node = node->order_next) - { - rdim_memcpy(out_ptr, node->idx_run, sizeof(*node->idx_run)*node->count); - out_ptr += node->count; - } - } - rdim_bake_section_list_push_new_unpacked(arena, §ions, idx_data, sizeof(RDI_U32)*idx_runs->idx_count, RDI_SectionKind_IndexRuns, 0); - return sections; -} - -#endif - -//////////////////////////////// -//~ rjf: [Serializing] Baked Data Section List -> Serialized Binary Strings - -#if 0 -RDI_PROC RDIM_String8List -rdim_serialized_strings_from_params_bake_section_list(RDIM_Arena *arena, RDIM_BakeParams *params, RDIM_BakeSectionList *sections) -{ - RDIM_String8List strings; - rdim_memzero_struct(&strings); - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - //- rjf: make table for actually laid out sections - RDI_U64 section_count = RDI_SectionKind_COUNT; - RDIM_BakeSection **bake_sections = rdim_push_array(scratch.arena, RDIM_BakeSection *, section_count); - for(RDIM_BakeSectionNode *n = sections->first; n != 0; n = n->next) - { - RDIM_BakeSection *bake_section = &n->v; - RDI_U64 idx = (RDI_U64)bake_section->tag; - if(0 <= idx && idx < section_count) - { - if(bake_sections[idx] != 0) - { - // TODO(rjf): error - malformed input! we have a duplicate section. - } - else - { - bake_sections[idx] = bake_section; - } - } - } - - //- rjf: push empty header & data section table - RDI_Header *rdi_header = rdim_push_array(arena, RDI_Header, 1); - RDI_Section *rdi_sections = rdim_push_array(arena, RDI_Section, section_count); - rdim_str8_list_push(arena, &strings, rdim_str8_struct(rdi_header)); - rdim_str8_list_push_align(arena, &strings, 8); - U32 data_section_off = (U32)strings.total_size; - rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)rdi_sections, sizeof(RDI_Section)*section_count)); - - // rjf: fill baked header - { - rdi_header->magic = RDI_MAGIC_CONSTANT; - rdi_header->encoding_version = RDI_ENCODING_VERSION; - rdi_header->data_section_off = data_section_off; - rdi_header->data_section_count = section_count; - } - - // rjf: fill baked data section table - U64 dst_idx = 0; - for(RDI_U64 src_idx = 0; src_idx < section_count; src_idx += 1, dst_idx += 1) - { - RDIM_BakeSection *src = bake_sections[src_idx]; - if(src == 0) { continue; } - RDI_Section *dst = rdi_sections+dst_idx; - U64 data_section_off = 0; - if(src->encoded_size != 0) - { - rdim_str8_list_push_align(arena, &strings, 8); - data_section_off = strings.total_size; - rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)src->data, src->encoded_size)); - } - dst->encoding = src->encoding; - dst->off = data_section_off; - dst->encoded_size = src->encoded_size; - dst->unpacked_size = src->unpacked_size; - } - - rdim_scratch_end(scratch); - } - return strings; -} -#endif diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index da4d0ee2..80122c0a 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -1508,71 +1508,4 @@ RDI_PROC RDIM_SerializedSection rdim_serialized_section_make_unpacked(void *data RDI_PROC RDIM_SerializedSectionBundle rdim_serialized_section_bundle_from_bake_results(RDIM_BakeResults *results); RDI_PROC RDIM_String8List rdim_file_blobs_from_section_bundle(RDIM_Arena *arena, RDIM_SerializedSectionBundle *bundle); -//////////////////////////////// -//~ rjf: [Baking] Build Artifacts -> Data Section Lists - -#if 0 -//- rjf: top-level info -RDI_PROC RDIM_BakeSectionList rdim_bake_top_level_info_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); - -//- rjf: binary sections -RDI_PROC RDIM_BakeSectionList rdim_bake_binary_section_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); - -//- rjf: units -RDI_PROC RDIM_BakeSectionList rdim_bake_unit_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params); - -//- rjf: unit vmap -RDI_PROC RDIM_BakeSectionList rdim_bake_unit_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params); - -//- rjf: source files -RDI_PROC RDIM_BakeSectionList rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params); - -//- rjf: line tables -RDI_PROC RDIM_BakeSectionList rdim_bake_line_table_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params); - -//- rjf: type nodes -RDI_PROC RDIM_BakeSectionList rdim_bake_type_node_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeParams *params); - -//- rjf: UDTs -RDI_PROC RDIM_BakeSectionList rdim_bake_udt_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); - -//- rjf: global variables -RDI_PROC RDIM_BakeSectionList rdim_bake_global_variable_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); - -//- rjf: global vmap -RDI_PROC RDIM_BakeSectionList rdim_bake_global_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params); - -//- rjf: thread variables -RDI_PROC RDIM_BakeSectionList rdim_bake_thread_variable_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); - -//- rjf: procedures -RDI_PROC RDIM_BakeSectionList rdim_bake_procedure_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); - -//- rjf: scopes -RDI_PROC RDIM_BakeSectionList rdim_bake_scope_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); - -//- rjf: scope vmap -RDI_PROC RDIM_BakeSectionList rdim_bake_scope_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params); - -//- rjf: name maps -RDI_PROC RDIM_BakeSectionList rdim_bake_top_level_name_map_section_list_from_params_maps(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeParams *params, RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT]); -RDI_PROC RDIM_BakeSectionList rdim_bake_name_map_section_list_from_params_kind_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeParams *params, RDI_NameMapKind k, RDIM_BakeNameMap *map); - -//- rjf: file paths -RDI_PROC RDIM_BakeSectionList rdim_bake_file_path_section_list_from_path_tree(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree); - -//- rjf: strings -RDI_PROC RDIM_BakeSectionList rdim_bake_string_section_list_from_string_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings); - -//- rjf: index runs -RDI_PROC RDIM_BakeSectionList rdim_bake_idx_run_section_list_from_idx_run_map(RDIM_Arena *arena, RDIM_BakeIdxRunMap *idx_runs); -#endif - -//////////////////////////////// -//~ rjf: [Serializing] Baked Data Section List -> Serialized Binary Strings - -#if 0 -RDI_PROC RDIM_String8List rdim_serialized_strings_from_params_bake_section_list(RDIM_Arena *arena, RDIM_BakeParams *params, RDIM_BakeSectionList *sections); -#endif - #endif // RDI_MAKE_H From 300b14ffb4801b8aa85d6d88a2a278ad732babab Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 7 Jun 2024 11:45:18 -0700 Subject: [PATCH 20/44] pass over high level composite rdi parsing helpers --- src/ctrl/ctrl_core.c | 18 ++- src/lib_rdi_format/rdi_format_parse.c | 157 ++++++++++++++++++++++++-- src/lib_rdi_format/rdi_format_parse.h | 28 ++++- 3 files changed, 189 insertions(+), 14 deletions(-) diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 5cf42018..722af5ce 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -2994,7 +2994,8 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_MachineID m U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); for(U32 match_i = 0; match_i < id_count; match_i += 1) { - U64 proc_voff = rdi_first_voff_from_proc_idx(rdi, ids[match_i]); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, ids[match_i]); + U64 proc_voff = rdi_first_voff_from_procedure(rdi, procedure); U64 proc_vaddr = proc_voff + base_vaddr; DMN_Trap trap = {process, proc_vaddr + voff, (U64)bp}; dmn_trap_chunk_list_push(arena, traps_out, 256, &trap); @@ -4262,7 +4263,8 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) procedure_id = ids[0]; } } - U64 voff = rdi_first_voff_from_proc_idx(rdi, procedure_id); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); + U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { entries_found = 1; @@ -4290,7 +4292,8 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) procedure_id = ids[0]; } } - U64 voff = rdi_first_voff_from_proc_idx(rdi, procedure_id); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); + U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { entries_found = 1; @@ -4317,7 +4320,8 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) procedure_id = ids[0]; } } - U64 voff = rdi_first_voff_from_proc_idx(rdi, procedure_id); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); + U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { DMN_Trap trap = {process->handle, module_base_vaddr + voff}; @@ -4350,7 +4354,8 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) procedure_id = ids[0]; } } - U64 voff = rdi_first_voff_from_proc_idx(rdi, procedure_id); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); + U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { entries_found = 1; @@ -4394,7 +4399,8 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) procedure_id = ids[0]; } } - U64 voff = rdi_first_voff_from_proc_idx(rdi, procedure_id); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); + U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { entries_found = 1; diff --git a/src/lib_rdi_format/rdi_format_parse.c b/src/lib_rdi_format/rdi_format_parse.c index bd54876c..b7d7f825 100644 --- a/src/lib_rdi_format/rdi_format_parse.c +++ b/src/lib_rdi_format/rdi_format_parse.c @@ -500,15 +500,158 @@ rdi_matches_from_map_node(RDI_Parsed *p, RDI_NameMapNode *node, RDI_U32 *n_out) //- procedures -RDI_PROC RDI_U64 -rdi_first_voff_from_proc_idx(RDI_Parsed *rdi, RDI_U32 proc_idx) +RDI_PROC RDI_Procedure * +rdi_procedure_from_name(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size) { - RDI_U64 result = 0; + RDI_NameMap *map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures); + RDI_ParsedNameMap map_parsed = {0}; + rdi_parsed_from_name_map(rdi, map, &map_parsed); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map_parsed, name, name_size); + RDI_U32 id_count = 0; + RDI_U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); + RDI_U32 procedure_idx = 0; + if(id_count > 0) { - RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx); - RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx); - RDI_U64 *voffs = rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_first); - result = *voffs; + procedure_idx = ids[0]; + } + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_idx); + return procedure; +} + +RDI_PROC RDI_Procedure * +rdi_procedure_from_name_cstr(RDI_Parsed *rdi, char *cstr) +{ + RDI_Procedure *result = rdi_procedure_from_name(rdi, (RDI_U8 *)cstr, rdi_cstring_length(cstr)); + return result; +} + +RDI_PROC RDI_Scope * +rdi_root_scope_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure) +{ + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx); + return scope; +} + +RDI_PROC RDI_U64 +rdi_first_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure) +{ + RDI_Scope *scope = rdi_root_scope_from_procedure(rdi, procedure); + RDI_U64 result = rdi_first_voff_from_scope(rdi, scope); + return result; +} + +RDI_PROC RDI_U64 +rdi_opl_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure) +{ + RDI_Scope *scope = rdi_root_scope_from_procedure(rdi, procedure); + RDI_U64 result = rdi_opl_voff_from_scope(rdi, scope); + return result; +} + +//- scopes + +RDI_PROC RDI_U64 +rdi_first_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope) +{ + RDI_U64 *voffs = rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_first); + RDI_U64 result = *voffs; + return result; +} + +RDI_PROC RDI_U64 +rdi_opl_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope) +{ + RDI_U64 *voffs = rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_opl); + RDI_U64 result = *voffs; + return result; +} + +//- units + +RDI_PROC RDI_Unit * +rdi_unit_from_voff(RDI_Parsed *rdi, RDI_U64 voff) +{ + RDI_U32 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, voff); + RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); + return unit; +} + +RDI_PROC RDI_LineTable * +rdi_line_table_from_unit(RDI_Parsed *rdi, RDI_Unit *unit) +{ + RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); + return line_table; +} + +//- line info + +RDI_PROC RDI_Line +rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff) +{ + RDI_Unit *unit = rdi_unit_from_voff(rdi, voff); + RDI_LineTable *line_table = rdi_line_table_from_unit(rdi, unit); + RDI_Line line = rdi_line_from_line_table_voff(rdi, line_table, voff); + return line; +} + +RDI_PROC RDI_Line +rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff) +{ + RDI_ParsedLineTable parsed = {0}; + rdi_parsed_from_line_table(rdi, line_table, &parsed); + RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed, voff); + RDI_Line result = {0}; + if(line_info_idx < parsed.count) + { + result = parsed.lines[line_info_idx]; } return result; } + +RDI_PROC RDI_SourceFile * +rdi_source_file_from_line(RDI_Parsed *rdi, RDI_Line *line) +{ + RDI_SourceFile *result = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx); + return result; +} + +//- source files + +RDI_PROC RDI_U8 * +rdi_normal_path_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U64 *len_out) +{ + return rdi_string_from_idx(rdi, src_file->normal_full_path_string_idx, len_out); +} + +RDI_PROC RDI_FilePathNode * +rdi_file_path_node_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file) +{ + RDI_FilePathNode *result = rdi_element_from_name_idx(rdi, FilePathNodes, src_file->file_path_node_idx); + return result; +} + +//- file path nodes + +RDI_PROC RDI_FilePathNode * +rdi_parent_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node) +{ + RDI_FilePathNode *result = rdi_element_from_name_idx(rdi, FilePathNodes, node->parent_path_node); + return result; +} + +RDI_PROC RDI_U8 * +rdi_name_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node, RDI_U64 *len_out) +{ + return rdi_string_from_idx(rdi, node->name_string_idx, len_out); +} + +//////////////////////////////// +//~ Parser Helpers + +RDI_PROC RDI_U64 +rdi_cstring_length(char *cstr) +{ + RDI_U64 result = 0; + for(;cstr[result] != 0; result += 1){} + return result; +} diff --git a/src/lib_rdi_format/rdi_format_parse.h b/src/lib_rdi_format/rdi_format_parse.h index e056a7d3..f75ae369 100644 --- a/src/lib_rdi_format/rdi_format_parse.h +++ b/src/lib_rdi_format/rdi_format_parse.h @@ -145,11 +145,37 @@ RDI_PROC RDI_U32 *rdi_matches_from_map_node(RDI_Parsed *p, RDI_NameMapNode *node //~ High-Level Composite Lookup Functions //- procedures -RDI_PROC RDI_U64 rdi_first_voff_from_proc_idx(RDI_Parsed *rdi, RDI_U32 proc_idx); +RDI_PROC RDI_Procedure *rdi_procedure_from_name(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size); +RDI_PROC RDI_Procedure *rdi_procedure_from_name_cstr(RDI_Parsed *rdi, char *cstr); +RDI_PROC RDI_Scope *rdi_root_scope_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure); +RDI_PROC RDI_U64 rdi_first_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure); +RDI_PROC RDI_U64 rdi_opl_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure); + +//- scopes +RDI_PROC RDI_U64 rdi_first_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope); +RDI_PROC RDI_U64 rdi_opl_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope); + +//- units +RDI_PROC RDI_Unit *rdi_unit_from_voff(RDI_Parsed *rdi, RDI_U64 voff); +RDI_PROC RDI_LineTable *rdi_line_table_from_unit(RDI_Parsed *rdi, RDI_Unit *unit); + +//- line info +RDI_PROC RDI_Line rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff); +RDI_PROC RDI_Line rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff); +RDI_PROC RDI_SourceFile *rdi_source_file_from_line(RDI_Parsed *rdi, RDI_Line *line); + +//- source files +RDI_PROC RDI_U8 *rdi_normal_path_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U64 *len_out); +RDI_PROC RDI_FilePathNode *rdi_file_path_node_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file); + +//- file path nodes +RDI_PROC RDI_FilePathNode *rdi_parent_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node); +RDI_PROC RDI_U8 *rdi_name_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node, RDI_U64 *len_out); //////////////////////////////// //~ Parser Helpers #define rdi_parse__min(a,b) (((a)<(b))?(a):(b)) +RDI_PROC RDI_U64 rdi_cstring_length(char *cstr); #endif // RDI_FORMAT_PARSE_H From 9dcb5a209a9267779562eaaf0c5d8ec8ecd15856 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 7 Jun 2024 13:45:26 -0700 Subject: [PATCH 21/44] more progress on rdi parsing library high-level composite helpers; update breakpad_from_pdb to new format/maker changes --- src/lib_rdi_format/rdi_format_parse.c | 86 +++++++++ src/lib_rdi_format/rdi_format_parse.h | 44 ++++- .../rdi_breakpad_from_pdb_main.c | 165 ++++++++---------- 3 files changed, 203 insertions(+), 92 deletions(-) diff --git a/src/lib_rdi_format/rdi_format_parse.c b/src/lib_rdi_format/rdi_format_parse.c index b7d7f825..87ccf1bc 100644 --- a/src/lib_rdi_format/rdi_format_parse.c +++ b/src/lib_rdi_format/rdi_format_parse.c @@ -525,6 +525,12 @@ rdi_procedure_from_name_cstr(RDI_Parsed *rdi, char *cstr) return result; } +RDI_PROC RDI_U8 * +rdi_name_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure, RDI_U64 *len_out) +{ + return rdi_string_from_idx(rdi, procedure->name_string_idx, len_out); +} + RDI_PROC RDI_Scope * rdi_root_scope_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure) { @@ -548,6 +554,14 @@ rdi_opl_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure) return result; } +RDI_PROC RDI_Procedure * +rdi_procedure_from_voff(RDI_Parsed *rdi, RDI_U64 voff) +{ + RDI_Scope *scope = rdi_scope_from_voff(rdi, voff); + RDI_Procedure *procedure = rdi_procedure_from_scope(rdi, scope); + return procedure; +} + //- scopes RDI_PROC RDI_U64 @@ -566,6 +580,21 @@ rdi_opl_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope) return result; } +RDI_PROC RDI_Scope * +rdi_scope_from_voff(RDI_Parsed *rdi, RDI_U64 voff) +{ + RDI_U32 idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, idx); + return scope; +} + +RDI_PROC RDI_Procedure * +rdi_procedure_from_scope(RDI_Parsed *rdi, RDI_Scope *scope) +{ + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx); + return procedure; +} + //- units RDI_PROC RDI_Unit * @@ -617,6 +646,31 @@ rdi_source_file_from_line(RDI_Parsed *rdi, RDI_Line *line) //- source files +RDI_PROC RDI_SourceFile * +rdi_source_file_from_normal_path(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size) +{ + RDI_NameMap *map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); + RDI_ParsedNameMap map_parsed = {0}; + rdi_parsed_from_name_map(rdi, map, &map_parsed); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map_parsed, name, name_size); + RDI_U32 id_count = 0; + RDI_U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); + RDI_U32 file_idx = 0; + if(id_count > 0) + { + file_idx = ids[0]; + } + RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, file_idx); + return file; +} + +RDI_PROC RDI_SourceFile * +rdi_source_file_from_normal_path_cstr(RDI_Parsed *rdi, char *cstr) +{ + RDI_SourceFile *result = rdi_source_file_from_normal_path(rdi, (RDI_U8 *)cstr, rdi_cstring_length(cstr)); + return result; +} + RDI_PROC RDI_U8 * rdi_normal_path_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U64 *len_out) { @@ -630,6 +684,38 @@ rdi_file_path_node_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file) return result; } +RDI_PROC RDI_SourceLineMap * +rdi_source_line_map_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file) +{ + RDI_SourceLineMap *result = rdi_element_from_name_idx(rdi, SourceLineMaps, src_file->source_line_map_idx); + return result; +} + +RDI_PROC RDI_U64 +rdi_first_voff_from_source_file_line_num(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U32 line_num) +{ + RDI_SourceLineMap *source_line_map = rdi_source_line_map_from_source_file(rdi, src_file); + RDI_U64 voff = rdi_first_voff_from_source_line_map_num(rdi, source_line_map, line_num); + return voff; +} + +//- source line maps + +RDI_PROC RDI_U64 +rdi_first_voff_from_source_line_map_num(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_U32 line_num) +{ + RDI_ParsedSourceLineMap parsed = {0}; + rdi_parsed_from_source_line_map(rdi, map, &parsed); + RDI_U32 all_voffs_count = 0; + RDI_U64 *all_voffs = rdi_line_voffs_from_num(&parsed, line_num, &all_voffs_count); + RDI_U64 voff = 0; + if(all_voffs_count != 0) + { + voff = all_voffs[0]; + } + return voff; +} + //- file path nodes RDI_PROC RDI_FilePathNode * diff --git a/src/lib_rdi_format/rdi_format_parse.h b/src/lib_rdi_format/rdi_format_parse.h index f75ae369..1e0c097a 100644 --- a/src/lib_rdi_format/rdi_format_parse.h +++ b/src/lib_rdi_format/rdi_format_parse.h @@ -7,6 +7,37 @@ // Defines helper types and functions for extracting data from // RDI files. +//////////////////////////////////////////////////////////////// +//~ Usage Samples +// +#if 0 +// Procedure Name -> Line +{ + RDI_Parsed *rdi = ...; + char *name = "mule_main"; + RDI_Procedure *procedure = rdi_procedure_from_name_cstr(rdi, name); // 1. name -> procedure + RDI_U64 procedure_first_voff = rdi_first_voff_from_procedure(rdi, procedure); // 2. procedure -> virtual offset + RDI_Line line = rdi_line_from_voff(rdi, procedure_first_voff); // 3. virtual offset -> line + RDI_SourceFile *file = rdi_source_file_from_line(rdi, &line); // 4. line -> source file + RDI_U64 file_path_size = 0; // 5. source file -> path + RDI_U8 *file_path = rdi_normal_path_from_source_file(rdi, file, &file_path_size); + printf("%s is at %.*s:%u\n", name, (int)file_path_size, file_path, line.line_num); +} + +// Line -> Procedure Name +{ + RDI_Parsed *rdi = ...; + char *path = "c:/devel/raddebugger/src/mule/mule_main.cpp"; + RDI_U32 line_num = 2557; + RDI_SourceFile *file = rdi_source_file_from_normal_path_cstr(rdi, path); // 1. path -> source file + RDI_U64 voff = rdi_first_voff_from_source_file_line_num(rdi, file, line_num); // 2. (source file, line) -> virtual offset + RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, voff); // 3. virtual offset -> procedure + RDI_U64 name_size = 0; // 4. procedure -> name + RDI_U8 *name = rdi_name_from_procedure(rdi, procedure, &name_size); + printf("%s:%u is inside %.*s\n", path, line_num, (int)name_size, name); +} +#endif + #ifndef RDI_FORMAT_PARSE_H #define RDI_FORMAT_PARSE_H @@ -147,26 +178,37 @@ RDI_PROC RDI_U32 *rdi_matches_from_map_node(RDI_Parsed *p, RDI_NameMapNode *node //- procedures RDI_PROC RDI_Procedure *rdi_procedure_from_name(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size); RDI_PROC RDI_Procedure *rdi_procedure_from_name_cstr(RDI_Parsed *rdi, char *cstr); +RDI_PROC RDI_U8 *rdi_name_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure, RDI_U64 *len_out); RDI_PROC RDI_Scope *rdi_root_scope_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure); RDI_PROC RDI_U64 rdi_first_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure); RDI_PROC RDI_U64 rdi_opl_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure); +RDI_PROC RDI_Procedure *rdi_procedure_from_voff(RDI_Parsed *rdi, RDI_U64 voff); //- scopes RDI_PROC RDI_U64 rdi_first_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope); RDI_PROC RDI_U64 rdi_opl_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope); +RDI_PROC RDI_Scope *rdi_scope_from_voff(RDI_Parsed *rdi, RDI_U64 voff); +RDI_PROC RDI_Procedure *rdi_procedure_from_scope(RDI_Parsed *rdi, RDI_Scope *scope); //- units RDI_PROC RDI_Unit *rdi_unit_from_voff(RDI_Parsed *rdi, RDI_U64 voff); RDI_PROC RDI_LineTable *rdi_line_table_from_unit(RDI_Parsed *rdi, RDI_Unit *unit); -//- line info +//- line tables RDI_PROC RDI_Line rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff); RDI_PROC RDI_Line rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff); RDI_PROC RDI_SourceFile *rdi_source_file_from_line(RDI_Parsed *rdi, RDI_Line *line); //- source files +RDI_PROC RDI_SourceFile *rdi_source_file_from_normal_path(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size); +RDI_PROC RDI_SourceFile *rdi_source_file_from_normal_path_cstr(RDI_Parsed *rdi, char *cstr); RDI_PROC RDI_U8 *rdi_normal_path_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U64 *len_out); RDI_PROC RDI_FilePathNode *rdi_file_path_node_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file); +RDI_PROC RDI_SourceLineMap *rdi_source_line_map_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file); +RDI_PROC RDI_U64 rdi_first_voff_from_source_file_line_num(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U32 line_num); + +//- source line maps +RDI_PROC RDI_U64 rdi_first_voff_from_source_line_map_num(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_U32 line_num); //- file path nodes RDI_PROC RDI_FilePathNode *rdi_parent_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node); diff --git a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c index b1578399..9a32b06e 100644 --- a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c +++ b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c @@ -59,61 +59,27 @@ struct P2B_BakeUnitVMapIn RDIM_UnitChunkList *units; }; -typedef struct P2B_BakeUnitVMapOut P2B_BakeUnitVMapOut; -struct P2B_BakeUnitVMapOut -{ - RDI_VMapEntry *vmap_entries; - RDI_U64 vmap_entries_count; -}; - internal TS_TASK_FUNCTION_DEF(p2b_bake_unit_vmap_task__entry_point) { P2B_BakeUnitVMapIn *in = (P2B_BakeUnitVMapIn *)p; - P2B_BakeUnitVMapOut *out = push_array(arena, P2B_BakeUnitVMapOut, 1); - RDIM_UnitVMapBakeResult bake = rdim_bake_unit_vmap(arena, in->units); - out->vmap_entries = bake.vmap.vmap; - out->vmap_entries_count = bake.vmap.count+1; + RDIM_UnitVMapBakeResult *out = push_array(arena, RDIM_UnitVMapBakeResult, 1); + *out = rdim_bake_unit_vmap(arena, in->units); return out; } -//- rjf: per-unit baking +//- rjf: line table baking -typedef struct P2B_BakeUnitIn P2B_BakeUnitIn; -struct P2B_BakeUnitIn +typedef struct P2B_BakeLineTablesIn P2B_BakeLineTablesIn; +struct P2B_BakeLineTablesIn { - RDIM_Unit *unit; + RDIM_LineTableChunkList *line_tables; }; -typedef struct P2B_BakeUnitOut P2B_BakeUnitOut; -struct P2B_BakeUnitOut +internal TS_TASK_FUNCTION_DEF(p2b_bake_line_table_task__entry_point) { - U64 unit_line_count; - U64 *unit_line_voffs; - RDI_Line *unit_lines; -}; - -internal TS_TASK_FUNCTION_DEF(p2b_bake_unit_task__entry_point) -{ - P2B_BakeUnitIn *in = (P2B_BakeUnitIn *)p; - P2B_BakeUnitOut *out = push_array(arena, P2B_BakeUnitOut, 1); - RDIM_BakeSectionList sections = rdim_bake_section_list_from_unit(arena, in->unit); - RDIM_BakeSection *voffs_section = 0; - RDIM_BakeSection *lines_section = 0; - for(RDIM_BakeSectionNode *n = sections.first; n != 0; n = n->next) - { - switch(n->v.tag) - { - default:{}break; - case RDI_SectionKind_LineInfoVoffs:{voffs_section = &n->v;}break; - case RDI_SectionKind_LineInfoData: {lines_section = &n->v;}break; - } - } - if(voffs_section != 0 && lines_section != 0) - { - out->unit_line_count = lines_section->unpacked_size/sizeof(RDI_Line); - out->unit_line_voffs = (U64 *)voffs_section->data; - out->unit_lines = (RDI_Line *)lines_section->data; - } + P2B_BakeLineTablesIn *in = (P2B_BakeLineTablesIn *)p; + RDIM_LineTableBakeResult *out = push_array(arena, RDIM_LineTableBakeResult, 1); + *out = rdim_bake_line_tables(arena, in->line_tables); return out; } @@ -124,8 +90,9 @@ struct P2B_DumpProcChunkIn { RDI_VMapEntry *unit_vmap; U32 unit_vmap_count; - P2B_BakeUnitOut **bake_units_out; - U64 bake_units_out_count; + U32 *unit_line_table_idxs; + U64 unit_count; + RDIM_LineTableBakeResult *line_tables_bake; RDIM_SymbolChunkNode *chunk; }; @@ -133,6 +100,12 @@ internal TS_TASK_FUNCTION_DEF(p2b_dump_proc_chunk_task__entry_point) { P2B_DumpProcChunkIn *in = (P2B_DumpProcChunkIn *)p; String8List *out = push_array(arena, String8List, 1); + RDI_LineTable *line_tables = in->line_tables_bake->line_tables; + RDI_U64 line_tables_count = in->line_tables_bake->line_tables_count; + RDI_U64 *line_table_voffs = in->line_tables_bake->line_table_voffs; + RDI_U64 line_table_voffs_count = in->line_tables_bake->line_table_voffs_count; + RDI_Line *line_table_lines = in->line_tables_bake->line_table_lines; + RDI_U64 line_table_lines_count = in->line_tables_bake->line_table_lines_count; for(U64 idx = 0; idx < in->chunk->count; idx += 1) { // NOTE(rjf): breakpad does not support multiple voff ranges per procedure. @@ -146,34 +119,45 @@ internal TS_TASK_FUNCTION_DEF(p2b_dump_proc_chunk_task__entry_point) // rjf: dump function lines U64 unit_idx = rdi_vmap_idx_from_voff(in->unit_vmap, in->unit_vmap_count, voff_range.min); - if(0 < unit_idx && unit_idx <= in->bake_units_out_count) + if(0 < unit_idx && unit_idx <= in->unit_count) { - // rjf: unpack unit line info - P2B_BakeUnitOut *bake_unit_out = in->bake_units_out[unit_idx]; - RDI_ParsedLineTable line_info = {bake_unit_out->unit_line_voffs, bake_unit_out->unit_lines, 0, bake_unit_out->unit_line_count, 0}; - for(U64 voff = voff_range.min, last_voff = 0; - voff < voff_range.max && voff > last_voff;) + U32 line_table_idx = in->unit_line_table_idxs[unit_idx]; + if(0 < line_table_idx && line_table_idx <= line_tables_count) { - RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&line_info, voff); - if(line_info_idx < line_info.count) + // rjf: unpack unit line info + RDI_LineTable *line_table = &line_tables[line_table_idx]; + RDI_ParsedLineTable line_info = { - RDI_Line *line = &line_info.lines[line_info_idx]; - U64 line_voff_min = line_info.voffs[line_info_idx]; - U64 line_voff_opl = line_info.voffs[line_info_idx+1]; - if(line->file_idx != 0) + line_table_voffs + line_table->voffs_base_idx, + line_table_lines + line_table->lines_base_idx, + 0, + line_table->lines_count, + 0 + }; + for(U64 voff = voff_range.min, last_voff = 0; + voff < voff_range.max && voff > last_voff;) + { + RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&line_info, voff); + if(line_info_idx < line_info.count) { - str8_list_pushf(arena, out, "%I64x %I64x %I64u %I64u\n", - line_voff_min, - line_voff_opl-line_voff_min, - (U64)line->line_num, - (U64)line->file_idx); + RDI_Line *line = &line_info.lines[line_info_idx]; + U64 line_voff_min = line_info.voffs[line_info_idx]; + U64 line_voff_opl = line_info.voffs[line_info_idx+1]; + if(line->file_idx != 0) + { + str8_list_pushf(arena, out, "%I64x %I64x %I64u %I64u\n", + line_voff_min, + line_voff_opl-line_voff_min, + (U64)line->line_num, + (U64)line->file_idx); + } + last_voff = voff; + voff = line_voff_opl; + } + else + { + break; } - last_voff = voff; - voff = line_voff_opl; - } - else - { - break; } } } @@ -236,20 +220,23 @@ entry_point(CmdLine *cmdline) RDIM_BakeParams *params = &convert2bake->bake_params; //- rjf: kick off unit vmap baking - P2B_BakeUnitVMapIn bake_unit_vmap_in = {params}; + P2B_BakeUnitVMapIn bake_unit_vmap_in = {¶ms->units}; TS_Ticket bake_unit_vmap_ticket = ts_kickoff(p2b_bake_unit_vmap_task__entry_point, 0, &bake_unit_vmap_in); - //- rjf: kick off per-line-table baking - P2B_BakeUnitIn *bake_units_in = push_array(arena, P2B_BakeUnitIn, params->units.total_count+1); - TS_Ticket *bake_units_tickets = push_array(arena, TS_Ticket, params->units.total_count+1); + //- rjf: kick off line-table baking + P2B_BakeLineTablesIn bake_line_tables_in = {¶ms->line_tables}; + TS_Ticket bake_line_tables_ticket = ts_kickoff(p2b_bake_line_table_task__entry_point, 0, &bake_line_tables_in); + + //- rjf: build unit -> line table idx array + U64 unit_count = params->units.total_count; + U32 *unit_line_table_idxs = push_array(arena, U32, unit_count+1); { - U64 idx = 1; + U64 dst_idx = 1; for(RDIM_UnitChunkNode *n = params->units.first; n != 0; n = n->next) { - for(U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, idx += 1) + for(U64 n_idx = 0; n_idx < n->count; n_idx += 1, dst_idx += 1) { - bake_units_in[chunk_idx].unit = &n->v[chunk_idx]; - bake_units_tickets[idx] = ts_kickoff(p2b_bake_unit_task__entry_point, 0, &bake_units_in[chunk_idx]); + unit_line_table_idxs[dst_idx] = rdim_idx_from_line_table(n->v[n_idx].line_table); } } } @@ -273,20 +260,15 @@ entry_point(CmdLine *cmdline) //- rjf: join unit vmap ProfBegin("join unit vmap"); - P2B_BakeUnitVMapOut *bake_unit_vmap_out = ts_join_struct(bake_unit_vmap_ticket, max_U64, P2B_BakeUnitVMapOut); - RDI_VMapEntry *unit_vmap = bake_unit_vmap_out->vmap_entries; - U32 unit_vmap_count = (U32)(bake_unit_vmap_out->vmap_entries_count); + RDIM_UnitVMapBakeResult *bake_unit_vmap_out = ts_join_struct(bake_unit_vmap_ticket, max_U64, RDIM_UnitVMapBakeResult); + RDI_VMapEntry *unit_vmap = bake_unit_vmap_out->vmap.vmap; + U32 unit_vmap_count = bake_unit_vmap_out->vmap.count; ProfEnd(); - //- rjf: join units - P2B_BakeUnitOut **bake_units_out = push_array(arena, P2B_BakeUnitOut*, params->units.total_count+1); - ProfScope("join units") - { - for(U64 idx = 1; idx < params->units.total_count+1; idx += 1) - { - bake_units_out[idx] = ts_join_struct(bake_units_tickets[idx], max_U64, P2B_BakeUnitOut); - } - } + //- rjf: join line tables + ProfBegin("join line table"); + RDIM_LineTableBakeResult *bake_line_tables_out = ts_join_struct(bake_line_tables_ticket, max_U64, RDIM_LineTableBakeResult); + ProfEnd(); //- rjf: kick off FUNC & line record dump tasks P2B_DumpProcChunkIn *dump_proc_chunk_in = push_array(arena, P2B_DumpProcChunkIn, params->procedures.chunk_count); @@ -298,8 +280,9 @@ entry_point(CmdLine *cmdline) { dump_proc_chunk_in[task_idx].unit_vmap = unit_vmap; dump_proc_chunk_in[task_idx].unit_vmap_count = unit_vmap_count; - dump_proc_chunk_in[task_idx].bake_units_out = bake_units_out; - dump_proc_chunk_in[task_idx].bake_units_out_count = params->units.total_count+1; + dump_proc_chunk_in[task_idx].unit_line_table_idxs = unit_line_table_idxs; + dump_proc_chunk_in[task_idx].unit_count = unit_count; + dump_proc_chunk_in[task_idx].line_tables_bake = bake_line_tables_out; dump_proc_chunk_in[task_idx].chunk = n; dump_proc_chunk_tickets[task_idx] = ts_kickoff(p2b_dump_proc_chunk_task__entry_point, 0, &dump_proc_chunk_in[task_idx]); } From a14a2f34f5fe0f0491df47e05eb16e4a871d3ca8 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 7 Jun 2024 14:54:13 -0700 Subject: [PATCH 22/44] rdi_make, rdi_from_pdb, rdi_dump: sketch out the building (no parsing/filling yet), dumping, and baking/serializing of inline sites --- src/lib_rdi_format/rdi_format.h | 4 ++- src/lib_rdi_make/rdi_make.c | 29 ++++++++++++++++- src/lib_rdi_make/rdi_make.h | 10 ++++++ src/rdi_dump/rdi_dump.c | 26 ++++++++++++++- src/rdi_dump/rdi_dump.h | 1 + src/rdi_dump/rdi_dump_main.c | 20 ++++++++++-- src/rdi_format/rdi_format.mdesk | 9 ++--- src/rdi_from_pdb/rdi_from_pdb.c | 58 +++++++++++++++++++++++++++++++++ src/rdi_from_pdb/rdi_from_pdb.h | 7 ++++ 9 files changed, 155 insertions(+), 9 deletions(-) diff --git a/src/lib_rdi_format/rdi_format.h b/src/lib_rdi_format/rdi_format.h index dfd73d6b..9f065ba1 100644 --- a/src/lib_rdi_format/rdi_format.h +++ b/src/lib_rdi_format/rdi_format.h @@ -52,7 +52,7 @@ typedef int64_t RDI_S64; // \"raddbg\0\0\" #define RDI_MAGIC_CONSTANT 0x0000676264646172 -#define RDI_ENCODING_VERSION 4 +#define RDI_ENCODING_VERSION 5 //////////////////////////////////////////////////////////////// //~ Format Types & Functions @@ -779,6 +779,7 @@ X(RDI_U32, local_first)\ X(RDI_U32, local_count)\ X(RDI_U32, static_local_idx_run_first)\ X(RDI_U32, static_local_count)\ +X(RDI_U32, inline_site_idx)\ #define RDI_InlineSite_XList \ X(RDI_U32, name_string_idx)\ @@ -1210,6 +1211,7 @@ RDI_U32 local_first; RDI_U32 local_count; RDI_U32 static_local_idx_run_first; RDI_U32 static_local_count; +RDI_U32 inline_site_idx; }; typedef struct RDI_InlineSite RDI_InlineSite; diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index 1bd3a998..81f78189 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -3421,6 +3421,33 @@ rdim_bake_scope_vmap(RDIM_Arena *arena, RDIM_ScopeChunkList *src) return result; } +RDI_PROC RDIM_InlineSiteBakeResult +rdim_bake_inline_sites(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_InlineSiteChunkList *src) +{ + RDIM_InlineSiteBakeResult result = {0}; + { + result.inline_sites_count = src->total_count; + result.inline_sites = rdim_push_array(arena, RDI_InlineSite, result.inline_sites_count+1); + RDI_U64 dst_idx = 1; + for(RDIM_InlineSiteChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + { + RDI_InlineSite *dst = &result.inline_sites[dst_idx]; + RDIM_InlineSite *src = &n->v[chunk_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->call_src_file_idx = (RDI_U32)rdim_idx_from_src_file(src->call_src_file); // TODO(rjf): @u64_to_u32 + dst->call_line_num = src->call_line_num; + dst->call_col_num = src->call_col_num; + dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 + dst->owner_type_idx = (RDI_U32)rdim_idx_from_type(src->owner); // TODO(rjf): @u64_to_u32 + dst->line_table_idx = (RDI_U32)rdim_idx_from_line_table(src->line_table); // TODO(rjf): @u64_to_u32 + } + } + } + return result; +} + RDI_PROC RDIM_TopLevelNameMapBakeResult rdim_bake_name_maps_top_level(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT]) { @@ -3598,7 +3625,7 @@ rdim_serialized_section_bundle_from_bake_results(RDIM_BakeResults *results) bundle.sections[RDI_SectionKind_Scopes] = rdim_serialized_section_make_unpacked_array(results->scopes.scopes, results->scopes.scopes_count); bundle.sections[RDI_SectionKind_ScopeVOffData] = rdim_serialized_section_make_unpacked_array(results->scopes.scope_voffs, results->scopes.scope_voffs_count); bundle.sections[RDI_SectionKind_ScopeVMap] = rdim_serialized_section_make_unpacked_array(results->scope_vmap.vmap.vmap, results->scope_vmap.vmap.count+1); - bundle.sections[RDI_SectionKind_InlineSites] = rdim_serialized_section_make_unpacked(0, 0); + bundle.sections[RDI_SectionKind_InlineSites] = rdim_serialized_section_make_unpacked_array(results->inline_sites.inline_sites, results->inline_sites.inline_sites_count); bundle.sections[RDI_SectionKind_Locals] = rdim_serialized_section_make_unpacked_array(results->scopes.locals, results->scopes.locals_count); bundle.sections[RDI_SectionKind_LocationBlocks] = rdim_serialized_section_make_unpacked_array(results->scopes.location_blocks, results->scopes.location_blocks_count); bundle.sections[RDI_SectionKind_LocationData] = rdim_serialized_section_make_unpacked_array(results->scopes.location_data, results->scopes.location_data_size); diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index 80122c0a..bb70bf42 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -826,6 +826,7 @@ struct RDIM_Scope RDIM_Local *first_local; RDIM_Local *last_local; RDI_U32 local_count; + RDIM_InlineSite *inline_site; }; typedef struct RDIM_ScopeChunkNode RDIM_ScopeChunkNode; @@ -1180,6 +1181,13 @@ struct RDIM_ScopeVMapBakeResult RDIM_BakeVMap vmap; }; +typedef struct RDIM_InlineSiteBakeResult RDIM_InlineSiteBakeResult; +struct RDIM_InlineSiteBakeResult +{ + RDI_InlineSite *inline_sites; + RDI_U64 inline_sites_count; +}; + typedef struct RDIM_TopLevelNameMapBakeResult RDIM_TopLevelNameMapBakeResult; struct RDIM_TopLevelNameMapBakeResult { @@ -1235,6 +1243,7 @@ struct RDIM_BakeResults RDIM_ThreadVariableBakeResult thread_variables; RDIM_ProcedureBakeResult procedures; RDIM_ScopeBakeResult scopes; + RDIM_InlineSiteBakeResult inline_sites; RDIM_ScopeVMapBakeResult scope_vmap; RDIM_TopLevelNameMapBakeResult top_level_name_maps; RDIM_NameMapBakeResult name_maps; @@ -1494,6 +1503,7 @@ RDI_PROC RDIM_ThreadVariableBakeResult rdim_bake_thread_variables(RDIM_Arena *a RDI_PROC RDIM_ProcedureBakeResult rdim_bake_procedures(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src); RDI_PROC RDIM_ScopeBakeResult rdim_bake_scopes(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_ScopeChunkList *src); RDI_PROC RDIM_ScopeVMapBakeResult rdim_bake_scope_vmap(RDIM_Arena *arena, RDIM_ScopeChunkList *src); +RDI_PROC RDIM_InlineSiteBakeResult rdim_bake_inline_sites(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_InlineSiteChunkList *src); RDI_PROC RDIM_TopLevelNameMapBakeResult rdim_bake_name_maps_top_level(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT]); RDI_PROC RDIM_FilePathBakeResult rdim_bake_file_paths(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree); RDI_PROC RDIM_StringBakeResult rdim_bake_strings(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings); diff --git a/src/rdi_dump/rdi_dump.c b/src/rdi_dump/rdi_dump.c index 4aa3e7cf..17c21cc8 100644 --- a/src/rdi_dump/rdi_dump.c +++ b/src/rdi_dump/rdi_dump.c @@ -580,7 +580,8 @@ rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *rdi, internal void rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *rdi, - RDI_ScopeBundle *bundle, RDI_Scope *scope, U32 indent_level){ + RDI_ScopeBundle *bundle, RDI_Scope *scope, U32 indent_level) +{ U32 this_idx = (U32)(scope - bundle->scopes); @@ -590,6 +591,12 @@ rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *rdi, str8_list_pushf(arena, out, "%.*s proc_idx=%u\n", indent_level, rdi_stringize_spaces, scope->proc_idx); + if(scope->inline_site_idx != 0) + { + str8_list_pushf(arena, out, "%.*s inline_site_idx=%u\n", + indent_level, rdi_stringize_spaces, scope->inline_site_idx); + } + // voff ranges { U32 voff_range_first_raw = scope->voff_range_first; @@ -765,3 +772,20 @@ rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *rdi, str8_list_pushf(arena, out, "%.*s[/%u]\n", indent_level, rdi_stringize_spaces, this_idx); } + +internal void +rdi_stringize_inline_site(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_InlineSite *inline_site, U32 indent_level) +{ + String8 name = {0}; + name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size); + RDI_SourceFile *source_file = rdi_element_from_name_idx(rdi, SourceFiles, inline_site->call_src_file_idx); + String8 source_file_path = {0}; + source_file_path.str = rdi_normal_path_from_source_file(rdi, source_file, &source_file_path.size); + str8_list_pushf(arena, out, "%.*sname='%S'\n", indent_level, rdi_stringize_spaces, name); + str8_list_pushf(arena, out, "%.*scall_src_file_idx=%u ('%S')\n", indent_level, rdi_stringize_spaces, inline_site->call_src_file_idx, source_file_path); + str8_list_pushf(arena, out, "%.*scall_line_num=%u\n", indent_level, rdi_stringize_spaces, inline_site->call_line_num); + str8_list_pushf(arena, out, "%.*scall_col_num=%u\n", indent_level, rdi_stringize_spaces, inline_site->call_col_num); + str8_list_pushf(arena, out, "%.*stype_idx=%u\n", indent_level, rdi_stringize_spaces, inline_site->type_idx); + str8_list_pushf(arena, out, "%.*sowner_type_idx=%u\n", indent_level, rdi_stringize_spaces, inline_site->owner_type_idx); + str8_list_pushf(arena, out, "%.*sline_table_idx=%u\n", indent_level, rdi_stringize_spaces, inline_site->line_table_idx); +} diff --git a/src/rdi_dump/rdi_dump.h b/src/rdi_dump/rdi_dump.h index 0ebe6479..7a469d9d 100644 --- a/src/rdi_dump/rdi_dump.h +++ b/src/rdi_dump/rdi_dump.h @@ -73,5 +73,6 @@ internal void rdi_stringize_global_variable(Arena *arena, String8List *out, RDI_ internal void rdi_stringize_thread_variable(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_ThreadVariable *thread_var, U32 indent_level); internal void rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_Procedure *proc, U32 indent_level); internal void rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_ScopeBundle *bundle, RDI_Scope *scope, U32 indent_level); +internal void rdi_stringize_inline_site(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_InlineSite *inline_site, U32 indent_level); #endif // RDI_DUMP_H diff --git a/src/rdi_dump/rdi_dump_main.c b/src/rdi_dump/rdi_dump_main.c index 3aa06373..bb4ae241 100644 --- a/src/rdi_dump/rdi_dump_main.c +++ b/src/rdi_dump/rdi_dump_main.c @@ -65,8 +65,9 @@ entry_point(CmdLine *cmd_line) DumpFlag_Procedures = (1<<14), DumpFlag_Scopes = (1<<15), DumpFlag_ScopeVMap = (1<<16), - DumpFlag_NameMaps = (1<<17), - DumpFlag_Strings = (1<<18), + DumpFlag_InlineSites = (1<<17), + DumpFlag_NameMaps = (1<<18), + DumpFlag_Strings = (1<<19), }; String8 input_name = {0}; DumpFlags dump_flags = (U32)0xffffffff; @@ -100,6 +101,7 @@ entry_point(CmdLine *cmd_line) 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("inline_sites"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_InlineSites; } else if(str8_match(n->string, str8_lit("name_maps"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_NameMaps; } else if(str8_match(n->string, str8_lit("strings"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_Strings; } } @@ -424,6 +426,20 @@ entry_point(CmdLine *cmd_line) str8_list_push(arena, &dump, str8_lit("\n")); } + //- rjf: INLINE SITES + if(dump_flags & DumpFlag_InlineSites) + { + str8_list_pushf(arena, &dump, "# INLINE SITES:\n"); + U64 count = 0; + RDI_InlineSite *v = rdi_table_from_name(rdi, InlineSites, &count); + for(U64 idx = 0; idx < count; idx += 1) + { + str8_list_pushf(arena, &dump, " inline_site[%I64u]:\n", idx); + rdi_stringize_inline_site(arena, &dump, rdi, &v[idx], 2); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + //- rjf: NAME MAPS if(dump_flags & DumpFlag_NameMaps) { diff --git a/src/rdi_format/rdi_format.mdesk b/src/rdi_format/rdi_format.mdesk index 26f6e51e..edc8e813 100644 --- a/src/rdi_format/rdi_format.mdesk +++ b/src/rdi_format/rdi_format.mdesk @@ -62,7 +62,7 @@ ""; "// \"raddbg\0\0\""; "#define RDI_MAGIC_CONSTANT 0x0000676264646172"; - "#define RDI_ENCODING_VERSION 4"; + "#define RDI_ENCODING_VERSION 5"; ""; "////////////////////////////////////////////////////////////////"; "//~ Format Types & Functions"; @@ -1006,9 +1006,10 @@ RDI_ScopeMemberTable: {voff_range_first RDI_U32 ""} {voff_range_opl RDI_U32 ""} {local_first RDI_U32 ""} - {local_count RDI_U32 ""} - {static_local_idx_run_first RDI_U32 ""} - {static_local_count RDI_U32 ""} + {local_count RDI_U32 ""} + {static_local_idx_run_first RDI_U32 ""} + {static_local_count RDI_U32 ""} + {inline_site_idx RDI_U32 ""} } @table(name type desc) diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index e5141165..fb5c6b59 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -1820,10 +1820,12 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) U64 sym_global_variables_chunk_cap = 1024; U64 sym_thread_variables_chunk_cap = 1024; U64 sym_scopes_chunk_cap = 1024; + U64 sym_inline_sites_chunk_cap = 1024; RDIM_SymbolChunkList sym_procedures = {0}; RDIM_SymbolChunkList sym_global_variables = {0}; RDIM_SymbolChunkList sym_thread_variables = {0}; RDIM_ScopeChunkList sym_scopes = {0}; + RDIM_InlineSiteChunkList sym_inline_sites = {0}; ////////////////////////// //- rjf: symbols pass 1: produce procedure frame info map (procedure -> frame info) @@ -2496,6 +2498,50 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) defrange_target = 0; defrange_target_is_param = 0; }break; + + //- rjf: INLINESITE + case CV_SymKind_INLINESITE: + { + // rjf: build inline site + RDIM_InlineSite *inline_site = rdim_inline_site_chunk_list_push(arena, &sym_inline_sites, sym_inline_sites_chunk_cap); + + // rjf: build scope + RDIM_Scope *scope = rdim_scope_chunk_list_push(arena, &sym_scopes, sym_scopes_chunk_cap); + scope->inline_site = inline_site; + if(top_scope_node == 0) + { + // TODO(rjf): log + } + if(top_scope_node != 0) + { + RDIM_Scope *top_scope = top_scope_node->scope; + SLLQueuePush_N(top_scope->first_child, top_scope->last_child, scope, next_sibling); + scope->parent_scope = top_scope; + scope->symbol = top_scope->symbol; + } + + // rjf: push this scope to scope stack + { + P2R_ScopeNode *node = free_scope_node; + if(node != 0) { SLLStackPop(free_scope_node); } + else { node = push_array_no_zero(scratch.arena, P2R_ScopeNode, 1); } + node->scope = scope; + SLLStackPush(top_scope_node, node); + } + }break; + + //- rjf: INLINESITE_END + case CV_SymKind_INLINESITE_END: + { + P2R_ScopeNode *n = top_scope_node; + if(n != 0) + { + SLLStackPop(top_scope_node); + SLLStackPush(free_scope_node, n); + } + defrange_target = 0; + defrange_target_is_param = 0; + }break; } } } @@ -2509,6 +2555,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) out->global_variables = sym_global_variables; out->thread_variables = sym_thread_variables; out->scopes = sym_scopes; + out->inline_sites = sym_inline_sites; } #undef p2r_type_ptr_from_itype @@ -3782,6 +3829,14 @@ internal TS_TASK_FUNCTION_DEF(p2r_bake_scope_vmap_task__entry_point) return out; } +internal TS_TASK_FUNCTION_DEF(p2r_bake_inline_sites_task__entry_point) +{ + P2R_BakeInlineSitesIn *in = (P2R_BakeInlineSitesIn *)p; + RDIM_InlineSiteBakeResult *out = push_array(arena, RDIM_InlineSiteBakeResult, 1); + ProfScope("bake inline sites") *out = rdim_bake_inline_sites(arena, in->strings, in->inline_sites); + return out; +} + internal TS_TASK_FUNCTION_DEF(p2r_bake_file_paths_task__entry_point) { P2R_BakeFilePathsIn *in = (P2R_BakeFilePathsIn *)p; @@ -4153,6 +4208,8 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) TS_Ticket bake_scopes_ticket = ts_kickoff(p2r_bake_scopes_task__entry_point, 0, &bake_scopes_in); P2R_BakeScopeVMapIn bake_scope_vmap_in = {&in_params->scopes}; TS_Ticket bake_scope_vmap_ticket = ts_kickoff(p2r_bake_scope_vmap_task__entry_point, 0, &bake_scope_vmap_in); + P2R_BakeInlineSitesIn bake_inline_sites_in = {&bake_strings, &in_params->inline_sites}; + TS_Ticket bake_inline_sites_ticket = ts_kickoff(p2r_bake_inline_sites_task__entry_point, 0, &bake_inline_sites_in); P2R_BakeFilePathsIn bake_file_paths_in = {&bake_strings, path_tree}; TS_Ticket bake_file_paths_ticket = ts_kickoff(p2r_bake_file_paths_task__entry_point, 0, &bake_file_paths_in); P2R_BakeStringsIn bake_strings_in = {&bake_strings}; @@ -4225,6 +4282,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) ProfScope("procedures") out_results->procedures = *ts_join_struct(bake_procedures_ticket, max_U64, RDIM_ProcedureBakeResult); ProfScope("scopes") out_results->scopes = *ts_join_struct(bake_scopes_ticket, max_U64, RDIM_ScopeBakeResult); ProfScope("scope vmap") out_results->scope_vmap = *ts_join_struct(bake_scope_vmap_ticket, max_U64, RDIM_ScopeVMapBakeResult); + ProfScope("inline sites") out_results->inline_sites = *ts_join_struct(bake_inline_sites_ticket, max_U64, RDIM_InlineSiteBakeResult); ProfScope("file paths") out_results->file_paths = *ts_join_struct(bake_file_paths_ticket, max_U64, RDIM_FilePathBakeResult); ProfScope("strings") out_results->strings = *ts_join_struct(bake_strings_ticket, max_U64, RDIM_StringBakeResult); ProfScope("type nodes") out_results->type_nodes = *ts_join_struct(bake_type_nodes_ticket, max_U64, RDIM_TypeNodeBakeResult); diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index 9e92e208..59e983a0 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -475,6 +475,13 @@ struct P2R_BakeScopeVMapIn RDIM_ScopeChunkList *scopes; }; +typedef struct P2R_BakeInlineSitesIn P2R_BakeInlineSitesIn; +struct P2R_BakeInlineSitesIn +{ + RDIM_BakeStringMapTight *strings; + RDIM_InlineSiteChunkList *inline_sites; +}; + typedef struct P2R_BakeFilePathsIn P2R_BakeFilePathsIn; struct P2R_BakeFilePathsIn { From 334bd3b06ff5f2ebcf3a1b6260ddb9f237683876 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 7 Jun 2024 15:22:53 -0700 Subject: [PATCH 23/44] inline site info extraction --- build.bat | 2 +- project.4coder | 2 +- src/rdi_from_pdb/rdi_from_pdb.c | 39 +++++++++++++++++++++++++++++++++ src/rdi_from_pdb/rdi_from_pdb.h | 1 + 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/build.bat b/build.bat index 74e5ea3e..9249f121 100644 --- a/build.bat +++ b/build.bat @@ -98,7 +98,7 @@ if not "%no_meta%"=="1" ( :: --- Build Everything (@build_targets) -------------------------------------- pushd build -if "%raddbg%"=="1" %compile% %gfx% ..\src\raddbg\raddbg_main.c %compile_link% %out%raddbg.exe || exit /b 1 +if "%raddbg%"=="1" %compile% ..\src\raddbg\raddbg_main.c %compile_link% %out%raddbg.exe || exit /b 1 if "%rdi_from_pdb%"=="1" %compile% ..\src\rdi_from_pdb\rdi_from_pdb_main.c %compile_link% %out%rdi_from_pdb.exe || exit /b 1 if "%rdi_from_dwarf%"=="1" %compile% ..\src\rdi_from_dwarf\rdi_from_dwarf.c %compile_link% %out%rdi_from_dwarf.exe || exit /b 1 if "%rdi_dump%"=="1" %compile% ..\src\rdi_dump\rdi_dump_main.c %compile_link% %out%rdi_dump.exe || exit /b 1 diff --git a/project.4coder b/project.4coder index c1283b5d..460ed992 100644 --- a/project.4coder +++ b/project.4coder @@ -56,7 +56,7 @@ commands = }, .rjf_f2 = { - .win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main_1.rdi && rdi_dump mule_main_1.rdi > mule_main_1.dump && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main_2.rdi && rdi_dump mule_main_2.rdi > mule_main_2.dump && diff mule_main_1.dump mule_main_2.dump && popd", + .win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main.rdi && rdi_dump mule_main.rdi > mule_main.dump", .linux = "", .out = "*compilation*", .footer_panel = true, diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index fb5c6b59..e31518eb 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -2502,8 +2502,46 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) //- rjf: INLINESITE case CV_SymKind_INLINESITE: { + // rjf: unpack sym + CV_SymInlineSite *sym = (CV_SymInlineSite *)sym_header_struct_base; + String8 binary_annots = str8((U8 *)(sym+1), rec_range->hdr.size - sizeof(rec_range->hdr.kind) - sizeof(*sym)); + + // rjf: extract external info about inline site + String8 name = str8_zero(); + RDIM_Type *type = 0; + RDIM_Type *owner = 0; + if(in->ipi_leaf != 0 && in->ipi_leaf->itype_first <= sym->inlinee && sym->inlinee < in->ipi_leaf->itype_opl) + { + CV_RecRange rec_range = in->ipi_leaf->leaf_ranges.ranges[sym->inlinee - in->ipi_leaf->itype_first]; + String8 rec_data = str8_substr(in->ipi_leaf->data, rng_1u64(rec_range.off, rec_range.off + rec_range.hdr.size)); + void *raw_leaf = rec_data.str + sizeof(U16); + + // rjf: extract method inline info + if(rec_range.hdr.kind == CV_LeafIDKind_MFUNC_ID && + rec_range.hdr.size >= sizeof(CV_LeafMFuncId)) + { + CV_LeafMFuncId *mfunc_id = (CV_LeafMFuncId*)raw_leaf; + name = str8_cstring_capped(mfunc_id + 1, rec_data.str + rec_data.size); + type = p2r_type_ptr_from_itype(mfunc_id->itype); + owner = mfunc_id->owner_itype != 0 ? p2r_type_ptr_from_itype(mfunc_id->owner_itype) : 0; + } + + // rjf: extract non-method function inline info + else if(rec_range.hdr.kind == CV_LeafIDKind_FUNC_ID && + rec_range.hdr.size >= sizeof(CV_LeafFuncId)) + { + CV_LeafFuncId *func_id = (CV_LeafFuncId*)raw_leaf; + name = str8_cstring_capped(func_id + 1, rec_data.str + rec_data.size); + type = p2r_type_ptr_from_itype(func_id->itype); + owner = func_id->scope_string_id != 0 ? p2r_type_ptr_from_itype(func_id->scope_string_id) : 0; + } + } + // rjf: build inline site RDIM_InlineSite *inline_site = rdim_inline_site_chunk_list_push(arena, &sym_inline_sites, sym_inline_sites_chunk_cap); + inline_site->name = name; + inline_site->type = type; + inline_site->owner= owner; // rjf: build scope RDIM_Scope *scope = rdim_scope_chunk_list_push(arena, &sym_scopes, sym_scopes_chunk_cap); @@ -3523,6 +3561,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) tasks_inputs[idx].coff_sections = coff_sections; tasks_inputs[idx].tpi_hash = tpi_hash; tasks_inputs[idx].tpi_leaf = tpi_leaf; + tasks_inputs[idx].ipi_leaf = ipi_leaf; tasks_inputs[idx].itype_fwd_map = itype_fwd_map; tasks_inputs[idx].itype_type_ptrs = itype_type_ptrs; tasks_inputs[idx].link_name_map = link_name_map; diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index 59e983a0..c8f776b9 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -249,6 +249,7 @@ struct P2R_SymbolStreamConvertIn PDB_CoffSectionArray *coff_sections; PDB_TpiHashParsed *tpi_hash; CV_LeafParsed *tpi_leaf; + CV_LeafParsed *ipi_leaf; CV_SymParsed *sym; U64 sym_ranges_first; U64 sym_ranges_opl; From 07d56ee27c5cae8073a6ec801a86095c985427e8 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 7 Jun 2024 16:40:21 -0700 Subject: [PATCH 24/44] codeview c13 inlinee lines info parsing, lookup in inline site parsing path --- src/codeview/codeview.c | 589 ++++++++++++++++-------------- src/codeview/codeview.h | 180 ++++----- src/codeview/codeview_stringize.c | 12 +- src/codeview/codeview_stringize.h | 2 +- src/rdi_from_pdb/rdi_from_pdb.c | 111 +++--- src/rdi_from_pdb/rdi_from_pdb.h | 1 + 6 files changed, 489 insertions(+), 406 deletions(-) diff --git a/src/codeview/codeview.c b/src/codeview/codeview.c index 5e3d5e6c..1919ad64 100644 --- a/src/codeview/codeview.c +++ b/src/codeview/codeview.c @@ -7,21 +7,44 @@ #include "generated/codeview.meta.c" //////////////////////////////// -//~ CodeView Common Functions +//~ CodeView Common Decoding Helper Functions + +internal U64 +cv_hash_from_string(String8 string) +{ + U64 result = 5381; + for(U64 i = 0; i < string.size; i += 1) + { + result = ((result << 5) + result) + string.str[i]; + } + return result; +} + +internal U64 +cv_hash_from_item_id(CV_ItemId item_id) +{ + U64 result = cv_hash_from_string(str8_struct(&item_id)); + return result; +} internal CV_NumericParsed -cv_numeric_from_data_range(U8 *first, U8 *opl){ +cv_numeric_from_data_range(U8 *first, U8 *opl) +{ CV_NumericParsed result = {0}; - if (first + 2 <= opl){ + if(first + 2 <= opl) + { U16 x = *(U16*)first; - if (x < 0x8000){ + if(x < 0x8000) + { result.kind = CV_NumericKind_USHORT; result.val = first; result.encoded_size = 2; } - else{ + else + { U64 val_size = 0; - switch (x){ + switch(x) + { case CV_NumericKind_CHAR: val_size = 1; break; case CV_NumericKind_SHORT: case CV_NumericKind_USHORT: val_size = 2; break; @@ -46,21 +69,23 @@ cv_numeric_from_data_range(U8 *first, U8 *opl){ case CV_NumericKind_UTF8STRING:val_size = 0; break; // TODO: ??? case CV_NumericKind_FLOAT16: val_size = 2; break; } - - if (first + 2 + val_size <= opl){ + if(first + 2 + val_size <= opl) + { result.kind = x; result.val = (first + 2); result.encoded_size = 2 + val_size; } } } - return(result); + return result; } internal B32 -cv_numeric_fits_in_u64(CV_NumericParsed *num){ +cv_numeric_fits_in_u64(CV_NumericParsed *num) +{ B32 result = 0; - switch (num->kind){ + switch(num->kind) + { case CV_NumericKind_USHORT: case CV_NumericKind_ULONG: case CV_NumericKind_UQUADWORD: @@ -68,13 +93,15 @@ cv_numeric_fits_in_u64(CV_NumericParsed *num){ result = 1; }break; } - return(result); + return result; } internal B32 -cv_numeric_fits_in_s64(CV_NumericParsed *num){ +cv_numeric_fits_in_s64(CV_NumericParsed *num) +{ B32 result = 0; - switch (num->kind){ + switch(num->kind) + { case CV_NumericKind_CHAR: case CV_NumericKind_SHORT: case CV_NumericKind_LONG: @@ -83,91 +110,63 @@ cv_numeric_fits_in_s64(CV_NumericParsed *num){ result = 1; }break; } - return(result); + return result; } internal B32 -cv_numeric_fits_in_f64(CV_NumericParsed *num){ +cv_numeric_fits_in_f64(CV_NumericParsed *num) +{ B32 result = 0; - switch (num->kind){ + switch(num->kind) + { case CV_NumericKind_FLOAT32: case CV_NumericKind_FLOAT64: { result = 1; }break; } - return(result); + return result; } internal U64 -cv_u64_from_numeric(CV_NumericParsed *num){ +cv_u64_from_numeric(CV_NumericParsed *num) +{ U64 result = 0; - switch (num->kind){ - case CV_NumericKind_USHORT: - { - result = *(U16*)num->val; - }break; - - case CV_NumericKind_ULONG: - { - result = *(U32*)num->val; - }break; - - case CV_NumericKind_UQUADWORD: - { - result = *(U64*)num->val; - }break; + switch(num->kind) + { + case CV_NumericKind_USHORT: {result = *(U16*)num->val;}break; + case CV_NumericKind_ULONG: {result = *(U32*)num->val;}break; + case CV_NumericKind_UQUADWORD:{result = *(U64*)num->val;}break; } - return(result); + return result; } internal S64 -cv_s64_from_numeric(CV_NumericParsed *num){ +cv_s64_from_numeric(CV_NumericParsed *num) +{ S64 result = 0; - switch (num->kind){ - case CV_NumericKind_CHAR: - { - result = *(S8*)num->val; - }break; - - case CV_NumericKind_SHORT: - { - result = *(S16*)num->val; - }break; - - case CV_NumericKind_LONG: - { - result = *(S32*)num->val; - }break; - - case CV_NumericKind_QUADWORD: - { - result = *(S64*)num->val; - }break; + switch(num->kind) + { + case CV_NumericKind_CHAR: {result = *(S8*)num->val;}break; + case CV_NumericKind_SHORT: {result = *(S16*)num->val;}break; + case CV_NumericKind_LONG: {result = *(S32*)num->val;}break; + case CV_NumericKind_QUADWORD: {result = *(S64*)num->val;}break; } return(result); } internal F64 -cv_f64_from_numeric(CV_NumericParsed *num){ +cv_f64_from_numeric(CV_NumericParsed *num) +{ F64 result = 0; - switch (num->kind){ - case CV_NumericKind_FLOAT32: - { - result = *(F32*)num->val; - }break; - - case CV_NumericKind_FLOAT64: - { - result = *(F64*)num->val; - }break; + switch(num->kind) + { + case CV_NumericKind_FLOAT32:{result = *(F32*)num->val;}break; + case CV_NumericKind_FLOAT64:{result = *(F64*)num->val;}break; } return(result); } -//////////////////////////////// -//~ Inline Binary Annotation Helpers - internal U64 cv_decode_inline_annot_u32(String8 data, U64 offset, U32 *out_value) { @@ -239,27 +238,27 @@ cv_decode_inline_annot_s32(String8 data, U64 offset, S32 *out_value) } //////////////////////////////// -//~ CodeView Sym Parser Functions +//~ CodeView Parsing Functions -//- the first pass parser +//- rjf: record range stream parsing internal CV_RecRangeStream* -cv_rec_range_stream_from_data(Arena *arena, String8 sym_data, U64 sym_align){ +cv_rec_range_stream_from_data(Arena *arena, String8 sym_data, U64 sym_align) +{ Assert(1 <= sym_align && IsPow2OrZero(sym_align)); - CV_RecRangeStream *result = push_array(arena, CV_RecRangeStream, 1); - U8 *data = sym_data.str; U64 cursor = 0; U64 cap = sym_data.size; - for (;cursor + sizeof(CV_RecHeader) <= cap;){ + for(;cursor + sizeof(CV_RecHeader) <= cap;) + { // setup a new chunk arena_push_align(arena, 64); - CV_RecRangeChunk *cur_chunk = cv_rec_range_stream_push_chunk(arena, result); - + CV_RecRangeChunk *cur_chunk = push_array_no_zero(arena, CV_RecRangeChunk, 1); + SLLQueuePush(result->first_chunk, result->last_chunk, cur_chunk); U64 partial_count = 0; - for (;partial_count < CV_REC_RANGE_CHUNK_SIZE && cursor + sizeof(CV_RecHeader) <= cap; - partial_count += 1){ + for(;partial_count < CV_REC_RANGE_CHUNK_SIZE && cursor + sizeof(CV_RecHeader) <= cap; partial_count += 1) + { // compute cap CV_RecHeader *hdr = (CV_RecHeader*)(data + cursor); U64 symbol_cap_unclamped = cursor + 2 + hdr->size; @@ -273,110 +272,110 @@ cv_rec_range_stream_from_data(Arena *arena, String8 sym_data, U64 sym_align){ U32 next_pos = AlignPow2(symbol_cap, sym_align); cursor = next_pos; } - result->total_count += partial_count; } - - return(result); + return result; } -//- sym +internal CV_RecRangeArray +cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream) +{ + U64 total_count = stream->total_count; + CV_RecRange *ranges = push_array_no_zero(arena, CV_RecRange, total_count); + U64 idx = 0; + for(CV_RecRangeChunk *chunk = stream->first_chunk; chunk != 0; chunk = chunk->next) + { + U64 copy_count_raw = total_count - idx; + U64 copy_count = ClampTop(copy_count_raw, CV_REC_RANGE_CHUNK_SIZE); + MemoryCopy(ranges + idx, chunk->ranges, copy_count*sizeof(CV_RecRange)); + idx += copy_count; + } + CV_RecRangeArray result = {0}; + result.ranges = ranges; + result.count = total_count; + return result; +} -internal CV_SymParsed* -cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align){ +//- rjf: sym stream parsing + +internal CV_SymParsed * +cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align) +{ Assert(1 <= sym_align && IsPow2OrZero(sym_align)); - ProfBegin("cv_sym_from_data"); - + ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); - // gather up symbols + //- rjf: gather symbols CV_RecRangeStream *stream = cv_rec_range_stream_from_data(scratch.arena, sym_data, sym_align); - // convert to result + //- rjf: convert to result, fill basics CV_SymParsed *result = push_array(arena, CV_SymParsed, 1); result->data = sym_data; result->sym_align = sym_align; result->sym_ranges = cv_rec_range_array_from_stream(arena, stream); - cv_sym_top_level_info_from_syms(arena, sym_data, &result->sym_ranges, &result->info); - scratch_end(scratch); - - ProfEnd(); - - return(result); -} - -internal void -cv_sym_top_level_info_from_syms(Arena *arena, String8 sym_data, - CV_RecRangeArray *ranges, - CV_SymTopLevelInfo *info_out){ - MemoryZeroStruct(info_out); - - CV_RecRange *range = ranges->ranges; - CV_RecRange *opl = range + ranges->count; - for (; range < opl; range += 1){ - U8 *first = sym_data.str + range->off + 2; - U64 cap = range->hdr.size - 2; - - switch (range->hdr.kind){ - case CV_SymKind_COMPILE: + //- rjf: extract top-level-info + { + CV_RecRange *range = result->sym_ranges.ranges; + CV_RecRange *opl = range + result->sym_ranges.count; + for(;range < opl; range += 1) + { + U8 *first = sym_data.str + range->off + 2; + U64 cap = range->hdr.size - 2; + switch(range->hdr.kind) { - if (sizeof(CV_SymCompile) <= cap){ + case CV_SymKind_COMPILE: + if(sizeof(CV_SymCompile) <= cap) + { CV_SymCompile *compile = (CV_SymCompile*)first; - String8 ver_str = str8_cstring_capped((char*)(compile + 1), (char *)(first + cap)); - - info_out->arch = compile->machine; - info_out->language = CV_CompileFlags_ExtractLanguage(compile->flags);; - info_out->compiler_name = ver_str; - } - }break; - - case CV_SymKind_COMPILE2: - { - if (sizeof(CV_SymCompile2) <= cap){ + result->info.arch = compile->machine; + result->info.language = CV_CompileFlags_ExtractLanguage(compile->flags);; + result->info.compiler_name = ver_str; + }break; + case CV_SymKind_COMPILE2: + if(sizeof(CV_SymCompile2) <= cap) + { CV_SymCompile2 *compile2 = (CV_SymCompile2*)first; - String8 ver_str = str8_cstring_capped((char*)(compile2 + 1), (char*)(first + cap)); String8 compiler_name = push_str8f(arena, "%.*s %u.%u.%u", str8_varg(ver_str), compile2->ver_major, compile2->ver_minor, compile2->ver_build); - - info_out->arch = compile2->machine; - info_out->language = CV_Compile2Flags_ExtractLanguage(compile2->flags);; - info_out->compiler_name = compiler_name; - } - }break; - - case CV_SymKind_COMPILE3: - { - if (sizeof(CV_SymCompile3) <= cap){ + result->info.arch = compile2->machine; + result->info.language = CV_Compile2Flags_ExtractLanguage(compile2->flags);; + result->info.compiler_name = compiler_name; + }break; + case CV_SymKind_COMPILE3: + if(sizeof(CV_SymCompile3) <= cap) + { CV_SymCompile3 *compile3 = (CV_SymCompile3*)first; - String8 ver_str = str8_cstring_capped((char*)(compile3 + 1), (char *)(first + cap)); String8 compiler_name = push_str8f(arena, "%.*s %u.%u.%u", str8_varg(ver_str), compile3->ver_major, compile3->ver_minor, compile3->ver_build); - - info_out->arch = compile3->machine; - info_out->language = CV_Compile3Flags_ExtractLanguage(compile3->flags);; - info_out->compiler_name = compiler_name; - } - }break; + result->info.arch = compile3->machine; + result->info.language = CV_Compile3Flags_ExtractLanguage(compile3->flags);; + result->info.compiler_name = compiler_name; + }break; + } } } + + scratch_end(scratch); + ProfEnd(); + return result; } -//- leaf +//- rjf: leaf stream parsing -internal CV_LeafParsed* -cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId itype_first){ - ProfBegin("cv_leaf_from_data"); - +internal CV_LeafParsed * +cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId itype_first) +{ + ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); // gather up symbols @@ -390,57 +389,31 @@ cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId itype_first){ result->leaf_ranges = cv_rec_range_array_from_stream(arena, stream); scratch_end(scratch); - ProfEnd(); - - return(result); -} - -//- range streams - -internal CV_RecRangeChunk* -cv_rec_range_stream_push_chunk(Arena *arena, CV_RecRangeStream *stream){ - CV_RecRangeChunk *result = push_array_no_zero(arena, CV_RecRangeChunk, 1); - SLLQueuePush(stream->first_chunk, stream->last_chunk, result); - return(result); -} - -internal CV_RecRangeArray -cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream){ - U64 total_count = stream->total_count; - CV_RecRange *ranges = push_array_no_zero(arena, CV_RecRange, total_count); - U64 idx = 0; - for (CV_RecRangeChunk *chunk = stream->first_chunk; - chunk != 0; - chunk = chunk->next){ - U64 copy_count_raw = total_count - idx; - U64 copy_count = ClampTop(copy_count_raw, CV_REC_RANGE_CHUNK_SIZE); - MemoryCopy(ranges + idx, chunk->ranges, copy_count*sizeof(CV_RecRange)); - idx += copy_count; - } - CV_RecRangeArray result = {0}; - result.ranges = ranges; - result.count = total_count; - return(result); + return result; } //////////////////////////////// //~ CodeView C13 Parser Functions -internal CV_C13Parsed* -cv_c13_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSectionArray *sections){ - ProfBegin("cv_c13_from_data"); +internal CV_C13Parsed * +cv_c13_parsed_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSectionArray *sections) +{ + ProfBeginFunction(); - // gather c13 data + ////////////////////////////// + //- rjf: gather c13 sub-sections + // CV_C13SubSectionNode *file_chksms = 0; CV_C13SubSectionNode *first = 0; CV_C13SubSectionNode *last = 0; U64 count = 0; { U32 cursor = 0; - for (; cursor + sizeof(CV_C13_SubSectionHeader) <= c13_data.size;){ + for(; cursor + sizeof(CV_C13SubSectionHeader) <= c13_data.size;) + { // read header - CV_C13_SubSectionHeader *hdr = (CV_C13_SubSectionHeader*)(c13_data.str + cursor); + CV_C13SubSectionHeader *hdr = (CV_C13SubSectionHeader*)(c13_data.str + cursor); // get sub section info U32 sub_section_off = cursor + sizeof(*hdr); @@ -450,15 +423,16 @@ cv_c13_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSec U32 sub_section_size = after_sub_section_off - sub_section_off; // emit sub section - if (!(hdr->kind & CV_C13_SubSectionKind_IgnoreFlag)){ + if(!(hdr->kind & CV_C13SubSectionKind_IgnoreFlag)) + { CV_C13SubSectionNode *node = push_array(arena, CV_C13SubSectionNode, 1); SLLQueuePush(first, last, node); count += 1; node->kind = hdr->kind; node->off = sub_section_off; node->size = sub_section_size; - - if (hdr->kind == CV_C13_SubSectionKind_FileChksms){ + if(hdr->kind == CV_C13SubSectionKind_FileChksms) + { file_chksms = node; } } @@ -468,112 +442,181 @@ cv_c13_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSec } } - // parse each section - for (CV_C13SubSectionNode *node = first; - node != 0; - node = node->next){ + ////////////////////////////// + //- rjf: parse each sub-section + // + U64 inlinee_lines_parsed_slots_count = 4096; + CV_C13InlineeLinesParsedNode **inlinee_lines_parsed_slots = push_array(arena, CV_C13InlineeLinesParsedNode *, inlinee_lines_parsed_slots_count); + for(CV_C13SubSectionNode *node = first; + node != 0; + node = node->next) + { U8 *first = c13_data.str + node->off; U32 cap = node->size; - - switch (node->kind){ - case CV_C13_SubSectionKind_Lines: + switch(node->kind) + { + default:{}break; + + ////////////////////////// + //- rjf: line info sub-section + // + case CV_C13SubSectionKind_Lines: + if(sizeof(CV_C13SubSecLinesHeader) <= cap) { // read header - if (sizeof(CV_C13_SubSecLinesHeader) <= cap){ - U32 read_off = 0; - U64 read_off_opl = node->size; - CV_C13_SubSecLinesHeader *hdr = (CV_C13_SubSecLinesHeader*)(first + read_off); + U32 read_off = 0; + U64 read_off_opl = node->size; + CV_C13SubSecLinesHeader *hdr = (CV_C13SubSecLinesHeader*)(first + read_off); + read_off += sizeof(*hdr); + + // extract top level info + U32 sec_idx = hdr->sec; + B32 has_cols = !!(hdr->flags & CV_C13SubSecLinesFlag_HasColumns); + U64 secrel_off = hdr->sec_off; + U64 secrel_opl = secrel_off + hdr->len; + U64 sec_base_off = sections->sections[sec_idx - 1].voff; + + // rjf: bad section index -> skip + if(sec_idx < 1 || sections->count < sec_idx) + { + continue; + } + + // read files + for(;read_off+sizeof(CV_C13File) <= read_off_opl;) + { + // rjf: grab next file header + CV_C13File *file = (CV_C13File*)(first + read_off); + U32 file_off = file->file_off; + U32 line_count_unclamped = file->num_lines; + U32 block_size = file->block_size; + + // file_name from file_off + String8 file_name = {0}; + if(file_off + sizeof(CV_C13Checksum) <= file_chksms->size) + { + CV_C13Checksum *checksum = (CV_C13Checksum*)(c13_data.str + file_chksms->off + file_off); + U32 name_off = checksum->name_off; + file_name = pdb_strtbl_string_from_off(strtbl, name_off); + } + + // array layouts + U32 line_item_size = sizeof(CV_C13Line); + if (has_cols){ + line_item_size += sizeof(CV_C13Column); + } + + U32 line_array_off = read_off + sizeof(*file); + U32 line_count_max = (read_off_opl - line_array_off) / line_item_size; + U32 line_count = ClampTop(line_count_unclamped, line_count_max); + + U32 col_array_off = line_array_off + line_count*sizeof(CV_C13Line); + + // parse lines + U64 *voffs = push_array_no_zero(arena, U64, line_count + 1); + U32 *line_nums = push_array_no_zero(arena, U32, line_count); + + { + CV_C13Line *line_ptr = (CV_C13Line*)(first + line_array_off); + CV_C13Line *line_opl = line_ptr + line_count; + + // TODO(allen): check order correctness here + + U32 i = 0; + for (; line_ptr < line_opl; line_ptr += 1, i += 1){ + voffs[i] = line_ptr->off + secrel_off + sec_base_off; + line_nums[i] = CV_C13LineFlags_ExtractLineNumber(line_ptr->flags); + } + voffs[i] = secrel_opl + sec_base_off; + } + + // emit parsed lines + CV_C13LinesParsedNode *lines_parsed_node = push_array(arena, CV_C13LinesParsedNode, 1); + CV_C13LinesParsed *lines_parsed = &lines_parsed_node->v; + lines_parsed->sec_idx = sec_idx; + lines_parsed->file_off = file_off; + lines_parsed->secrel_base_off = secrel_off; + lines_parsed->file_name = file_name; + lines_parsed->voffs = voffs; + lines_parsed->line_nums = line_nums; + lines_parsed->line_count = line_count; + SLLQueuePush(node->lines_first, node->lines_last, lines_parsed_node); + + // rjf: advance + read_off += sizeof(*file); + read_off += line_item_size*line_count; + } + }break; + + ////////////////////////// + //- rjf: inlinee line info sub-section + // + case CV_C13SubSectionKind_InlineeLines: + if(sizeof(CV_C13InlineeLinesSig) <= cap) + { + // rjf: read sig + U32 read_off = 0; + U64 read_off_opl = node->size; + CV_C13InlineeLinesSig *sig = (CV_C13InlineeLinesSig *)(first + read_off); + read_off += sizeof(*sig); + + // rjf: read source lines + for(;read_off + sizeof(CV_C13InlineeSourceLineHeader) <= read_off_opl;) + { + // rjf: read next header + CV_C13InlineeSourceLineHeader *hdr = (CV_C13InlineeSourceLineHeader *)(first + read_off); read_off += sizeof(*hdr); - // extract top level info - U32 sec_idx = hdr->sec; - B32 has_cols = !!(hdr->flags & CV_C13_SubSecLinesFlag_HasColumns); - U64 secrel_off = hdr->sec_off; - U64 secrel_opl = secrel_off + hdr->len; - U64 sec_base_off = sections->sections[sec_idx - 1].voff; - - // rjf: bad section index -> skip - if(sec_idx < 1 || sections->count < sec_idx) + // rjf: file_off -> file_name + String8 file_name = {0}; + if(hdr->file_off + sizeof(CV_C13Checksum) <= file_chksms->size) { - continue; + CV_C13Checksum *checksum = (CV_C13Checksum*)(c13_data.str + file_chksms->off + hdr->file_off); + U32 name_off = checksum->name_off; + file_name = pdb_strtbl_string_from_off(strtbl, name_off); } - // read files - for(;read_off+sizeof(CV_C13_File) <= read_off_opl;) + // rjf: parse extra files + U32 extra_file_count = 0; + U32 *extra_files = 0; + if(*sig == CV_C13InlineeLinesSig_EXTRA_FILES && read_off+sizeof(U32) <= read_off_opl) { - // rjf: grab next file header - CV_C13_File *file = (CV_C13_File*)(first + read_off); - U32 file_off = file->file_off; - U32 line_count_unclamped = file->num_lines; - U32 block_size = file->block_size; - - // file_name from file_off - String8 file_name = {0}; - if (file_off + sizeof(CV_C13_Checksum) <= file_chksms->size){ - CV_C13_Checksum *checksum = (CV_C13_Checksum*)(c13_data.str + file_chksms->off + file_off); - U32 name_off = checksum->name_off; - file_name = pdb_strtbl_string_from_off(strtbl, name_off); - } - - // array layouts - U32 line_item_size = sizeof(CV_C13_Line); - if (has_cols){ - line_item_size += sizeof(CV_C13_Column); - } - - U32 line_array_off = read_off + sizeof(*file); - U32 line_count_max = (read_off_opl - line_array_off) / line_item_size; - U32 line_count = ClampTop(line_count_unclamped, line_count_max); - - U32 col_array_off = line_array_off + line_count*sizeof(CV_C13_Line); - - // parse lines - U64 *voffs = push_array_no_zero(arena, U64, line_count + 1); - U32 *line_nums = push_array_no_zero(arena, U32, line_count); - - { - CV_C13_Line *line_ptr = (CV_C13_Line*)(first + line_array_off); - CV_C13_Line *line_opl = line_ptr + line_count; - - // TODO(allen): check order correctness here - - U32 i = 0; - for (; line_ptr < line_opl; line_ptr += 1, i += 1){ - voffs[i] = line_ptr->off + secrel_off + sec_base_off; - line_nums[i] = CV_C13_LineFlags_ExtractLineNumber(line_ptr->flags); - } - voffs[i] = secrel_opl + sec_base_off; - } - - // emit parsed lines - CV_C13LinesParsedNode *lines_parsed_node = push_array(arena, CV_C13LinesParsedNode, 1); - CV_C13LinesParsed *lines_parsed = &lines_parsed_node->v; - lines_parsed->sec_idx = sec_idx; - lines_parsed->file_off = file_off; - lines_parsed->secrel_base_off = secrel_off; - lines_parsed->file_name = file_name; - lines_parsed->voffs = voffs; - lines_parsed->line_nums = line_nums; - lines_parsed->line_count = line_count; - SLLQueuePush(node->lines_first, node->lines_last, lines_parsed_node); - - // rjf: advance - read_off += sizeof(*file); - read_off += line_item_size*line_count; + U32 *extra_file_count_ptr = (U32 *)(first + read_off); + read_off += sizeof(*extra_file_count_ptr); + U32 max_extra_file_count = (read_off_opl-read_off)/sizeof(U32); + extra_file_count = Min(*extra_file_count_ptr, max_extra_file_count); + extra_files = (U32 *)(first + read_off); + read_off += sizeof(*extra_files)*extra_file_count; } + + // rjf: push node for this inlinee lines parsed into this subsection's list + CV_C13InlineeLinesParsedNode *n = push_array(arena, CV_C13InlineeLinesParsedNode, 1); + SLLQueuePush(node->inlinee_lines_first, node->inlinee_lines_last, n); + n->v.inlinee = hdr->inlinee; + n->v.file_name = file_name; + n->v.first_source_ln = hdr->first_source_ln; + n->v.extra_file_count = extra_file_count; + n->v.extra_files = extra_files; + + // rjf: push node into inlinee parse hash table + U64 hash = cv_hash_from_item_id(hdr->inlinee); + U64 slot_idx = hash%inlinee_lines_parsed_slots_count; + SLLStackPush_N(inlinee_lines_parsed_slots[slot_idx], n, hash_next); } }break; } } - // convert to result + ////////////////////////////// + //- rjf: fill output + // CV_C13Parsed *result = push_array(arena, CV_C13Parsed, 1); result->first_sub_section = first; result->last_sub_section = last; result->sub_section_count = count; result->file_chksms_sub_section = file_chksms; - + result->inlinee_lines_parsed_slots = inlinee_lines_parsed_slots; + result->inlinee_lines_parsed_slots_count = inlinee_lines_parsed_slots_count; ProfEnd(); - - return(result); + return result; } diff --git a/src/codeview/codeview.h b/src/codeview/codeview.h index 015829d3..4b5c4000 100644 --- a/src/codeview/codeview.h +++ b/src/codeview/codeview.h @@ -2651,9 +2651,9 @@ struct CV_LeafUDTModSrcLine //////////////////////////////// //~ CodeView Format C13 Line Info Types -#define CV_C13_SubSectionKind_IgnoreFlag 0x80000000 +#define CV_C13SubSectionKind_IgnoreFlag 0x80000000 -#define CV_C13_SubSectionKindXList(X)\ +#define CV_C13SubSectionKindXList(X)\ X(Symbols, 0xF1)\ X(Lines, 0xF2)\ X(StringTable, 0xF3)\ @@ -2670,83 +2670,83 @@ X(CoffSymbolRVA, 0xFD)\ X(XfgHashType, 0xFF)\ X(XfgHashVirtual, 0x100) -typedef U32 CV_C13_SubSectionKind; -typedef enum CV_C13_SubSectionKindEnum +typedef U32 CV_C13SubSectionKind; +typedef enum CV_C13SubSectionKindEnum { -#define X(N,c) CV_C13_SubSectionKind_##N = c, - CV_C13_SubSectionKindXList(X) +#define X(N,c) CV_C13SubSectionKind_##N = c, + CV_C13SubSectionKindXList(X) #undef X } -CV_C13_SubSectionKindEnum; +CV_C13SubSectionKindEnum; -typedef struct CV_C13_SubSectionHeader CV_C13_SubSectionHeader; -struct CV_C13_SubSectionHeader +typedef struct CV_C13SubSectionHeader CV_C13SubSectionHeader; +struct CV_C13SubSectionHeader { - CV_C13_SubSectionKind kind; + CV_C13SubSectionKind kind; U32 size; }; //- FileChksms sub-section -typedef U8 CV_C13_ChecksumKind; -typedef enum CV_C13_ChecksumKindEnum +typedef U8 CV_C13ChecksumKind; +typedef enum CV_C13ChecksumKindEnum { - CV_C13_ChecksumKind_Null, - CV_C13_ChecksumKind_MD5, - CV_C13_ChecksumKind_SHA1, - CV_C13_ChecksumKind_SHA256, + CV_C13ChecksumKind_Null, + CV_C13ChecksumKind_MD5, + CV_C13ChecksumKind_SHA1, + CV_C13ChecksumKind_SHA256, } -CV_C13_ChecksumKindEnum; +CV_C13ChecksumKindEnum; -typedef struct CV_C13_Checksum CV_C13_Checksum; -struct CV_C13_Checksum +typedef struct CV_C13Checksum CV_C13Checksum; +struct CV_C13Checksum { U32 name_off; U8 len; - CV_C13_ChecksumKind kind; + CV_C13ChecksumKind kind; }; //- Lines sub-section -typedef U16 CV_C13_SubSecLinesFlags; +typedef U16 CV_C13SubSecLinesFlags; enum { - CV_C13_SubSecLinesFlag_HasColumns = (1 << 0) + CV_C13SubSecLinesFlag_HasColumns = (1 << 0) }; -typedef struct CV_C13_SubSecLinesHeader CV_C13_SubSecLinesHeader; -struct CV_C13_SubSecLinesHeader +typedef struct CV_C13SubSecLinesHeader CV_C13SubSecLinesHeader; +struct CV_C13SubSecLinesHeader { U32 sec_off; CV_SectionIndex sec; - CV_C13_SubSecLinesFlags flags; + CV_C13SubSecLinesFlags flags; U32 len; }; -typedef struct CV_C13_File CV_C13_File; -struct CV_C13_File +typedef struct CV_C13File CV_C13File; +struct CV_C13File { U32 file_off; U32 num_lines; U32 block_size; - // CV_C13_Line[num_lines] lines; - // CV_C13_Column[num_lines] columns; (if HasColumns) + // CV_C13Line[num_lines] lines; + // CV_C13Column[num_lines] columns; (if HasColumns) }; -typedef U32 CV_C13_LineFlags; -#define CV_C13_LineFlags_ExtractLineNumber(f) ((f)&0xFFFFFF) -#define CV_C13_LineFlags_ExtractDeltaToEnd(f) (((f)>>24)&0x7F) -#define CV_C13_LineFlags_ExtractStatement(f) (((f)>>31)&0x1) +typedef U32 CV_C13LineFlags; +#define CV_C13LineFlags_ExtractLineNumber(f) ((f)&0xFFFFFF) +#define CV_C13LineFlags_ExtractDeltaToEnd(f) (((f)>>24)&0x7F) +#define CV_C13LineFlags_ExtractStatement(f) (((f)>>31)&0x1) -typedef struct CV_C13_Line CV_C13_Line; -struct CV_C13_Line +typedef struct CV_C13Line CV_C13Line; +struct CV_C13Line { U32 off; - CV_C13_LineFlags flags; + CV_C13LineFlags flags; }; -typedef struct CV_C13_Column CV_C13_Column; -struct CV_C13_Column +typedef struct CV_C13Column CV_C13Column; +struct CV_C13Column { U16 start; U16 end; @@ -2754,16 +2754,16 @@ struct CV_C13_Column //- FrameData sub-section -typedef U32 CV_C13_FrameDataFlags; +typedef U32 CV_C13FrameDataFlags; enum { - CV_C13_FrameDataFlag_HasStructuredExceptionHandling = (1 << 0), - CV_C13_FrameDataFlag_HasExceptionHandling = (1 << 1), - CV_C13_FrameDataFlag_HasIsFuncStart = (1 << 2), + CV_C13FrameDataFlag_HasStructuredExceptionHandling = (1 << 0), + CV_C13FrameDataFlag_HasExceptionHandling = (1 << 1), + CV_C13FrameDataFlag_HasIsFuncStart = (1 << 2), }; -typedef struct CV_C13_FrameData CV_C13_FrameData; -struct CV_C13_FrameData +typedef struct CV_C13FrameData CV_C13FrameData; +struct CV_C13FrameData { U32 start_voff; U32 code_size; @@ -2773,25 +2773,25 @@ struct CV_C13_FrameData U32 frame_func; U16 prolog_size; U16 saved_reg_size; - CV_C13_FrameDataFlags flags; + CV_C13FrameDataFlags flags; }; //- InlineLines sub-section -typedef U32 CV_C13_InlineeLinesSig; +typedef U32 CV_C13InlineeLinesSig; enum { - CV_C13_InlineeLinesSig_NORMAL, - CV_C13_InlineeLinesSig_EXTRA_FILES, + CV_C13InlineeLinesSig_NORMAL, + CV_C13InlineeLinesSig_EXTRA_FILES, }; -typedef struct CV_C13_InlineeSourceLineHeader CV_C13_InlineeSourceLineHeader; -struct CV_C13_InlineeSourceLineHeader +typedef struct CV_C13InlineeSourceLineHeader CV_C13InlineeSourceLineHeader; +struct CV_C13InlineeSourceLineHeader { CV_ItemId inlinee; // LF_FUNC_ID or LF_MFUNC_ID U32 file_off; // offset into FileChksms sub-section U32 first_source_ln; // base source line number for binary annotations - // if sig set to CV_C13_InlineeLinesSig_EXTRA_FILES + // if sig set to CV_C13InlineeLinesSig_EXTRA_FILES // U32 extra_file_count; // U32 files[]; }; @@ -2871,7 +2871,6 @@ struct CV_SymParsed CV_SymTopLevelInfo info; }; - //////////////////////////////// //~ CodeView Leaf Parser Types @@ -2913,26 +2912,51 @@ struct CV_C13LinesParsedNode CV_C13LinesParsed v; }; +typedef struct CV_C13InlineeLinesParsed CV_C13InlineeLinesParsed; +struct CV_C13InlineeLinesParsed +{ + CV_ItemId inlinee; + String8 file_name; + U32 first_source_ln; + U32 extra_file_count; + U32 *extra_files; +}; + +typedef struct CV_C13InlineeLinesParsedNode CV_C13InlineeLinesParsedNode; +struct CV_C13InlineeLinesParsedNode +{ + CV_C13InlineeLinesParsedNode *next; + CV_C13InlineeLinesParsedNode *hash_next; + CV_C13InlineeLinesParsed v; +}; + typedef struct CV_C13SubSectionNode CV_C13SubSectionNode; struct CV_C13SubSectionNode { struct CV_C13SubSectionNode *next; - CV_C13_SubSectionKind kind; + CV_C13SubSectionKind kind; U32 off; U32 size; CV_C13LinesParsedNode *lines_first; CV_C13LinesParsedNode *lines_last; + CV_C13InlineeLinesParsedNode *inlinee_lines_first; + CV_C13InlineeLinesParsedNode *inlinee_lines_last; }; typedef struct CV_C13Parsed CV_C13Parsed; struct CV_C13Parsed { + // rjf: full sub-section list CV_C13SubSectionNode *first_sub_section; CV_C13SubSectionNode *last_sub_section; U64 sub_section_count; - // accelerator + // rjf: fastpath to file checksums section CV_C13SubSectionNode *file_chksms_sub_section; + + // rjf: fastpath to map inlinee CV_ItemId -> CV_InlineeLinesParsed quickly + CV_C13InlineeLinesParsedNode **inlinee_lines_parsed_slots; + U64 inlinee_lines_parsed_slots_count; }; //////////////////////////////// @@ -2946,52 +2970,42 @@ struct CV_TypeIdArray }; //////////////////////////////// -//~ CodeView Common Functions +//~ CodeView Common Decoding Helper Functions + +internal U64 cv_hash_from_string(String8 string); +internal U64 cv_hash_from_item_id(CV_ItemId item_id); internal CV_NumericParsed cv_numeric_from_data_range(U8 *first, U8 *opl); -internal B32 cv_numeric_fits_in_u64(CV_NumericParsed *num); -internal B32 cv_numeric_fits_in_s64(CV_NumericParsed *num); -internal B32 cv_numeric_fits_in_f64(CV_NumericParsed *num); +internal B32 cv_numeric_fits_in_u64(CV_NumericParsed *num); +internal B32 cv_numeric_fits_in_s64(CV_NumericParsed *num); +internal B32 cv_numeric_fits_in_f64(CV_NumericParsed *num); -internal U64 cv_u64_from_numeric(CV_NumericParsed *num); -internal S64 cv_s64_from_numeric(CV_NumericParsed *num); -internal F64 cv_f64_from_numeric(CV_NumericParsed *num); - -//////////////////////////////// -//~ Inline Binary Annotation Helpers +internal U64 cv_u64_from_numeric(CV_NumericParsed *num); +internal S64 cv_s64_from_numeric(CV_NumericParsed *num); +internal F64 cv_f64_from_numeric(CV_NumericParsed *num); internal U64 cv_decode_inline_annot_u32(String8 data, U64 offset, U32 *out_value); internal U64 cv_decode_inline_annot_s32(String8 data, U64 offset, S32 *out_value); //////////////////////////////// -//~ CodeView Sym/Leaf Parser Functions +//~ CodeView Parsing Functions -//- the first pass parser -internal CV_RecRangeStream* cv_rec_range_stream_from_data(Arena *arena, String8 data, U64 align); +//- rjf: record range stream parsing +internal CV_RecRangeStream *cv_rec_range_stream_from_data(Arena *arena, String8 data, U64 align); +internal CV_RecRangeArray cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream); -//- sym -internal CV_SymParsed* cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align); +//- rjf: sym stream parsing +internal CV_SymParsed *cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align); -internal void cv_sym_top_level_info_from_syms(Arena *arena, String8 sym_data, - CV_RecRangeArray *ranges, - CV_SymTopLevelInfo *info_out); - -//- leaf -internal CV_LeafParsed* cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId first); - -//- range streams -internal CV_RecRangeChunk* cv_rec_range_stream_push_chunk(Arena *arena, - CV_RecRangeStream *stream); -// TODO(allen): check why this isn't a pointer return - -// leave a note if there's a good reason, otherwise switch to pointer return -internal CV_RecRangeArray cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream); +//- rjf: leaf stream parsing +internal CV_LeafParsed *cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId first); //////////////////////////////// //~ CodeView C13 Parser Functions typedef struct PDB_Strtbl PDB_Strtbl; typedef struct PDB_CoffSectionArray PDB_CoffSectionArray; -internal CV_C13Parsed* cv_c13_from_data(Arena *arena, String8 c13_data, struct PDB_Strtbl *strtbl, struct PDB_CoffSectionArray *sections); +internal CV_C13Parsed *cv_c13_parsed_from_data(Arena *arena, String8 c13_data, struct PDB_Strtbl *strtbl, struct PDB_CoffSectionArray *sections); #endif // CODEVIEW_H diff --git a/src/codeview/codeview_stringize.c b/src/codeview/codeview_stringize.c index 9c1245ae..8539ab96 100644 --- a/src/codeview/codeview_stringize.c +++ b/src/codeview/codeview_stringize.c @@ -49,12 +49,12 @@ cv_stringize_lvar_addr_gap_list(Arena *arena, String8List *out, void *first, voi } internal String8 -cv_string_from_c13_sub_section_kind(CV_C13_SubSectionKind kind){ +cv_string_from_c13_sub_section_kind(CV_C13SubSectionKind kind){ String8 result = str8_lit("UNRECOGNIZED_C13_SUB_SECTION_KIND"); switch (kind){ case 0: str8_lit("PARSE_ERROR"); break; -#define X(N,c) case CV_C13_SubSectionKind_##N: result = str8_lit(#N); break; - CV_C13_SubSectionKindXList(X) +#define X(N,c) case CV_C13SubSectionKind_##N: result = str8_lit(#N); break; + CV_C13SubSectionKindXList(X) #undef X } return(result); @@ -2280,7 +2280,7 @@ cv_stringize_c13_parsed(Arena *arena, String8List *out, CV_C13Parsed *c13){ switch(node->kind) { - case CV_C13_SubSectionKind_Lines: + case CV_C13SubSectionKind_Lines: { if (node->lines_first == 0) { @@ -2309,12 +2309,12 @@ cv_stringize_c13_parsed(Arena *arena, String8List *out, CV_C13Parsed *c13){ } }break; - case CV_C13_SubSectionKind_FileChksms: + case CV_C13SubSectionKind_FileChksms: { str8_list_push(arena, out, str8_lit(" no stringizer path\n")); }break; - case CV_C13_SubSectionKind_InlineeLines: + case CV_C13SubSectionKind_InlineeLines: { str8_list_push(arena, out, str8_lit(" no stringizer path\n")); }break; diff --git a/src/codeview/codeview_stringize.h b/src/codeview/codeview_stringize.h index b37cd904..9a94d9c4 100644 --- a/src/codeview/codeview_stringize.h +++ b/src/codeview/codeview_stringize.h @@ -27,7 +27,7 @@ internal void cv_stringize_lvar_addr_gap_list(Arena *arena, String8List *out, void *first, void *opl); internal String8 cv_string_from_basic_type(CV_BasicType basic_type); -internal String8 cv_string_from_c13_sub_section_kind(CV_C13_SubSectionKind kind); +internal String8 cv_string_from_c13_sub_section_kind(CV_C13SubSectionKind kind); internal String8 cv_string_from_reg(CV_Arch arch, CV_Reg reg); internal String8 cv_string_from_pointer_kind(CV_PointerKind ptr_kind); internal String8 cv_string_from_pointer_mode(CV_PointerMode ptr_mode); diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index e31518eb..2204645c 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -544,7 +544,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_c13_stream_parse_task__entry_point) { P2R_C13StreamParseIn *in = (P2R_C13StreamParseIn *)p; void *out = 0; - ProfScope("parse c13 stream") out = cv_c13_from_data(arena, in->data, in->strtbl, in->coff_sections); + ProfScope("parse c13 stream") out = cv_c13_parsed_from_data(arena, in->data, in->strtbl, in->coff_sections); return out; } @@ -608,59 +608,67 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) //- rjf: build this unit's line table RDIM_LineTable *line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 256); - if(pdb_unit_c13->first_sub_section != 0) + for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; + node != 0; + node = node->next) { - for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; - node != 0; - node = node->next) + if(node->kind == CV_C13SubSectionKind_Lines) { - if(node->kind == CV_C13_SubSectionKind_Lines) + for(CV_C13LinesParsedNode *lines_n = node->lines_first; + lines_n != 0; + lines_n = lines_n->next) { - for(CV_C13LinesParsedNode *lines_n = node->lines_first; - lines_n != 0; - lines_n = lines_n->next) + CV_C13LinesParsed *lines = &lines_n->v; + + // rjf: file name -> normalized file path + String8 file_path = lines->file_name; + String8 file_path_normalized = lower_from_str8(scratch.arena, str8_skip_chop_whitespace(file_path)); + for(U64 idx = 0; idx < file_path_normalized.size; idx += 1) { - CV_C13LinesParsed *lines = &lines_n->v; - - // rjf: file name -> normalized file path - String8 file_path = lines->file_name; - String8 file_path_normalized = lower_from_str8(scratch.arena, str8_skip_chop_whitespace(file_path)); - for(U64 idx = 0; idx < file_path_normalized.size; idx += 1) + if(file_path_normalized.str[idx] == '\\') { - if(file_path_normalized.str[idx] == '\\') - { - file_path_normalized.str[idx] = '/'; - } + file_path_normalized.str[idx] = '/'; } - - // rjf: normalized file path -> source file node - U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); - U64 src_file_slot = file_path_normalized_hash%src_file_map.slots_count; - P2R_SrcFileNode *src_file_node = 0; - for(P2R_SrcFileNode *n = src_file_map.slots[src_file_slot]; n != 0; n = n->next) - { - if(str8_match(n->src_file->normal_full_path, file_path_normalized, 0)) - { - src_file_node = n; - break; - } - } - if(src_file_node == 0) - { - src_file_node = push_array(scratch.arena, P2R_SrcFileNode, 1); - SLLStackPush(src_file_map.slots[src_file_slot], src_file_node); - src_file_node->src_file = rdim_src_file_chunk_list_push(arena, &out->src_files, 4096); - src_file_node->src_file->normal_full_path = push_str8_copy(arena, file_path_normalized); - } - - // rjf: push sequence into both line table & source file's line map - RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, lines->voffs, lines->line_nums, lines->col_nums, lines->line_count); - rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); } + + // rjf: normalized file path -> source file node + U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); + U64 src_file_slot = file_path_normalized_hash%src_file_map.slots_count; + P2R_SrcFileNode *src_file_node = 0; + for(P2R_SrcFileNode *n = src_file_map.slots[src_file_slot]; n != 0; n = n->next) + { + if(str8_match(n->src_file->normal_full_path, file_path_normalized, 0)) + { + src_file_node = n; + break; + } + } + if(src_file_node == 0) + { + src_file_node = push_array(scratch.arena, P2R_SrcFileNode, 1); + SLLStackPush(src_file_map.slots[src_file_slot], src_file_node); + src_file_node->src_file = rdim_src_file_chunk_list_push(arena, &out->src_files, 4096); + src_file_node->src_file->normal_full_path = push_str8_copy(arena, file_path_normalized); + } + + // rjf: push sequence into both line table & source file's line map + RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, lines->voffs, lines->line_nums, lines->col_nums, lines->line_count); + rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); } } } + //- rjf: build all inlinee line tables within this unit + for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; + node != 0; + node = node->next) + { + if(node->kind == CV_C13SubSectionKind_InlineeLines) + { + + } + } + //- rjf: build unit RDIM_Unit *dst_unit = rdim_unit_chunk_list_push(arena, &out->units, units_chunk_cap); dst_unit->unit_name = unit_name; @@ -2506,6 +2514,22 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) CV_SymInlineSite *sym = (CV_SymInlineSite *)sym_header_struct_base; String8 binary_annots = str8((U8 *)(sym+1), rec_range->hdr.size - sizeof(rec_range->hdr.kind) - sizeof(*sym)); + // rjf: map inlinee -> parsed cv c13 inlinee line info + CV_C13InlineeLinesParsed *inlinee_lines_parsed = 0; + if(in->c13 != 0) + { + U64 hash = cv_hash_from_item_id(sym->inlinee); + U64 slot_idx = in->c13->inlinee_lines_parsed_slots_count; + for(CV_C13InlineeLinesParsedNode *n = in->c13->inlinee_lines_parsed_slots[slot_idx]; n != 0; n = n->hash_next) + { + if(n->v.inlinee == sym->inlinee) + { + inlinee_lines_parsed = &n->v; + break; + } + } + } + // rjf: extract external info about inline site String8 name = str8_zero(); RDIM_Type *type = 0; @@ -3577,6 +3601,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) tasks_inputs[idx].sym = sym_for_unit[idx-global_stream_subdivision_tasks_count]; tasks_inputs[idx].sym_ranges_first= 0; tasks_inputs[idx].sym_ranges_opl = sym_for_unit[idx-global_stream_subdivision_tasks_count]->sym_ranges.count; + tasks_inputs[idx].c13 = c13_for_unit[idx-global_stream_subdivision_tasks_count]; } tasks_tickets[idx] = ts_kickoff(p2r_symbol_stream_convert_task__entry_point, 0, &tasks_inputs[idx]); } diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index c8f776b9..2a17447a 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -251,6 +251,7 @@ struct P2R_SymbolStreamConvertIn CV_LeafParsed *tpi_leaf; CV_LeafParsed *ipi_leaf; CV_SymParsed *sym; + CV_C13Parsed *c13; U64 sym_ranges_first; U64 sym_ranges_opl; CV_TypeId *itype_fwd_map; From cfd2380caa5284cdc5ea2a334ebbfd3ad42e677f Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 7 Jun 2024 17:22:45 -0700 Subject: [PATCH 25/44] rdi_from_pdb: sketch out unified inlinee parsing/gathering path in units conversion task --- src/lib_rdi_make/rdi_make.c | 2 - src/rdi_from_pdb/rdi_from_pdb.c | 99 +++++++++++++++++++++++---------- src/rdi_from_pdb/rdi_from_pdb.h | 18 +++++- 3 files changed, 88 insertions(+), 31 deletions(-) diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index 81f78189..b976d23f 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -2803,7 +2803,6 @@ rdim_bake_line_tables(RDIM_Arena *arena, RDIM_LineTableChunkList *src) //- rjf: sort RDIM_SortKey *sorted_line_keys = 0; - RDIM_ProfScope("sort") { sorted_line_keys = rdim_sort_key_array(scratch.arena, line_keys, key_count); } @@ -2815,7 +2814,6 @@ rdim_bake_line_tables(RDIM_Arena *arena, RDIM_LineTableChunkList *src) //- rjf: arrange output RDI_U64 *arranged_voffs = dst_line_voffs + dst_voff_idx; RDI_Line *arranged_lines = dst_lines + dst_line_idx; - RDIM_ProfScope("arrange output") { for(RDI_U64 i = 0; i < key_count; i += 1) { diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index 2204645c..cd9ab282 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -580,7 +580,9 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) src_file_map.slots_count = 65536; src_file_map.slots = push_array(scratch.arena, P2R_SrcFileNode *, src_file_map.slots_count); + //////////////////////////// //- rjf: pass 1: build per-unit info & per-unit line tables + // for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) { PDB_CompUnit *pdb_unit = in->comp_units->units[comp_unit_idx]; @@ -658,17 +660,6 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) } } - //- rjf: build all inlinee line tables within this unit - for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; - node != 0; - node = node->next) - { - if(node->kind == CV_C13SubSectionKind_InlineeLines) - { - - } - } - //- rjf: build unit RDIM_Unit *dst_unit = rdim_unit_chunk_list_push(arena, &out->units, units_chunk_cap); dst_unit->unit_name = unit_name; @@ -679,7 +670,9 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) dst_unit->line_table = line_table; } + //////////////////////////// //- rjf: pass 2: build per-unit voff ranges from comp unit contributions table + // PDB_CompUnitContribution *contrib_ptr = in->comp_unit_contributions->contributions; PDB_CompUnitContribution *contrib_opl = contrib_ptr + in->comp_unit_contributions->count; for(;contrib_ptr < contrib_opl; contrib_ptr += 1) @@ -691,6 +684,73 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) rdim_rng1u64_list_push(arena, &unit->voff_ranges, range); } } + + //////////////////////////// + //- rjf: pass 3: parse all inlinee line tables + // + for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) + { + CV_SymParsed *unit_sym = in->comp_unit_syms[comp_unit_idx]; + CV_C13Parsed *unit_c13 = in->comp_unit_c13s[comp_unit_idx]; + CV_RecRange *rec_ranges_first = unit_sym->sym_ranges.ranges; + CV_RecRange *rec_ranges_opl = rec_ranges_first+unit_sym->sym_ranges.count; + for(CV_RecRange *rec_range = rec_ranges_first; + rec_range < rec_ranges_opl; + rec_range += 1) + { + //- rjf: rec range -> symbol info range + U64 sym_off_first = rec_range->off + 2; + U64 sym_off_opl = rec_range->off + rec_range->hdr.size; + + //- rjf: skip invalid ranges + if(sym_off_opl > unit_sym->data.size || sym_off_first > unit_sym->data.size || sym_off_first > sym_off_opl) + { + continue; + } + + //- rjf: unpack symbol info + CV_SymKind kind = rec_range->hdr.kind; + U64 sym_header_struct_size = cv_header_struct_size_from_sym_kind(kind); + void *sym_header_struct_base = unit_sym->data.str + sym_off_first; + void *sym_data_opl = unit_sym->data.str + sym_off_opl; + + //- rjf: skip bad sizes + if(sym_off_first + sym_header_struct_size > sym_off_opl) + { + continue; + } + + //- rjf: process symbol + switch(kind) + { + default:{}break; + case CV_SymKind_INLINESITE: + { + // rjf: unpack sym + CV_SymInlineSite *sym = (CV_SymInlineSite *)sym_header_struct_base; + String8 binary_annots = str8((U8 *)(sym+1), rec_range->hdr.size - sizeof(rec_range->hdr.kind) - sizeof(*sym)); + + // rjf: map inlinee -> parsed cv c13 inlinee line info + CV_C13InlineeLinesParsed *inlinee_lines_parsed = 0; + { + U64 hash = cv_hash_from_item_id(sym->inlinee); + U64 slot_idx = unit_c13->inlinee_lines_parsed_slots_count; + for(CV_C13InlineeLinesParsedNode *n = unit_c13->inlinee_lines_parsed_slots[slot_idx]; n != 0; n = n->hash_next) + { + if(n->v.inlinee == sym->inlinee) + { + inlinee_lines_parsed = &n->v; + break; + } + } + } + + // rjf: build line table + RDIM_LineTable *line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 4096); + }break; + } + } + } } scratch_end(scratch); return out; @@ -2514,22 +2574,6 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) CV_SymInlineSite *sym = (CV_SymInlineSite *)sym_header_struct_base; String8 binary_annots = str8((U8 *)(sym+1), rec_range->hdr.size - sizeof(rec_range->hdr.kind) - sizeof(*sym)); - // rjf: map inlinee -> parsed cv c13 inlinee line info - CV_C13InlineeLinesParsed *inlinee_lines_parsed = 0; - if(in->c13 != 0) - { - U64 hash = cv_hash_from_item_id(sym->inlinee); - U64 slot_idx = in->c13->inlinee_lines_parsed_slots_count; - for(CV_C13InlineeLinesParsedNode *n = in->c13->inlinee_lines_parsed_slots[slot_idx]; n != 0; n = n->hash_next) - { - if(n->v.inlinee == sym->inlinee) - { - inlinee_lines_parsed = &n->v; - break; - } - } - } - // rjf: extract external info about inline site String8 name = str8_zero(); RDIM_Type *type = 0; @@ -3601,7 +3645,6 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) tasks_inputs[idx].sym = sym_for_unit[idx-global_stream_subdivision_tasks_count]; tasks_inputs[idx].sym_ranges_first= 0; tasks_inputs[idx].sym_ranges_opl = sym_for_unit[idx-global_stream_subdivision_tasks_count]->sym_ranges.count; - tasks_inputs[idx].c13 = c13_for_unit[idx-global_stream_subdivision_tasks_count]; } tasks_tickets[idx] = ts_kickoff(p2r_symbol_stream_convert_task__entry_point, 0, &tasks_inputs[idx]); } diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index 2a17447a..b13d3a9d 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -152,6 +152,23 @@ struct P2R_LinkNameMap U64 link_name_count; }; +//- rjf: inlinee line table map (item id -> line table) + +typedef struct P2R_InlineeLineTableMapNode P2R_InlineeLineTableMapNode; +struct P2R_InlineeLineTableMapNode +{ + P2R_InlineeLineTableMapNode *next; + CV_ItemId id; + RDIM_LineTable *line_table; +}; + +typedef struct P2R_InlineeLineTableMap P2R_InlineeLineTableMap; +struct P2R_InlineeLineTableMap +{ + P2R_InlineeLineTableMapNode **slots; + U64 slots_count; +}; + //- rjf: normalized file path -> source file map typedef struct P2R_SrcFileNode P2R_SrcFileNode; @@ -251,7 +268,6 @@ struct P2R_SymbolStreamConvertIn CV_LeafParsed *tpi_leaf; CV_LeafParsed *ipi_leaf; CV_SymParsed *sym; - CV_C13Parsed *c13; U64 sym_ranges_first; U64 sym_ranges_opl; CV_TypeId *itype_fwd_map; From 6f92fe971a35e77d1e3b6f4c82654471c7160487 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 10 Jun 2024 09:18:05 -0700 Subject: [PATCH 26/44] rdi_from_pdb: inline binary annotations parsing --- src/codeview/codeview.c | 16 ++++ src/codeview/codeview.h | 6 ++ src/rdi_from_pdb/rdi_from_pdb.c | 162 ++++++++++++++++++++++++++++++-- src/rdi_from_pdb/rdi_from_pdb.h | 1 + 4 files changed, 179 insertions(+), 6 deletions(-) diff --git a/src/codeview/codeview.c b/src/codeview/codeview.c index 1919ad64..439a960d 100644 --- a/src/codeview/codeview.c +++ b/src/codeview/codeview.c @@ -237,6 +237,21 @@ cv_decode_inline_annot_s32(String8 data, U64 offset, S32 *out_value) return read_size; } +internal S32 +cv_inline_annot_signed_from_unsigned_operand(U32 value) +{ + if(value & 1) + { + value = -(value >> 1); + } + else + { + value = value >> 1; + } + S32 result = (S32)value; + return result; +} + //////////////////////////////// //~ CodeView Parsing Functions @@ -611,6 +626,7 @@ cv_c13_parsed_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_ //- rjf: fill output // CV_C13Parsed *result = push_array(arena, CV_C13Parsed, 1); + result->data = c13_data; result->first_sub_section = first; result->last_sub_section = last; result->sub_section_count = count; diff --git a/src/codeview/codeview.h b/src/codeview/codeview.h index 4b5c4000..b74dabd2 100644 --- a/src/codeview/codeview.h +++ b/src/codeview/codeview.h @@ -2946,6 +2946,9 @@ struct CV_C13SubSectionNode typedef struct CV_C13Parsed CV_C13Parsed; struct CV_C13Parsed { + // rjf: source data + String8 data; + // rjf: full sub-section list CV_C13SubSectionNode *first_sub_section; CV_C13SubSectionNode *last_sub_section; @@ -2988,6 +2991,9 @@ internal F64 cv_f64_from_numeric(CV_NumericParsed *num); internal U64 cv_decode_inline_annot_u32(String8 data, U64 offset, U32 *out_value); internal U64 cv_decode_inline_annot_s32(String8 data, U64 offset, S32 *out_value); +internal S32 cv_inline_annot_signed_from_unsigned_operand(U32 value); + + //////////////////////////////// //~ CodeView Parsing Functions diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index cd9ab282..de9f07bb 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -583,7 +583,8 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) //////////////////////////// //- rjf: pass 1: build per-unit info & per-unit line tables // - for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) + ProfScope("pass 1: build per-unit info & per-unit line tables") + for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) { PDB_CompUnit *pdb_unit = in->comp_units->units[comp_unit_idx]; CV_SymParsed *pdb_unit_sym = in->comp_unit_syms[comp_unit_idx]; @@ -675,7 +676,8 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) // PDB_CompUnitContribution *contrib_ptr = in->comp_unit_contributions->contributions; PDB_CompUnitContribution *contrib_opl = contrib_ptr + in->comp_unit_contributions->count; - for(;contrib_ptr < contrib_opl; contrib_ptr += 1) + ProfScope("pass 2: build per-unit voff ranges from comp unit contributions table") + for(;contrib_ptr < contrib_opl; contrib_ptr += 1) { if(contrib_ptr->mod < in->comp_units->count) { @@ -688,7 +690,8 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) //////////////////////////// //- rjf: pass 3: parse all inlinee line tables // - for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) + ProfScope("pass 3: parse all inlinee line tables") + for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) { CV_SymParsed *unit_sym = in->comp_unit_syms[comp_unit_idx]; CV_C13Parsed *unit_c13 = in->comp_unit_c13s[comp_unit_idx]; @@ -745,8 +748,155 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) } } - // rjf: build line table - RDIM_LineTable *line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 4096); + // rjf: build line table, fill with parsed binary annotations + RDIM_LineTable *line_table = 0; + if(inlinee_lines_parsed != 0) + { + // rjf: build line table + line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 4096); + + // rjf: state machine registers + CV_InlineRangeKind range_kind = 0; + U32 code_length = 0; + U32 code_offset = 0; + String8 file_name = inlinee_lines_parsed->file_name; + S32 line = (S32)inlinee_lines_parsed->first_source_ln; + S32 column = 1; + U64 code_offset_lo = 0; + B32 code_offset_changed = 0; + B32 code_offset_lo_changed = 0; + B32 code_length_changed = 0; + B32 ln_changed = 1; + B32 file_off_changed = 0; + + // rjf: grab checksums sub-section + CV_C13SubSectionNode *file_chksms = unit_c13->file_chksms_sub_section; + + // rjf: decode loop + U64 read_off = 0; + U64 read_off_opl = binary_annots.size; + for(B32 good = 1; read_off < read_off_opl && good;) + { + // rjf: decode next annotation op + U32 op = CV_InlineBinaryAnnotation_Null; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &op); + + // rjf: apply op + switch(op) + { + default:{good = 0;}break; + case CV_InlineBinaryAnnotation_Null: + { + }break; + case CV_InlineBinaryAnnotation_CodeOffset: + { + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_offset); + }break; + case CV_InlineBinaryAnnotation_ChangeCodeOffsetBase: + { + good = 0; + // TODO(rjf): currently untested/unknown - first guess below: + // + // U32 delta = 0; + // read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &delta); + // code_offset_base = code_offset; + // code_offset_end = code_offset + delta; + // code_offset += delta; + }break; + case CV_InlineBinaryAnnotation_ChangeCodeOffset: + { + U32 delta = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &delta); + code_offset += delta; + }break; + case CV_InlineBinaryAnnotation_ChangeCodeLength: + { + code_length = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_length); + }break; + case CV_InlineBinaryAnnotation_ChangeFile: + { + U32 new_file_off = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &new_file_off); + String8 new_file_name = {0}; + if(new_file_off + sizeof(CV_C13Checksum) <= file_chksms->size) + { + CV_C13Checksum *checksum = (CV_C13Checksum*)(unit_c13->data.str + file_chksms->off + new_file_off); + U32 name_off = checksum->name_off; + new_file_name = pdb_strtbl_string_from_off(in->pdb_strtbl, name_off); + } + file_name = new_file_name; + }break; + case CV_InlineBinaryAnnotation_ChangeLineOffset: + { + S32 delta = 0; + read_off += cv_decode_inline_annot_s32(binary_annots, read_off, &delta); + line += delta; + }break; + case CV_InlineBinaryAnnotation_ChangeLineEndDelta: + { + good = 0; + // TODO(rjf): currently untested/unknown - first guess below: + // + // S32 end_delta = 1; + // read_off += cv_decode_inline_annot_s32(binary_annots, read_off, &end_delta); + // line += end_delta; + }break; + case CV_InlineBinaryAnnotation_ChangeRangeKind: + { + good = 0; + // TODO(rjf): currently untested/unknown - first guess below: + // + // read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &range_kind); + }break; + case CV_InlineBinaryAnnotation_ChangeColumnStart: + { + good = 0; + // TODO(rjf): currently untested/unknown - first guess below: + // + // S32 delta = 0; + // read_off += cv_decode_inline_annot_s32(binary_annots, read_off, &delta); + // column += delta; + }break; + case CV_InlineBinaryAnnotation_ChangeColumnEndDelta: + { + // TODO(rjf): currently untested/unknown - first guess below: + // + // S32 end_delta = 0; + // read_off += cv_decode_inline_annot_s32(binary_annots, read_off, &end_delta); + // column += end_delta; + }break; + case CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset: + { + U32 code_offset_and_line_offset = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_offset_and_line_offset); + U32 code_delta = (code_offset_and_line_offset & 0xf); + S32 line_delta = cv_inline_annot_signed_from_unsigned_operand(code_offset_and_line_offset >> 4); + code_offset += code_delta; + line += line_delta; + }break; + case CV_InlineBinaryAnnotation_ChangeCodeLengthAndCodeOffset: + { + U32 offset_delta = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_length); + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &offset_delta); + code_offset += offset_delta; + }break; + case CV_InlineBinaryAnnotation_ChangeColumnEnd: + { + // TODO(rjf): currently untested/unknown - first guess below: + // + // U32 column_end = 0; + // read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &column_end); + }break; + } + } + } + + // rjf: insert line table to map, for later lookups + { + // TODO(rjf) + } }break; } } @@ -2981,7 +3131,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) ////////////////////////////////////////////////////////////// //- rjf: kick off unit conversion & source file collection // - P2R_UnitConvertIn unit_convert_in = {comp_units, comp_unit_contributions, sym_for_unit, c13_for_unit}; + P2R_UnitConvertIn unit_convert_in = {strtbl, comp_units, comp_unit_contributions, sym_for_unit, c13_for_unit}; TS_Ticket unit_convert_ticket = ts_kickoff(p2r_units_convert_task__entry_point, 0, &unit_convert_in); ////////////////////////////////////////////////////////////// diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index b13d3a9d..d4285ca8 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -190,6 +190,7 @@ struct P2R_SrcFileMap typedef struct P2R_UnitConvertIn P2R_UnitConvertIn; struct P2R_UnitConvertIn { + PDB_Strtbl *pdb_strtbl; PDB_CompUnitArray *comp_units; PDB_CompUnitContributionArray *comp_unit_contributions; CV_SymParsed **comp_unit_syms; From 4888f90f7fe399364000d3c240e7d7bcadd9e2ce Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 10 Jun 2024 09:45:41 -0700 Subject: [PATCH 27/44] rdi_from_pdb: next checkpoint on inline line table parsing/conversion --- src/rdi_from_pdb/rdi_from_pdb.c | 112 ++++++++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 6 deletions(-) diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index de9f07bb..22d05d59 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -732,6 +732,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) // rjf: unpack sym CV_SymInlineSite *sym = (CV_SymInlineSite *)sym_header_struct_base; String8 binary_annots = str8((U8 *)(sym+1), rec_range->hdr.size - sizeof(rec_range->hdr.kind) - sizeof(*sym)); + U64 base_voff = 0; // rjf: map inlinee -> parsed cv c13 inlinee line info CV_C13InlineeLinesParsed *inlinee_lines_parsed = 0; @@ -759,15 +760,28 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) CV_InlineRangeKind range_kind = 0; U32 code_length = 0; U32 code_offset = 0; + U32 last_code_offset = code_offset; String8 file_name = inlinee_lines_parsed->file_name; + String8 last_file_name = file_name; S32 line = (S32)inlinee_lines_parsed->first_source_ln; + S32 last_line = line; S32 column = 1; - U64 code_offset_lo = 0; - B32 code_offset_changed = 0; - B32 code_offset_lo_changed = 0; - B32 code_length_changed = 0; - B32 ln_changed = 1; - B32 file_off_changed = 0; + S32 last_column = column; + + // rjf: gathered lines + typedef struct LineChunk LineChunk; + struct LineChunk + { + LineChunk *next; + U64 cap; + U64 count; + U64 *voffs; // [line_count + 1] (sorted) + U32 *line_nums; // [line_count] + U16 *col_nums; // [2*line_count] + }; + LineChunk *first_line_chunk = 0; + LineChunk *last_line_chunk = 0; + U64 total_line_chunk_line_count = 0; // rjf: grab checksums sub-section CV_C13SubSectionNode *file_chksms = unit_c13->file_chksms_sub_section; @@ -787,6 +801,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) default:{good = 0;}break; case CV_InlineBinaryAnnotation_Null: { + good = 0; }break; case CV_InlineBinaryAnnotation_CodeOffset: { @@ -890,6 +905,91 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) // read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &column_end); }break; } + + // rjf: gather new lines + if(line != last_line || code_offset != last_code_offset) + { + LineChunk *chunk = last_line_chunk; + if(chunk == 0 || chunk->count+1 >= chunk->cap) + { + chunk = push_array(scratch.arena, LineChunk, 1); + SLLQueuePush(first_line_chunk, last_line_chunk, chunk); + chunk->cap = 256; + chunk->voffs = push_array_no_zero(scratch.arena, U64, chunk->cap); + chunk->line_nums = push_array_no_zero(scratch.arena, U32, chunk->cap); + } + chunk->voffs[chunk->count] = base_voff + code_offset; + chunk->voffs[chunk->count+1] = 0xffffffffffffffffull; + chunk->line_nums[chunk->count] = (U32)line; + chunk->count += 1; + total_line_chunk_line_count += 1; + } + + // rjf: push line sequence to line table & source file + if(!good || (op == CV_InlineBinaryAnnotation_ChangeFile && !str8_match(last_file_name, file_name, 0))) + { + String8 seq_file_name = last_file_name; // NOTE(rjf): `file_name` is possibly changed to the next sequence, so use previous + + // rjf: file name -> normalized file path + String8 file_path = seq_file_name; + String8 file_path_normalized = lower_from_str8(scratch.arena, str8_skip_chop_whitespace(file_path)); + for(U64 idx = 0; idx < file_path_normalized.size; idx += 1) + { + if(file_path_normalized.str[idx] == '\\') + { + file_path_normalized.str[idx] = '/'; + } + } + + // rjf: normalized file path -> source file node + U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); + U64 src_file_slot = file_path_normalized_hash%src_file_map.slots_count; + P2R_SrcFileNode *src_file_node = 0; + for(P2R_SrcFileNode *n = src_file_map.slots[src_file_slot]; n != 0; n = n->next) + { + if(str8_match(n->src_file->normal_full_path, file_path_normalized, 0)) + { + src_file_node = n; + break; + } + } + if(src_file_node == 0) + { + src_file_node = push_array(scratch.arena, P2R_SrcFileNode, 1); + SLLStackPush(src_file_map.slots[src_file_slot], src_file_node); + src_file_node->src_file = rdim_src_file_chunk_list_push(arena, &out->src_files, 4096); + src_file_node->src_file->normal_full_path = push_str8_copy(arena, file_path_normalized); + } + + // rjf: gather all lines + RDI_U64 *voffs = push_array_no_zero(arena, RDI_U64, total_line_chunk_line_count+1); + RDI_U32 *line_nums = push_array_no_zero(arena, RDI_U32, total_line_chunk_line_count); + RDI_U64 line_count = total_line_chunk_line_count; + { + U64 dst_idx = 0; + for(LineChunk *chunk = first_line_chunk; chunk != 0; chunk = chunk->next) + { + MemoryCopy(voffs+dst_idx, chunk->voffs, sizeof(U64)*chunk->count); + MemoryCopy(line_nums+dst_idx, chunk->line_nums, sizeof(U32)*chunk->count); + dst_idx += chunk->count; + } + voffs[dst_idx] = 0xffffffffffffffffull; + } + + // rjf: push + RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, voffs, line_nums, 0, line_count); + rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); + + // rjf: clear line chunks for subsequent sequences + first_line_chunk = last_line_chunk = 0; + total_line_chunk_line_count = 0; + } + + // rjf: update prev/current states + last_file_name = file_name; + last_line = line; + last_column = column; + last_code_offset = code_offset; } } From 21b439e7e5f2e7e9fd176fc93c7f92aece3dff9a Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 10 Jun 2024 11:12:21 -0700 Subject: [PATCH 28/44] merged line table sort experiments --- project.4coder | 2 +- src/scratch/ryan_scratch.c | 54 +++++++++----------------------------- 2 files changed, 14 insertions(+), 42 deletions(-) diff --git a/project.4coder b/project.4coder index 460ed992..7a6b0ae3 100644 --- a/project.4coder +++ b/project.4coder @@ -47,7 +47,7 @@ commands = { .rjf_f1 = { - .win = "build raddbg telemetry", + .win = "build ryan_scratch no_meta && pushd build && ryan_scratch.exe && popd", .linux = "", .out = "*compilation*", .footer_panel = true, diff --git a/src/scratch/ryan_scratch.c b/src/scratch/ryan_scratch.c index 1087cf13..ad4b4c8c 100644 --- a/src/scratch/ryan_scratch.c +++ b/src/scratch/ryan_scratch.c @@ -4,10 +4,6 @@ //////////////////////////////// //~ rjf: Build Options -#define BUILD_VERSION_MAJOR 0 -#define BUILD_VERSION_MINOR 9 -#define BUILD_VERSION_PATCH 10 -#define BUILD_RELEASE_PHASE_STRING_LITERAL "ALPHA" #define BUILD_TITLE "ryan_scratch" #define BUILD_CONSOLE_INTERFACE 1 @@ -16,65 +12,33 @@ //- rjf: [lib] #include "lib_rdi_format/rdi_format.h" -#include "lib_rdi_format/rdi_format_parse.h" #include "lib_rdi_format/rdi_format.c" -#include "lib_rdi_format/rdi_format_parse.c" +#include "third_party/rad_lzb_simple/rad_lzb_simple.h" +#include "third_party/rad_lzb_simple/rad_lzb_simple.c" //- rjf: [h] #include "base/base_inc.h" #include "os/os_inc.h" #include "task_system/task_system.h" -#include "rdi_make_local/rdi_make_local.h" -#include "mdesk/mdesk.h" -#include "hash_store/hash_store.h" -#include "file_stream/file_stream.h" -#include "text_cache/text_cache.h" -#include "path/path.h" -#include "txti/txti.h" +#include "rdi_make/rdi_make_local.h" #include "coff/coff.h" -#include "pe/pe.h" #include "codeview/codeview.h" #include "codeview/codeview_stringize.h" #include "msf/msf.h" #include "pdb/pdb.h" #include "pdb/pdb_stringize.h" -#include "rdi_from_pdb/rdi_from_pdb.h" -#include "regs/regs.h" -#include "regs/rdi/regs_rdi.h" -#include "type_graph/type_graph.h" -#include "dbgi/dbgi.h" -#include "demon/demon_inc.h" -#include "eval/eval_inc.h" -#include "unwind/unwind.h" -#include "ctrl/ctrl_inc.h" //- rjf: [c] #include "base/base_inc.c" #include "os/os_inc.c" #include "task_system/task_system.c" -#include "rdi_make_local/rdi_make_local.c" -#include "mdesk/mdesk.c" -#include "hash_store/hash_store.c" -#include "file_stream/file_stream.c" -#include "text_cache/text_cache.c" -#include "path/path.c" -#include "txti/txti.c" +#include "rdi_make/rdi_make_local.c" #include "coff/coff.c" -#include "pe/pe.c" #include "codeview/codeview.c" #include "codeview/codeview_stringize.c" #include "msf/msf.c" #include "pdb/pdb.c" #include "pdb/pdb_stringize.c" -#include "rdi_from_pdb/rdi_from_pdb.c" -#include "regs/regs.c" -#include "regs/rdi/regs_rdi.c" -#include "type_graph/type_graph.c" -#include "dbgi/dbgi.c" -#include "demon/demon_inc.c" -#include "eval/eval_inc.c" -#include "unwind/unwind.c" -#include "ctrl/ctrl_inc.c" //////////////////////////////// //~ rjf: Entry Point @@ -82,5 +46,13 @@ internal void entry_point(CmdLine *cmdline) { - + Arena *arena = arena_alloc(); + RDIM_SortKey keys_unsorted[] = {{1, (void *)2}, {2}, {3}, {1, (void *)1}, {2}, {3}, {1, (void *)3}, {2}, {3}, {1, (void *)4}, {2}, {3}, {1, (void *)5}, {2}, {3}}; + U64 keys_count = ArrayCount(keys_unsorted); + RDIM_SortKey *keys_sorted = rdim_sort_key_array(arena, keys_unsorted, keys_count); + for(U64 idx = 0; idx < keys_count; idx += 1) + { + printf("%I64u (%I64u),", keys_sorted[idx].key, (U64)keys_sorted[idx].val); + } + printf("\n"); } From 61630f4cf9cd4b70118369dd936472712b0a26c2 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 10 Jun 2024 11:26:54 -0700 Subject: [PATCH 29/44] eliminate per-inline-site line tables; merge inline site line info with unit's line table --- src/lib_rdi_make/rdi_make.c | 1 + src/rdi_from_pdb/rdi_from_pdb.c | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index b976d23f..5dd75247 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -3338,6 +3338,7 @@ rdim_bake_scopes(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_Scope dst_scope->voff_range_opl = (RDI_U32)voff_idx_opl; // TODO(rjf): @u64_to_u32 dst_scope->local_first = (RDI_U32)local_idx_first; // TODO(rjf): @u64_to_u32 dst_scope->local_count = (RDI_U32)(local_idx_opl - local_idx_first); // TODO(rjf): @u64_to_u32 + dst_scope->inline_site_idx = (RDI_U32)rdim_idx_from_inline_site(src_scope->inline_site); // TODO(rjf): @u64_to_u32 } } } diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index 22d05d59..15be8d47 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -583,6 +583,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) //////////////////////////// //- rjf: pass 1: build per-unit info & per-unit line tables // + RDIM_LineTable **unit_line_tables = push_array(scratch.arena, RDIM_LineTable *, in->comp_units->count); ProfScope("pass 1: build per-unit info & per-unit line tables") for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) { @@ -609,8 +610,9 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) MemoryZeroStruct(&obj_name); } - //- rjf: build this unit's line table + //- rjf: build this unit's line table, fill out primary line info (inline info added after) RDIM_LineTable *line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 256); + unit_line_tables[comp_unit_idx] = line_table; for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; node != 0; node = node->next) @@ -753,9 +755,6 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) RDIM_LineTable *line_table = 0; if(inlinee_lines_parsed != 0) { - // rjf: build line table - line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 4096); - // rjf: state machine registers CV_InlineRangeKind range_kind = 0; U32 code_length = 0; @@ -977,7 +976,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) } // rjf: push - RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, voffs, line_nums, 0, line_count); + RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, unit_line_tables[comp_unit_idx], src_file_node->src_file, voffs, line_nums, 0, line_count); rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); // rjf: clear line chunks for subsequent sequences From 5c8c1a89e35596c41928e3f97c8c9cd593109577 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 10 Jun 2024 11:35:31 -0700 Subject: [PATCH 30/44] correctly apply procedure base voffs in inline line info parsing --- src/rdi_from_pdb/rdi_from_pdb.c | 18 ++++++++++++++++-- src/rdi_from_pdb/rdi_from_pdb.h | 1 + 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index 15be8d47..84e6c748 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -699,6 +699,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) CV_C13Parsed *unit_c13 = in->comp_unit_c13s[comp_unit_idx]; CV_RecRange *rec_ranges_first = unit_sym->sym_ranges.ranges; CV_RecRange *rec_ranges_opl = rec_ranges_first+unit_sym->sym_ranges.count; + U64 base_voff = 0; for(CV_RecRange *rec_range = rec_ranges_first; rec_range < rec_ranges_opl; rec_range += 1) @@ -729,12 +730,25 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) switch(kind) { default:{}break; + + //- rjf: LPROC32/GPROC32 (gather base address) + case CV_SymKind_LPROC32: + case CV_SymKind_GPROC32: + { + CV_SymProc32 *proc32 = (CV_SymProc32 *)sym_header_struct_base; + COFF_SectionHeader *section = (0 < proc32->sec && proc32->sec <= in->coff_sections->count) ? &in->coff_sections->sections[proc32->sec-1] : 0; + if(section != 0) + { + base_voff = section->voff + proc32->off; + } + }break; + + //- rjf: INLINESITE case CV_SymKind_INLINESITE: { // rjf: unpack sym CV_SymInlineSite *sym = (CV_SymInlineSite *)sym_header_struct_base; String8 binary_annots = str8((U8 *)(sym+1), rec_range->hdr.size - sizeof(rec_range->hdr.kind) - sizeof(*sym)); - U64 base_voff = 0; // rjf: map inlinee -> parsed cv c13 inlinee line info CV_C13InlineeLinesParsed *inlinee_lines_parsed = 0; @@ -3230,7 +3244,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) ////////////////////////////////////////////////////////////// //- rjf: kick off unit conversion & source file collection // - P2R_UnitConvertIn unit_convert_in = {strtbl, comp_units, comp_unit_contributions, sym_for_unit, c13_for_unit}; + P2R_UnitConvertIn unit_convert_in = {strtbl, coff_sections, comp_units, comp_unit_contributions, sym_for_unit, c13_for_unit}; TS_Ticket unit_convert_ticket = ts_kickoff(p2r_units_convert_task__entry_point, 0, &unit_convert_in); ////////////////////////////////////////////////////////////// diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index d4285ca8..c2038f2c 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -191,6 +191,7 @@ typedef struct P2R_UnitConvertIn P2R_UnitConvertIn; struct P2R_UnitConvertIn { PDB_Strtbl *pdb_strtbl; + PDB_CoffSectionArray *coff_sections; PDB_CompUnitArray *comp_units; PDB_CompUnitContributionArray *comp_unit_contributions; CV_SymParsed **comp_unit_syms; From c61f820aef7e90f76c285ad04d2c82cfff68a846 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 10 Jun 2024 12:34:22 -0700 Subject: [PATCH 31/44] extend rdi line info lookups with depth; fix bad panel deref in target view cmds --- build.bat | 2 +- project.4coder | 2 +- src/dasm_cache/dasm_cache.c | 2 +- src/df/core/df_core.c | 6 +-- src/df/gfx/df_views.c | 5 ++- src/lib_rdi_format/rdi_format_parse.c | 38 ++++++++++++++++--- src/lib_rdi_format/rdi_format_parse.h | 6 +-- src/mule/mule_main.cpp | 30 +++++++++++++++ .../rdi_breakpad_from_pdb_main.c | 2 +- 9 files changed, 75 insertions(+), 18 deletions(-) diff --git a/build.bat b/build.bat index 9249f121..75d519e8 100644 --- a/build.bat +++ b/build.bat @@ -43,7 +43,7 @@ if "%asan%"=="1" set auto_compile_flags=%auto_compile_flags% -fsanitize=add :: --- Compile/Link Line Definitions ------------------------------------------ set cl_common= /I..\src\ /I..\local\ /nologo /FC /Z7 set clang_common= -I..\src\ -I..\local\ -gcodeview -fdiagnostics-absolute-paths -Wall -Wno-unknown-warning-option -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf -set cl_debug= call cl /Od /DBUILD_DEBUG=1 %cl_common% %auto_compile_flags% +set cl_debug= call cl /Od /Ob1 /DBUILD_DEBUG=1 %cl_common% %auto_compile_flags% set cl_release= call cl /O2 /DBUILD_DEBUG=0 %cl_common% %auto_compile_flags% set clang_debug= call clang -g -O0 -DBUILD_DEBUG=1 %clang_common% %auto_compile_flags% set clang_release= call clang -g -O2 -DBUILD_DEBUG=0 %clang_common% %auto_compile_flags% diff --git a/project.4coder b/project.4coder index 7a6b0ae3..460ed992 100644 --- a/project.4coder +++ b/project.4coder @@ -47,7 +47,7 @@ commands = { .rjf_f1 = { - .win = "build ryan_scratch no_meta && pushd build && ryan_scratch.exe && popd", + .win = "build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, diff --git a/src/dasm_cache/dasm_cache.c b/src/dasm_cache/dasm_cache.c index 2b255e6a..e3ebddaa 100644 --- a/src/dasm_cache/dasm_cache.c +++ b/src/dasm_cache/dasm_cache.c @@ -460,7 +460,7 @@ dasm_parse_thread__entry_point(void *p) RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); RDI_ParsedLineTable unit_line_info = {0}; rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); - U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff); + U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff, 0); if(line_info_idx < unit_line_info.count) { RDI_Line *line = &unit_line_info.lines[line_info_idx]; diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index cf59414c..a2221427 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -3278,7 +3278,7 @@ df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entit RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); RDI_ParsedLineTable unit_line_info = {0}; rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); - U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff); + U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff, 0); if(unit_line_info.voffs != 0) { Rng1U64 range = r1u64(base_voff, unit_line_info.voffs[line_info_idx+1]); @@ -3322,7 +3322,7 @@ df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff) RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); RDI_ParsedLineTable unit_line_info = {0}; rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); - U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff); + U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff, 0); if(line_info_idx < unit_line_info.count) { RDI_Line *line = &unit_line_info.lines[line_info_idx]; @@ -3957,7 +3957,7 @@ df_eval_parse_ctx_from_src_loc(DI_Scope *scope, DF_Entity *file, TxtPt pt) RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); RDI_ParsedLineTable unit_line_info = {0}; rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); - U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff); + U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff, 0); Rng1U64 range = r1u64(base_voff, unit_line_info.voffs[line_info_idx+1]); S64 actual_line = (S64)unit_line_info.lines[line_info_idx].line_num; DF_TextLineSrc2DasmInfoNode *src2dasm_n = push_array(scratch.arena, DF_TextLineSrc2DasmInfoNode, 1); diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index c8870701..6a4c259d 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -3467,8 +3467,9 @@ DF_VIEW_CMD_FUNCTION_DEF(Target) { DF_Cmd *cmd = &n->cmd; - // rjf: mismatched view => skip - if(df_panel_from_handle(cmd->params.panel) != panel) + // rjf: mismatched window/panel => skip + if(df_window_from_handle(cmd->params.window) != ws || + df_panel_from_handle(cmd->params.panel) != panel) { continue; } diff --git a/src/lib_rdi_format/rdi_format_parse.c b/src/lib_rdi_format/rdi_format_parse.c index 87ccf1bc..85af6af7 100644 --- a/src/lib_rdi_format/rdi_format_parse.c +++ b/src/lib_rdi_format/rdi_format_parse.c @@ -231,13 +231,13 @@ rdi_parsed_from_line_table(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_Parse } RDI_PROC RDI_U64 -rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff) +rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff, RDI_U64 depth) { RDI_U64 result = 0; if(line_info->count > 0 && line_info->voffs[0] <= voff && voff < line_info->voffs[line_info->count - 1]) { + //- rjf: find i such that: (vmap[i].voff <= voff) && (voff < vmap[i + 1].voff) // assuming: (i < j) -> (vmap[i].voff < vmap[j].voff) - // find i such that: (vmap[i].voff <= voff) && (voff < vmap[i + 1].voff) RDI_U32 first = 0; RDI_U32 opl = line_info->count; for(;;) @@ -262,6 +262,32 @@ rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff) } } result = (RDI_U64)first; + + //- rjf: scan leftward, to find shallowest line info matching this voff + for(;result != 0;) + { + if(line_info->voffs[result-1] == voff) + { + result -= 1; + } + else + { + break; + } + } + + //- rjf: scan rightward, to match depth parameter + for(U64 idx = 0; idx < depth && result+1 < line_info->count; idx += 1) + { + if(line_info->voffs[result+1] == voff) + { + result += 1; + } + else + { + break; + } + } } return result; } @@ -615,20 +641,20 @@ rdi_line_table_from_unit(RDI_Parsed *rdi, RDI_Unit *unit) //- line info RDI_PROC RDI_Line -rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff) +rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff, RDI_U64 depth) { RDI_Unit *unit = rdi_unit_from_voff(rdi, voff); RDI_LineTable *line_table = rdi_line_table_from_unit(rdi, unit); - RDI_Line line = rdi_line_from_line_table_voff(rdi, line_table, voff); + RDI_Line line = rdi_line_from_line_table_voff(rdi, line_table, voff, depth); return line; } RDI_PROC RDI_Line -rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff) +rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff, RDI_U64 depth) { RDI_ParsedLineTable parsed = {0}; rdi_parsed_from_line_table(rdi, line_table, &parsed); - RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed, voff); + RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed, voff, depth); RDI_Line result = {0}; if(line_info_idx < parsed.count) { diff --git a/src/lib_rdi_format/rdi_format_parse.h b/src/lib_rdi_format/rdi_format_parse.h index 1e0c097a..82ccdbe7 100644 --- a/src/lib_rdi_format/rdi_format_parse.h +++ b/src/lib_rdi_format/rdi_format_parse.h @@ -159,7 +159,7 @@ RDI_PROC RDI_U32 *rdi_idx_run_from_first_count(RDI_Parsed *rdi, RDI_U32 raw_firs //- line info RDI_PROC void rdi_parsed_from_line_table(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_ParsedLineTable *out); -RDI_PROC RDI_U64 rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff); +RDI_PROC RDI_U64 rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff, RDI_U64 depth); RDI_PROC void rdi_parsed_from_source_line_map(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_ParsedSourceLineMap *out); RDI_PROC RDI_U64 *rdi_line_voffs_from_num(RDI_ParsedSourceLineMap *map, RDI_U32 linenum, RDI_U32 *n_out); @@ -195,8 +195,8 @@ RDI_PROC RDI_Unit *rdi_unit_from_voff(RDI_Parsed *rdi, RDI_U64 voff); RDI_PROC RDI_LineTable *rdi_line_table_from_unit(RDI_Parsed *rdi, RDI_Unit *unit); //- line tables -RDI_PROC RDI_Line rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff); -RDI_PROC RDI_Line rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff); +RDI_PROC RDI_Line rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff, RDI_U64 depth); +RDI_PROC RDI_Line rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff, RDI_U64 depth); RDI_PROC RDI_SourceFile *rdi_source_file_from_line(RDI_Parsed *rdi, RDI_Line *line); //- source files diff --git a/src/mule/mule_main.cpp b/src/mule/mule_main.cpp index a9647a31..b1a93972 100644 --- a/src/mule/mule_main.cpp +++ b/src/mule/mule_main.cpp @@ -1514,6 +1514,34 @@ extern "C"{ #include "mule_c.h" } +//////////////////////////////// +//~ rjf: Basic Inline Line Info Tests + +#if defined(_MSC_VER) +# define FORCE_INLINE __forceinline +#elif defined(__clang__) +# define FORCE_INLINE __attribute__((always_inline)) +#else +# error need force inline for this compiler +#endif + +static FORCE_INLINE void +basic_inlinee(void) +{ + OutputDebugStringA("A\n"); + OutputDebugStringA("B\n"); + OutputDebugStringA("C\n"); + OutputDebugStringA("D\n"); +} + +static void +basic_inline_tests(void) +{ + OutputDebugStringA("{\n"); + basic_inlinee(); + OutputDebugStringA("}\n"); +} + //////////////////////////////// //~ rjf: Fancy Visualization Eval Tests @@ -2595,6 +2623,8 @@ mule_main(int argc, char** argv){ alloca_stepping_tests(); + basic_inline_tests(); + inline_stepping_tests(); overloaded_line_stepping_tests(); diff --git a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c index 9a32b06e..b1cdede4 100644 --- a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c +++ b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c @@ -137,7 +137,7 @@ internal TS_TASK_FUNCTION_DEF(p2b_dump_proc_chunk_task__entry_point) for(U64 voff = voff_range.min, last_voff = 0; voff < voff_range.max && voff > last_voff;) { - RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&line_info, voff); + RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&line_info, voff, 0); if(line_info_idx < line_info.count) { RDI_Line *line = &line_info.lines[line_info_idx]; From c18c02a37e0226a9d2ba9c4b8627dd2332909258 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 10 Jun 2024 13:23:32 -0700 Subject: [PATCH 32/44] fix cases where decorative disasm lines were being confused with non-decorative --- src/dasm_cache/dasm_cache.c | 27 ++++++++++++++++++--------- src/dasm_cache/dasm_cache.h | 9 ++++++++- src/df/gfx/df_gfx.c | 3 ++- src/mule/mule_main.cpp | 4 ++-- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/dasm_cache/dasm_cache.c b/src/dasm_cache/dasm_cache.c index e3ebddaa..85963a80 100644 --- a/src/dasm_cache/dasm_cache.c +++ b/src/dasm_cache/dasm_cache.c @@ -73,7 +73,10 @@ dasm_inst_array_idx_from_code_off__linear_scan(DASM_InstArray *array, U64 off) if(array->v[idx].code_off <= off && off < next_off) { result = idx; - break; + if(!(array->v[idx].flags & DASM_InstFlag_Decorative)) + { + break; + } } } return result; @@ -472,15 +475,19 @@ dasm_parse_thread__entry_point(void *p) if(params.style_flags & DASM_StyleFlag_SourceFilesNames && file->normal_full_path_string_idx != 0 && file_normalized_full_path.size != 0) { - DASM_Inst inst = {0}; + String8 inst_string = push_str8f(scratch.arena, "> %S", file_normalized_full_path); + DASM_Inst inst = {u32_from_u64_saturate(off), DASM_InstFlag_Decorative, 0, r1u64(inst_strings.total_size + inst_strings.node_count, + inst_strings.total_size + inst_strings.node_count + inst_string.size)}; dasm_inst_chunk_list_push(scratch.arena, &inst_list, 1024, &inst); - str8_list_pushf(scratch.arena, &inst_strings, "> %S", file_normalized_full_path); + str8_list_push(scratch.arena, &inst_strings, inst_string); } if(params.style_flags & DASM_StyleFlag_SourceFilesNames && file->normal_full_path_string_idx == 0) { - DASM_Inst inst = {0}; + String8 inst_string = str8_lit(">"); + DASM_Inst inst = {u32_from_u64_saturate(off), DASM_InstFlag_Decorative, 0, r1u64(inst_strings.total_size + inst_strings.node_count, + inst_strings.total_size + inst_strings.node_count + inst_string.size)}; dasm_inst_chunk_list_push(scratch.arena, &inst_list, 1024, &inst); - str8_list_pushf(scratch.arena, &inst_strings, ">"); + str8_list_push(scratch.arena, &inst_strings, inst_string); } last_file = file; } @@ -512,9 +519,11 @@ dasm_parse_thread__entry_point(void *p) String8 line_text = str8_skip_chop_whitespace(str8_substr(data, text_info.lines_ranges[line->line_num-1])); if(line_text.size != 0) { - DASM_Inst inst = {0}; + String8 inst_string = push_str8f(scratch.arena, "> %S", line_text); + DASM_Inst inst = {u32_from_u64_saturate(off), DASM_InstFlag_Decorative, 0, r1u64(inst_strings.total_size + inst_strings.node_count, + inst_strings.total_size + inst_strings.node_count + inst_string.size)}; dasm_inst_chunk_list_push(scratch.arena, &inst_list, 1024, &inst); - str8_list_pushf(scratch.arena, &inst_strings, "> %S", line_text); + str8_list_push(scratch.arena, &inst_strings, inst_string); } } } @@ -567,8 +576,8 @@ dasm_parse_thread__entry_point(void *p) } } String8 inst_string = push_str8f(scratch.arena, "%S%S%s%S", addr_part, code_bytes_part, udc.asm_buf, symbol_part); - DASM_Inst inst = {off, rel_voff, r1u64(inst_strings.total_size + inst_strings.node_count, - inst_strings.total_size + inst_strings.node_count + inst_string.size)}; + DASM_Inst inst = {u32_from_u64_saturate(off), 0, rel_voff, r1u64(inst_strings.total_size + inst_strings.node_count, + inst_strings.total_size + inst_strings.node_count + inst_string.size)}; dasm_inst_chunk_list_push(scratch.arena, &inst_list, 1024, &inst); str8_list_push(scratch.arena, &inst_strings, inst_string); diff --git a/src/dasm_cache/dasm_cache.h b/src/dasm_cache/dasm_cache.h index 5c588b56..bb3e33e8 100644 --- a/src/dasm_cache/dasm_cache.h +++ b/src/dasm_cache/dasm_cache.h @@ -42,10 +42,17 @@ struct DASM_Params //////////////////////////////// //~ rjf: Instruction Types +typedef U32 DASM_InstFlags; +enum +{ + DASM_InstFlag_Decorative = (1<<0), +}; + typedef struct DASM_Inst DASM_Inst; struct DASM_Inst { - U64 code_off; + U32 code_off; + DASM_InstFlags flags; U64 addr; Rng1U64 text_range; }; diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index 99931256..cf7f9ebe 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -12034,7 +12034,8 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ { for(DF_TextLineDasm2SrcInfoNode *n = dasm2src_list->first; n != 0; n = n->next) { - if(n->v.voff_range.min <= hovered_line_voff && hovered_line_voff < n->v.voff_range.max) + if(n->v.voff_range.min <= hovered_line_voff && + hovered_line_voff < n->v.voff_range.max) { line_info_line_num = n->v.pt.line; matches = 1; diff --git a/src/mule/mule_main.cpp b/src/mule/mule_main.cpp index b1a93972..7ea90255 100644 --- a/src/mule/mule_main.cpp +++ b/src/mule/mule_main.cpp @@ -1526,7 +1526,7 @@ extern "C"{ #endif static FORCE_INLINE void -basic_inlinee(void) +basic_inlinee(int inlinee_param_x, int inlinee_param_y, int inlinee_param_z) { OutputDebugStringA("A\n"); OutputDebugStringA("B\n"); @@ -1538,7 +1538,7 @@ static void basic_inline_tests(void) { OutputDebugStringA("{\n"); - basic_inlinee(); + basic_inlinee(12, 34, 56); OutputDebugStringA("}\n"); } From a009473557f81ef32725456ec65a1454c52dd979 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 10 Jun 2024 13:28:08 -0700 Subject: [PATCH 33/44] adjust line info lookup apis to be range-based, with a first-and-shallowest-only helper --- src/dasm_cache/dasm_cache.c | 2 +- src/df/core/df_core.c | 6 +++--- src/lib_rdi_format/rdi_format_parse.c | 31 +++++++++++++++++++-------- src/lib_rdi_format/rdi_format_parse.h | 7 +++--- 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/dasm_cache/dasm_cache.c b/src/dasm_cache/dasm_cache.c index 85963a80..ae248831 100644 --- a/src/dasm_cache/dasm_cache.c +++ b/src/dasm_cache/dasm_cache.c @@ -463,7 +463,7 @@ dasm_parse_thread__entry_point(void *p) RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); RDI_ParsedLineTable unit_line_info = {0}; rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); - U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff, 0); + U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff); if(line_info_idx < unit_line_info.count) { RDI_Line *line = &unit_line_info.lines[line_info_idx]; diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index a2221427..cf59414c 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -3278,7 +3278,7 @@ df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entit RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); RDI_ParsedLineTable unit_line_info = {0}; rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); - U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff, 0); + U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff); if(unit_line_info.voffs != 0) { Rng1U64 range = r1u64(base_voff, unit_line_info.voffs[line_info_idx+1]); @@ -3322,7 +3322,7 @@ df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff) RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); RDI_ParsedLineTable unit_line_info = {0}; rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); - U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff, 0); + U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff); if(line_info_idx < unit_line_info.count) { RDI_Line *line = &unit_line_info.lines[line_info_idx]; @@ -3957,7 +3957,7 @@ df_eval_parse_ctx_from_src_loc(DI_Scope *scope, DF_Entity *file, TxtPt pt) RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); RDI_ParsedLineTable unit_line_info = {0}; rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); - U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff, 0); + U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff); Rng1U64 range = r1u64(base_voff, unit_line_info.voffs[line_info_idx+1]); S64 actual_line = (S64)unit_line_info.lines[line_info_idx].line_num; DF_TextLineSrc2DasmInfoNode *src2dasm_n = push_array(scratch.arena, DF_TextLineSrc2DasmInfoNode, 1); diff --git a/src/lib_rdi_format/rdi_format_parse.c b/src/lib_rdi_format/rdi_format_parse.c index 85af6af7..e89df1e9 100644 --- a/src/lib_rdi_format/rdi_format_parse.c +++ b/src/lib_rdi_format/rdi_format_parse.c @@ -231,9 +231,10 @@ rdi_parsed_from_line_table(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_Parse } RDI_PROC RDI_U64 -rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff, RDI_U64 depth) +rdi_line_info_idx_range_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff, RDI_U64 *n_out) { RDI_U64 result = 0; + RDI_U64 n = 0; if(line_info->count > 0 && line_info->voffs[0] <= voff && voff < line_info->voffs[line_info->count - 1]) { //- rjf: find i such that: (vmap[i].voff <= voff) && (voff < vmap[i + 1].voff) @@ -276,12 +277,12 @@ rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff, RDI_U6 } } - //- rjf: scan rightward, to match depth parameter - for(U64 idx = 0; idx < depth && result+1 < line_info->count; idx += 1) + //- rjf: scan rightward, to count # of line info with this voff + for(U64 idx = result; idx < line_info->count; idx += 1) { - if(line_info->voffs[result+1] == voff) + if(line_info->voffs[idx] == voff) { - result += 1; + n += 1; } else { @@ -289,6 +290,18 @@ rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff, RDI_U6 } } } + if(n_out) + { + *n_out = n; + } + return result; +} + +RDI_PROC RDI_U64 +rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff) +{ + RDI_U64 count = 0; + RDI_U64 result = rdi_line_info_idx_range_from_voff(line_info, voff, &count); return result; } @@ -641,20 +654,20 @@ rdi_line_table_from_unit(RDI_Parsed *rdi, RDI_Unit *unit) //- line info RDI_PROC RDI_Line -rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff, RDI_U64 depth) +rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff) { RDI_Unit *unit = rdi_unit_from_voff(rdi, voff); RDI_LineTable *line_table = rdi_line_table_from_unit(rdi, unit); - RDI_Line line = rdi_line_from_line_table_voff(rdi, line_table, voff, depth); + RDI_Line line = rdi_line_from_line_table_voff(rdi, line_table, voff); return line; } RDI_PROC RDI_Line -rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff, RDI_U64 depth) +rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff) { RDI_ParsedLineTable parsed = {0}; rdi_parsed_from_line_table(rdi, line_table, &parsed); - RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed, voff, depth); + RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed, voff); RDI_Line result = {0}; if(line_info_idx < parsed.count) { diff --git a/src/lib_rdi_format/rdi_format_parse.h b/src/lib_rdi_format/rdi_format_parse.h index 82ccdbe7..66a20cdc 100644 --- a/src/lib_rdi_format/rdi_format_parse.h +++ b/src/lib_rdi_format/rdi_format_parse.h @@ -159,7 +159,8 @@ RDI_PROC RDI_U32 *rdi_idx_run_from_first_count(RDI_Parsed *rdi, RDI_U32 raw_firs //- line info RDI_PROC void rdi_parsed_from_line_table(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_ParsedLineTable *out); -RDI_PROC RDI_U64 rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff, RDI_U64 depth); +RDI_PROC RDI_U64 rdi_line_info_idx_range_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff, RDI_U64 *n_out); +RDI_PROC RDI_U64 rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff); RDI_PROC void rdi_parsed_from_source_line_map(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_ParsedSourceLineMap *out); RDI_PROC RDI_U64 *rdi_line_voffs_from_num(RDI_ParsedSourceLineMap *map, RDI_U32 linenum, RDI_U32 *n_out); @@ -195,8 +196,8 @@ RDI_PROC RDI_Unit *rdi_unit_from_voff(RDI_Parsed *rdi, RDI_U64 voff); RDI_PROC RDI_LineTable *rdi_line_table_from_unit(RDI_Parsed *rdi, RDI_Unit *unit); //- line tables -RDI_PROC RDI_Line rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff, RDI_U64 depth); -RDI_PROC RDI_Line rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff, RDI_U64 depth); +RDI_PROC RDI_Line rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff); +RDI_PROC RDI_Line rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff); RDI_PROC RDI_SourceFile *rdi_source_file_from_line(RDI_Parsed *rdi, RDI_Line *line); //- source files From 8a6837c55353869b3505869c5cc9c5fc1786c4cd Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 10 Jun 2024 13:33:32 -0700 Subject: [PATCH 34/44] fix disasm cmd/ui discrepancy --- src/df/gfx/df_views.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 6a4c259d..83653365 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -6621,10 +6621,10 @@ DF_VIEW_CMD_FUNCTION_DEF(Disassembly) // DF_Entity *process = df_entity_from_handle(dv->process); Architecture arch = df_architecture_from_entity(process); - U64 dasm_base_vaddr = AlignDownPow2(dv->base_vaddr, KB(64)); + U64 dasm_base_vaddr = AlignDownPow2(dv->base_vaddr, KB(16)); DF_Entity *dasm_module = df_module_from_process_vaddr(process, dasm_base_vaddr); DI_Key dasm_dbgi_key = df_dbgi_key_from_module(dasm_module); - Rng1U64 dasm_vaddr_range = r1u64(dasm_base_vaddr, dasm_base_vaddr+KB(64)); + Rng1U64 dasm_vaddr_range = r1u64(dasm_base_vaddr, dasm_base_vaddr+KB(16)); U128 dasm_key = ctrl_hash_store_key_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, dasm_vaddr_range, 0); U128 dasm_data_hash = {0}; DASM_Params dasm_params = {0}; From dd5cc894838fea722eea51f24288e55a2d4a58dc Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 10 Jun 2024 14:36:00 -0700 Subject: [PATCH 35/44] parse inline site scope ranges in symbol conversion pass --- src/rdi_from_pdb/rdi_from_pdb.c | 99 +++++++++++++++++++++++++++++++++ src/rdi_from_pdb/rdi_from_pdb.h | 17 ------ 2 files changed, 99 insertions(+), 17 deletions(-) diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index 84e6c748..ef11dfda 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -2229,6 +2229,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) RDIM_LocationSet *defrange_target = 0; B32 defrange_target_is_param = 0; U64 procedure_num = 0; + U64 procedure_base_voff = 0; CV_RecRange *rec_ranges_first = in->sym->sym_ranges.ranges + in->sym_ranges_first; CV_RecRange *rec_ranges_opl = in->sym->sym_ranges.ranges + in->sym_ranges_opl; typedef struct P2R_ScopeNode P2R_ScopeNode; @@ -2420,6 +2421,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) U64 voff_last = voff_first + proc32->len; RDIM_Rng1U64 voff_range = {voff_first, voff_last}; rdim_scope_push_voff_range(arena, &sym_scopes, procedure_root_scope, voff_range); + procedure_base_voff = voff_first; } } @@ -2897,6 +2899,103 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) node->scope = scope; SLLStackPush(top_scope_node, node); } + + // rjf: parse offset ranges of this inline site - attach to scope + { + U32 code_length = 0; + U32 code_offset = 0; + U32 last_code_offset = code_offset; + U32 last_code_length = code_length; + U64 read_off = 0; + U64 read_off_opl = binary_annots.size; + for(B32 good = 1; read_off < read_off_opl && good;) + { + // rjf: decode next annotation op + U32 op = CV_InlineBinaryAnnotation_Null; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &op); + + // rjf: apply op + switch(op) + { + default:{good = 1;}break; + case CV_InlineBinaryAnnotation_Null: + { + good = 0; + }break; + case CV_InlineBinaryAnnotation_CodeOffset: + { + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_offset); + }break; + case CV_InlineBinaryAnnotation_ChangeCodeOffsetBase: + { + good = 0; + // TODO(rjf): currently untested/unknown - first guess below: + // + // U32 delta = 0; + // read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &delta); + // code_offset_base = code_offset; + // code_offset_end = code_offset + delta; + // code_offset += delta; + }break; + case CV_InlineBinaryAnnotation_ChangeCodeOffset: + { + U32 delta = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &delta); + code_offset += delta; + }break; + case CV_InlineBinaryAnnotation_ChangeCodeLength: + { + code_length = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_length); + }break; + case CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset: + { + U32 code_offset_and_line_offset = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_offset_and_line_offset); + U32 code_delta = (code_offset_and_line_offset & 0xf); + code_offset += code_delta; + }break; + case CV_InlineBinaryAnnotation_ChangeCodeLengthAndCodeOffset: + { + U32 offset_delta = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_length); + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &offset_delta); + code_offset += offset_delta; + }break; + } + + // rjf: gather new ranges + if(last_code_length != code_length) + { + // rjf: convert current state machine state to [first_voff, opl_voff) range + RDIM_Rng1U64 voff_range = + { + procedure_base_voff + code_offset, + procedure_base_voff + code_offset + code_length, + }; + + // rjf: attempt to extend last-added range to cover this range, if possible + if(scope->voff_ranges.last != 0 && scope->voff_ranges.last->v.max == voff_range.min) + { + scope->voff_ranges.last->v.max = voff_range.max; + } + + // rjf: cannot add to previous range? -> build new range & add to scope + else + { + rdim_scope_push_voff_range(arena, &sym_scopes, scope, voff_range); + } + + // rjf: advance + code_offset += code_length; + code_length = 0; + } + + // rjf: update prev/current states + last_code_offset = code_offset; + last_code_length = code_length; + } + } }break; //- rjf: INLINESITE_END diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index c2038f2c..fcf73c03 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -152,23 +152,6 @@ struct P2R_LinkNameMap U64 link_name_count; }; -//- rjf: inlinee line table map (item id -> line table) - -typedef struct P2R_InlineeLineTableMapNode P2R_InlineeLineTableMapNode; -struct P2R_InlineeLineTableMapNode -{ - P2R_InlineeLineTableMapNode *next; - CV_ItemId id; - RDIM_LineTable *line_table; -}; - -typedef struct P2R_InlineeLineTableMap P2R_InlineeLineTableMap; -struct P2R_InlineeLineTableMap -{ - P2R_InlineeLineTableMapNode **slots; - U64 slots_count; -}; - //- rjf: normalized file path -> source file map typedef struct P2R_SrcFileNode P2R_SrcFileNode; From 649932cce0eff8f7638fcd54a72c9d5ce88d0d3d Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 10 Jun 2024 15:06:25 -0700 Subject: [PATCH 36/44] look up into inline site info in call stack view; display both concrete & inline frames --- src/df/gfx/df_views.c | 105 +++++++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 23 deletions(-) diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 83653365..971c999a 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -4842,6 +4842,7 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) DI_Scope *scope = di_scope_open(); DF_CtrlCtx ctrl_ctx = df_ctrl_ctx_from_view(ws, view); DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread); + Architecture arch = df_architecture_from_entity(thread); U64 selected_unwind_count = ctrl_ctx.unwind_count; DF_Entity *process = thread->parent; Vec4F32 thread_color = df_rgba_from_theme_color(DF_ThemeColor_PlainText); @@ -4851,6 +4852,73 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) } CTRL_Unwind unwind = df_query_cached_unwind_from_thread(thread); + //- rjf: compute full call stack, including concrete & inline frames + typedef struct DF_CallStackFrame DF_CallStackFrame; + struct DF_CallStackFrame + { + void *regs; + B32 is_inline_frame; + String8 name; + String8 type_string; + }; + typedef struct DF_CallStackFrameNode DF_CallStackFrameNode; + struct DF_CallStackFrameNode + { + DF_CallStackFrameNode *next; + DF_CallStackFrame v; + }; + DF_CallStackFrame *frames = 0; + U64 frames_count = 0; + { + TG_Graph *graph = tg_graph_begin(bit_size_from_arch(arch)/8, 256); + DF_CallStackFrameNode *first_frame = 0; + DF_CallStackFrameNode *last_frame = 0; + for(U64 unwind_idx = 0; unwind_idx < unwind.frames.count; unwind_idx += 1) + { + CTRL_UnwindFrame *unwind_f = &unwind.frames.v[unwind_idx]; + U64 rip_vaddr = regs_rip_from_arch_block(arch, unwind_f->regs); + DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); + U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr); + DI_Key dbgi_key = df_dbgi_key_from_module(module); + RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); + RDI_Scope *scope = rdi_scope_from_voff(rdi, rip_voff); + RDI_Procedure *procedure = rdi_procedure_from_scope(rdi, scope); + RDI_TypeNode *procedure_type = rdi_element_from_name_idx(rdi, TypeNodes, procedure->type_idx); + + // rjf: add frame for inlines + for(RDI_Scope *s = scope; s->inline_site_idx != 0; s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx)) + { + RDI_InlineSite *site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx); + RDI_TypeNode *site_type = rdi_element_from_name_idx(rdi, TypeNodes, site->type_idx); + DF_CallStackFrameNode *n = push_array(scratch.arena, DF_CallStackFrameNode, 1); + SLLQueuePush(first_frame, last_frame, n); + n->v.regs = unwind_f->regs; + n->v.is_inline_frame = 1; + n->v.name.str = rdi_string_from_idx(rdi, site->name_string_idx, &n->v.name.size); + n->v.type_string = tg_string_from_key(scratch.arena, graph, rdi, tg_key_ext(tg_kind_from_rdi_type_kind(site_type->kind), (U64)site->type_idx)); + frames_count += 1; + } + + // rjf: add frame for concrete frame + DF_CallStackFrameNode *n = push_array(scratch.arena, DF_CallStackFrameNode, 1); + SLLQueuePush(first_frame, last_frame, n); + n->v.regs = unwind_f->regs; + n->v.is_inline_frame = 0; + n->v.name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &n->v.name.size); + n->v.type_string = tg_string_from_key(scratch.arena, graph, rdi, tg_key_ext(tg_kind_from_rdi_type_kind(procedure_type->kind), (U64)procedure->type_idx)); + frames_count += 1; + } + frames = push_array(scratch.arena, DF_CallStackFrame, frames_count); + { + U64 idx = 0; + for(DF_CallStackFrameNode *f = first_frame; f != 0; f = f->next) + { + MemoryCopyStruct(&frames[idx], &f->v); + idx += 1; + } + } + } + //- rjf: grab state typedef struct DF_CallStackViewState DF_CallStackViewState; struct DF_CallStackViewState @@ -4880,8 +4948,8 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) scroll_list_params.flags = UI_ScrollListFlag_All; scroll_list_params.row_height_px = floor_f32(ui_top_font_size()*2.5f); scroll_list_params.dim_px = dim_2f32(rect); - scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(3, unwind.frames.count)); - scroll_list_params.item_range = r1s64(0, unwind.frames.count+1); + scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(3, frames_count)); + scroll_list_params.item_range = r1s64(0, frames_count+1); scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1; } UI_ScrollListSignal scroll_list_sig = {0}; @@ -4914,7 +4982,7 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) } //- rjf: frame rows - for(S64 row_num = visible_row_range.min; row_num <= visible_row_range.max && row_num <= unwind.frames.count; row_num += 1) + for(S64 row_num = visible_row_range.min; row_num <= visible_row_range.max && row_num <= frames_count; row_num += 1) { if(row_num == 0) { @@ -4924,29 +4992,12 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) // rjf: unpack frame U64 frame_idx = row_num-1; - CTRL_UnwindFrame *frame = &unwind.frames.v[frame_idx]; + DF_CallStackFrame *frame = &frames[frame_idx]; U64 rip_vaddr = regs_rip_from_arch_block(thread->arch, frame->regs); DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); B32 frame_valid = (rip_vaddr != 0); - U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr); - DI_Key dbgi_key = df_dbgi_key_from_module(module); - RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); - String8 symbol_name = {0}; - String8 symbol_type_string = {0}; - { - U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, rip_voff); - RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); - U64 proc_idx = scope->proc_idx; - RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx); - RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, procedure->type_idx); - TG_Key type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), procedure->type_idx); - U64 name_size = 0; - U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); - RDI_TopLevelInfo *top_level_info = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); - TG_Graph *graph = tg_graph_begin(rdi_addr_size_from_arch(top_level_info->arch), 256); - symbol_name = str8(name_ptr, name_size); - symbol_type_string = tg_string_from_key(scratch.arena, graph, rdi, type_key); - } + String8 symbol_name = frame->name; + String8 symbol_type_string = frame->type_string; // rjf: build row if(frame_valid) UI_NamedTableVectorF("###callstack_%p_%I64x", view, frame_idx) @@ -5007,6 +5058,14 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable|UI_BoxFlag_Clip, "frame_%I64x", frame_idx); UI_Parent(box) { + if(frame->is_inline_frame) + { + UI_PrefWidth(ui_text_dim(10, 1)) + { + ui_set_next_text_color(df_rgba_from_theme_color(DF_ThemeColor_WeakText)); + ui_label(str8_lit("[inlined]")); + } + } if(symbol_name.size == 0) { ui_set_next_text_color(df_rgba_from_theme_color(DF_ThemeColor_WeakText)); From 6488e2d5e2a654aa9b634b02ddf32c3e9da10498 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 10 Jun 2024 15:26:02 -0700 Subject: [PATCH 37/44] oops! --- src/rdi_from_pdb/rdi_from_pdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index ef11dfda..e5815223 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -754,7 +754,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) CV_C13InlineeLinesParsed *inlinee_lines_parsed = 0; { U64 hash = cv_hash_from_item_id(sym->inlinee); - U64 slot_idx = unit_c13->inlinee_lines_parsed_slots_count; + U64 slot_idx = hash%unit_c13->inlinee_lines_parsed_slots_count; for(CV_C13InlineeLinesParsedNode *n = unit_c13->inlinee_lines_parsed_slots[slot_idx]; n != 0; n = n->hash_next) { if(n->v.inlinee == sym->inlinee) From af80e1bfc88099e479047f9f02f650c08cffbaaf Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 10 Jun 2024 15:42:50 -0700 Subject: [PATCH 38/44] fix missing line chunks in inline line table parsing --- src/rdi_from_pdb/rdi_from_pdb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index e5815223..a4cf1e79 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -920,7 +920,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) } // rjf: gather new lines - if(line != last_line || code_offset != last_code_offset) + if(!good || line != last_line || code_offset != last_code_offset) { LineChunk *chunk = last_line_chunk; if(chunk == 0 || chunk->count+1 >= chunk->cap) @@ -932,7 +932,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) chunk->line_nums = push_array_no_zero(scratch.arena, U32, chunk->cap); } chunk->voffs[chunk->count] = base_voff + code_offset; - chunk->voffs[chunk->count+1] = 0xffffffffffffffffull; + chunk->voffs[chunk->count+1] = base_voff + code_offset + code_length; chunk->line_nums[chunk->count] = (U32)line; chunk->count += 1; total_line_chunk_line_count += 1; From e25c3044b089c3eff7f980e9cf3bd2c39bb74ec7 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 10 Jun 2024 15:59:19 -0700 Subject: [PATCH 39/44] do not assume non-empty name map bakes --- src/rdi_from_pdb/rdi_from_pdb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index a4cf1e79..86a3f139 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -4766,7 +4766,11 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) { for(EachNonZeroEnumVal(RDI_NameMapKind, k)) { - name_map_bakes[k] = *ts_join_struct(bake_name_maps_tickets[k], max_U64, RDIM_NameMapBakeResult); + RDIM_NameMapBakeResult *bake = ts_join_struct(bake_name_maps_tickets[k], max_U64, RDIM_NameMapBakeResult); + if(bake != 0) + { + name_map_bakes[k] = *bake; + } } } From 97a96cfdd43592f69bf31103031348697f5239b3 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 13 Jun 2024 10:41:19 -0700 Subject: [PATCH 40/44] go back to per-inline-site line tables; eliminate call location for inline tables; these can be encoded via parent line tables; wire up parsed line tables to inline site production from symbol conversion phase --- project.4coder | 3 +- src/demon/demon_core.h | 2 +- src/lib_rdi_format/rdi_format.h | 6 --- src/lib_rdi_make/rdi_make.c | 3 -- src/lib_rdi_make/rdi_make.h | 3 -- src/rdi_dump/rdi_dump.c | 6 --- src/rdi_format/rdi_format.mdesk | 3 -- src/rdi_from_pdb/rdi_from_pdb.c | 83 ++++++++++++++++++++++++--------- src/rdi_from_pdb/rdi_from_pdb.h | 2 + 9 files changed, 65 insertions(+), 46 deletions(-) diff --git a/project.4coder b/project.4coder index 460ed992..5409cda1 100644 --- a/project.4coder +++ b/project.4coder @@ -47,7 +47,8 @@ commands = { .rjf_f1 = { - .win = "build raddbg telemetry", + .win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main.rdi && rdi_dump mule_main.rdi > mule_main.dump && popd", + // .win = "build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, diff --git a/src/demon/demon_core.h b/src/demon/demon_core.h index 48a2cb63..53d3ef99 100644 --- a/src/demon/demon_core.h +++ b/src/demon/demon_core.h @@ -15,7 +15,7 @@ typedef struct DMN_CtrlCtx DMN_CtrlCtx; struct DMN_CtrlCtx { - U64 u64 [1]; + U64 u64[1]; }; //////////////////////////////// diff --git a/src/lib_rdi_format/rdi_format.h b/src/lib_rdi_format/rdi_format.h index 9f065ba1..bded37a4 100644 --- a/src/lib_rdi_format/rdi_format.h +++ b/src/lib_rdi_format/rdi_format.h @@ -783,9 +783,6 @@ X(RDI_U32, inline_site_idx)\ #define RDI_InlineSite_XList \ X(RDI_U32, name_string_idx)\ -X(RDI_U32, call_src_file_idx)\ -X(RDI_U32, call_line_num)\ -X(RDI_U32, call_col_num)\ X(RDI_U32, type_idx)\ X(RDI_U32, owner_type_idx)\ X(RDI_U32, line_table_idx)\ @@ -1218,9 +1215,6 @@ typedef struct RDI_InlineSite RDI_InlineSite; struct RDI_InlineSite { RDI_U32 name_string_idx; -RDI_U32 call_src_file_idx; -RDI_U32 call_line_num; -RDI_U32 call_col_num; RDI_U32 type_idx; RDI_U32 owner_type_idx; RDI_U32 line_table_idx; diff --git a/src/lib_rdi_make/rdi_make.c b/src/lib_rdi_make/rdi_make.c index 5dd75247..c106943f 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -3435,9 +3435,6 @@ rdim_bake_inline_sites(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM RDI_InlineSite *dst = &result.inline_sites[dst_idx]; RDIM_InlineSite *src = &n->v[chunk_idx]; dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->call_src_file_idx = (RDI_U32)rdim_idx_from_src_file(src->call_src_file); // TODO(rjf): @u64_to_u32 - dst->call_line_num = src->call_line_num; - dst->call_col_num = src->call_col_num; dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 dst->owner_type_idx = (RDI_U32)rdim_idx_from_type(src->owner); // TODO(rjf): @u64_to_u32 dst->line_table_idx = (RDI_U32)rdim_idx_from_line_table(src->line_table); // TODO(rjf): @u64_to_u32 diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index bb70bf42..025e7b2f 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -773,9 +773,6 @@ struct RDIM_InlineSite { struct RDIM_InlineSiteChunkNode *chunk; RDIM_String8 name; - RDIM_SrcFile *call_src_file; - RDI_U32 call_line_num; - RDI_U32 call_col_num; RDIM_Type *type; RDIM_Type *owner; RDIM_LineTable *line_table; diff --git a/src/rdi_dump/rdi_dump.c b/src/rdi_dump/rdi_dump.c index 17c21cc8..59284b0e 100644 --- a/src/rdi_dump/rdi_dump.c +++ b/src/rdi_dump/rdi_dump.c @@ -778,13 +778,7 @@ rdi_stringize_inline_site(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_I { String8 name = {0}; name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size); - RDI_SourceFile *source_file = rdi_element_from_name_idx(rdi, SourceFiles, inline_site->call_src_file_idx); - String8 source_file_path = {0}; - source_file_path.str = rdi_normal_path_from_source_file(rdi, source_file, &source_file_path.size); str8_list_pushf(arena, out, "%.*sname='%S'\n", indent_level, rdi_stringize_spaces, name); - str8_list_pushf(arena, out, "%.*scall_src_file_idx=%u ('%S')\n", indent_level, rdi_stringize_spaces, inline_site->call_src_file_idx, source_file_path); - str8_list_pushf(arena, out, "%.*scall_line_num=%u\n", indent_level, rdi_stringize_spaces, inline_site->call_line_num); - str8_list_pushf(arena, out, "%.*scall_col_num=%u\n", indent_level, rdi_stringize_spaces, inline_site->call_col_num); str8_list_pushf(arena, out, "%.*stype_idx=%u\n", indent_level, rdi_stringize_spaces, inline_site->type_idx); str8_list_pushf(arena, out, "%.*sowner_type_idx=%u\n", indent_level, rdi_stringize_spaces, inline_site->owner_type_idx); str8_list_pushf(arena, out, "%.*sline_table_idx=%u\n", indent_level, rdi_stringize_spaces, inline_site->line_table_idx); diff --git a/src/rdi_format/rdi_format.mdesk b/src/rdi_format/rdi_format.mdesk index edc8e813..b6ff7d21 100644 --- a/src/rdi_format/rdi_format.mdesk +++ b/src/rdi_format/rdi_format.mdesk @@ -1016,9 +1016,6 @@ RDI_ScopeMemberTable: RDI_InlineSiteMemberTable: { {name_string_idx RDI_U32 ""} - {call_src_file_idx RDI_U32 ""} - {call_line_num RDI_U32 ""} - {call_col_num RDI_U32 ""} {type_idx RDI_U32 ""} {owner_type_idx RDI_U32 ""} {line_table_idx RDI_U32 ""} diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index 86a3f139..7393d59e 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -583,7 +583,6 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) //////////////////////////// //- rjf: pass 1: build per-unit info & per-unit line tables // - RDIM_LineTable **unit_line_tables = push_array(scratch.arena, RDIM_LineTable *, in->comp_units->count); ProfScope("pass 1: build per-unit info & per-unit line tables") for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) { @@ -611,8 +610,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) } //- rjf: build this unit's line table, fill out primary line info (inline info added after) - RDIM_LineTable *line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 256); - unit_line_tables[comp_unit_idx] = line_table; + RDIM_LineTable *line_table = 0; for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; node != 0; node = node->next) @@ -657,8 +655,15 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) } // rjf: push sequence into both line table & source file's line map - RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, lines->voffs, lines->line_nums, lines->col_nums, lines->line_count); - rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); + if(lines->line_count != 0) + { + if(line_table == 0) + { + line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 256); + } + RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, lines->voffs, lines->line_nums, lines->col_nums, lines->line_count); + rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); + } } } } @@ -692,6 +697,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) //////////////////////////// //- rjf: pass 3: parse all inlinee line tables // + out->units_first_inline_site_line_tables = push_array(arena, RDIM_LineTable *, in->comp_units->count); ProfScope("pass 3: parse all inlinee line tables") for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) { @@ -990,8 +996,19 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) } // rjf: push - RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, unit_line_tables[comp_unit_idx], src_file_node->src_file, voffs, line_nums, 0, line_count); - rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); + if(line_count != 0) + { + if(line_table == 0) + { + line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 256); + if(out->units_first_inline_site_line_tables[comp_unit_idx] == 0) + { + out->units_first_inline_site_line_tables[comp_unit_idx] = line_table; + } + } + RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, voffs, line_nums, 0, line_count); + rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); + } // rjf: clear line chunks for subsequent sequences first_line_chunk = last_line_chunk = 0; @@ -1005,11 +1022,6 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) last_code_offset = code_offset; } } - - // rjf: insert line table to map, for later lookups - { - // TODO(rjf) - } }break; } } @@ -2240,6 +2252,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) }; P2R_ScopeNode *top_scope_node = 0; P2R_ScopeNode *free_scope_node = 0; + RDIM_LineTable *inline_site_line_table = in->first_inline_site_line_table; for(CV_RecRange *rec_range = rec_ranges_first; rec_range < rec_ranges_opl; rec_range += 1) @@ -2872,9 +2885,30 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) // rjf: build inline site RDIM_InlineSite *inline_site = rdim_inline_site_chunk_list_push(arena, &sym_inline_sites, sym_inline_sites_chunk_cap); - inline_site->name = name; - inline_site->type = type; - inline_site->owner= owner; + inline_site->name = name; + inline_site->type = type; + inline_site->owner = owner; + inline_site->line_table = inline_site_line_table; + + // rjf: increment to next inline site line table in this unit + if(inline_site_line_table != 0 && inline_site_line_table->chunk != 0) + { + RDIM_LineTableChunkNode *chunk = inline_site_line_table->chunk; + U64 current_idx = (U64)(inline_site_line_table - chunk->v); + if(current_idx+1 < chunk->count) + { + inline_site_line_table += 1; + } + else + { + chunk = chunk->next; + inline_site_line_table = 0; + if(chunk != 0) + { + inline_site_line_table = chunk->v; + } + } + } // rjf: build scope RDIM_Scope *scope = rdim_scope_chunk_list_push(arena, &sym_scopes, sym_scopes_chunk_cap); @@ -3957,12 +3991,14 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) RDIM_UnitChunkList all_units = {0}; RDIM_SrcFileChunkList all_src_files = {0}; RDIM_LineTableChunkList all_line_tables = {0}; + RDIM_LineTable **units_first_inline_site_line_tables = 0; ProfScope("join unit conversion & src file tasks") { P2R_UnitConvertOut *out = ts_join_struct(unit_convert_ticket, max_U64, P2R_UnitConvertOut); all_units = out->units; all_src_files = out->src_files; all_line_tables = out->line_tables; + units_first_inline_site_line_tables = out->units_first_inline_site_line_tables; } ////////////////////////////////////////////////////////////// @@ -3987,14 +4023,14 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) { for(U64 idx = 0; idx < tasks_count; idx += 1) { - tasks_inputs[idx].arch = arch; - tasks_inputs[idx].coff_sections = coff_sections; - tasks_inputs[idx].tpi_hash = tpi_hash; - tasks_inputs[idx].tpi_leaf = tpi_leaf; - tasks_inputs[idx].ipi_leaf = ipi_leaf; - tasks_inputs[idx].itype_fwd_map = itype_fwd_map; - tasks_inputs[idx].itype_type_ptrs = itype_type_ptrs; - tasks_inputs[idx].link_name_map = link_name_map; + tasks_inputs[idx].arch = arch; + tasks_inputs[idx].coff_sections = coff_sections; + tasks_inputs[idx].tpi_hash = tpi_hash; + tasks_inputs[idx].tpi_leaf = tpi_leaf; + tasks_inputs[idx].ipi_leaf = ipi_leaf; + tasks_inputs[idx].itype_fwd_map = itype_fwd_map; + tasks_inputs[idx].itype_type_ptrs = itype_type_ptrs; + tasks_inputs[idx].link_name_map = link_name_map; if(idx < global_stream_subdivision_tasks_count) { tasks_inputs[idx].sym = sym; @@ -4007,6 +4043,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) tasks_inputs[idx].sym = sym_for_unit[idx-global_stream_subdivision_tasks_count]; tasks_inputs[idx].sym_ranges_first= 0; tasks_inputs[idx].sym_ranges_opl = sym_for_unit[idx-global_stream_subdivision_tasks_count]->sym_ranges.count; + tasks_inputs[idx].first_inline_site_line_table = units_first_inline_site_line_tables[idx-global_stream_subdivision_tasks_count]; } tasks_tickets[idx] = ts_kickoff(p2r_symbol_stream_convert_task__entry_point, 0, &tasks_inputs[idx]); } diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index fcf73c03..a0a78db5 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -187,6 +187,7 @@ struct P2R_UnitConvertOut RDIM_UnitChunkList units; RDIM_SrcFileChunkList src_files; RDIM_LineTableChunkList line_tables; + RDIM_LineTable **units_first_inline_site_line_tables; }; //- rjf: link name map building tasks @@ -258,6 +259,7 @@ struct P2R_SymbolStreamConvertIn CV_TypeId *itype_fwd_map; RDIM_Type **itype_type_ptrs; P2R_LinkNameMap *link_name_map; + RDIM_LineTable *first_inline_site_line_table; }; typedef struct P2R_SymbolStreamConvertOut P2R_SymbolStreamConvertOut; From 5a24649a3117a47f8ba39a5a511434e80a752705 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 13 Jun 2024 11:28:35 -0700 Subject: [PATCH 41/44] pull out 'rich unwind' gathering path, which takes a 'concrete unwind' and produces a full unwind with debug-info-derived inline frames --- project.4coder | 4 +- src/df/core/df_core.c | 60 ++++++++++++++++- src/df/core/df_core.h | 42 ++++++++++++ src/df/core/df_core.mdesk | 1 + src/df/core/generated/df_core.meta.c | 3 +- src/df/core/generated/df_core.meta.h | 1 + src/df/gfx/df_views.c | 99 +++++++--------------------- 7 files changed, 131 insertions(+), 79 deletions(-) diff --git a/project.4coder b/project.4coder index 5409cda1..d64a1538 100644 --- a/project.4coder +++ b/project.4coder @@ -47,8 +47,8 @@ commands = { .rjf_f1 = { - .win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main.rdi && rdi_dump mule_main.rdi > mule_main.dump && popd", - // .win = "build raddbg telemetry", + //.win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main.rdi && rdi_dump mule_main.rdi > mule_main.dump && popd", + .win = "build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index cf59414c..39912eb5 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -3654,6 +3654,58 @@ df_module_from_thread_candidates(DF_Entity *thread, DF_EntityList *candidates) return module; } +internal DF_Unwind +df_unwind_from_ctrl_unwind(Arena *arena, DI_Scope *di_scope, DF_Entity *process, CTRL_Unwind *base_unwind) +{ + Temp scratch = scratch_begin(&arena, 1); + DF_UnwindFrameList rich_frames_list = {0}; + Architecture arch = df_architecture_from_entity(process); + for(U64 base_frame_idx = 0; base_frame_idx < base_unwind->frames.count; base_frame_idx += 1) + { + CTRL_UnwindFrame *base_frame = &base_unwind->frames.v[base_frame_idx]; + U64 rip_vaddr = regs_rip_from_arch_block(arch, base_frame->regs); + DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); + U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr); + DI_Key dbgi_key = df_dbgi_key_from_module(module); + RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 0); + RDI_Scope *scope = rdi_scope_from_voff(rdi, rip_voff); + + // rjf: add rich frames for inlines + for(RDI_Scope *s = scope; s->inline_site_idx != 0; s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx)) + { + RDI_InlineSite *site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx); + DF_UnwindFrameNode *n = push_array(scratch.arena, DF_UnwindFrameNode, 1); + SLLQueuePush(rich_frames_list.first, rich_frames_list.last, n); + rich_frames_list.count += 1; + n->v.regs = base_frame->regs; + n->v.rdi = rdi; + n->v.procedure = 0; + n->v.inline_site = site; + } + + // rjf: add frame for concrete frame + DF_UnwindFrameNode *n = push_array(scratch.arena, DF_UnwindFrameNode, 1); + SLLQueuePush(rich_frames_list.first, rich_frames_list.last, n); + rich_frames_list.count += 1; + n->v.regs = base_frame->regs; + n->v.rdi = rdi; + n->v.procedure = rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx); + n->v.inline_site = 0; + } + DF_Unwind result = {0}; + { + result.frames.count = rich_frames_list.count; + result.frames.v = push_array(arena, DF_UnwindFrame, result.frames.count); + U64 idx = 0; + for(DF_UnwindFrameNode *n = rich_frames_list.first; n != 0; n = n->next, idx += 1) + { + MemoryCopyStruct(&result.frames.v[idx], &n->v); + } + } + scratch_end(scratch); + return result; +} + //////////////////////////////// //~ rjf: Entity -> Log Entities @@ -5652,6 +5704,7 @@ df_ctrl_ctx_apply_overrides(DF_CtrlCtx *ctx, DF_CtrlCtx *overrides) { ctx->thread = overrides->thread; ctx->unwind_count = overrides->unwind_count; + ctx->inline_unwind_count = overrides->inline_unwind_count; } } @@ -7565,8 +7618,8 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) //- rjf: debug control context management operations case DF_CoreCmdKind_SelectThread: { + MemoryZeroStruct(&df_state->ctrl_ctx); df_state->ctrl_ctx.thread = params.entity; - df_state->ctrl_ctx.unwind_count = 0; }break; case DF_CoreCmdKind_SelectUnwind: { @@ -7575,6 +7628,11 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) U64 max_unwind = unwind.frames.count ? unwind.frames.count-1 : 0; U64 index = Clamp(0, params.index, max_unwind); df_state->ctrl_ctx.unwind_count = index; + df_state->ctrl_ctx.inline_unwind_count = 0; + }break; + case DF_CoreCmdKind_SelectInlineUnwind: + { + }break; case DF_CoreCmdKind_UpOneFrame: { diff --git a/src/df/core/df_core.h b/src/df/core/df_core.h index a8a72850..824cfc38 100644 --- a/src/df/core/df_core.h +++ b/src/df/core/df_core.h @@ -77,6 +77,7 @@ struct DF_CtrlCtx { DF_Handle thread; U64 unwind_count; + U64 inline_unwind_count; }; //////////////////////////////// @@ -516,6 +517,46 @@ struct DF_EntityFuzzyItemArray U64 count; }; +//////////////////////////////// +//~ rjf: Rich (Including Inline) Unwind Types + +typedef struct DF_UnwindFrame DF_UnwindFrame; +struct DF_UnwindFrame +{ + void *regs; + RDI_Parsed *rdi; + RDI_Procedure *procedure; + RDI_InlineSite *inline_site; +}; + +typedef struct DF_UnwindFrameNode DF_UnwindFrameNode; +struct DF_UnwindFrameNode +{ + DF_UnwindFrameNode *next; + DF_UnwindFrame v; +}; + +typedef struct DF_UnwindFrameList DF_UnwindFrameList; +struct DF_UnwindFrameList +{ + DF_UnwindFrameNode *first; + DF_UnwindFrameNode *last; + U64 count; +}; + +typedef struct DF_UnwindFrameArray DF_UnwindFrameArray; +struct DF_UnwindFrameArray +{ + DF_UnwindFrame *v; + U64 count; +}; + +typedef struct DF_Unwind DF_Unwind; +struct DF_Unwind +{ + DF_UnwindFrameArray frames; +}; + //////////////////////////////// //~ rjf: Source <-> Disasm Types @@ -1562,6 +1603,7 @@ internal EVAL_String2NumMap *df_push_locals_map_from_dbgi_key_voff(Arena *arena, internal EVAL_String2NumMap *df_push_member_map_from_dbgi_key_voff(Arena *arena, DI_Scope *scope, DI_Key *dbgi_key, U64 voff); internal B32 df_set_thread_rip(DF_Entity *thread, U64 vaddr); internal DF_Entity *df_module_from_thread_candidates(DF_Entity *thread, DF_EntityList *candidates); +internal DF_Unwind df_unwind_from_ctrl_unwind(Arena *arena, DI_Scope *di_scope, DF_Entity *process, CTRL_Unwind *base_unwind); //////////////////////////////// //~ rjf: Entity -> Log Entities diff --git a/src/df/core/df_core.mdesk b/src/df/core/df_core.mdesk index 3297cce4..f4c5b70d 100644 --- a/src/df/core/df_core.mdesk +++ b/src/df/core/df_core.mdesk @@ -152,6 +152,7 @@ DF_CoreCmdTable:// | | | {SelectThreadWindow 0 Entity Thread 0 0 0 0 0 1 Null "select_thread_window" "Select Thread On Window" "Selects a thread for the active window, overriding the global selected thread." "" } {SelectThreadView 0 Entity Thread 0 0 0 0 0 1 Null "select_thread_view" "Select Thread On View" "Selects a thread for the active view, overriding the global and per-window selected threads." "" } {SelectUnwind 1 Null Nil 0 0 0 0 0 0 Null "select_unwind" "Select Unwind" "Selects an unwind frame number for the selected thread." "" } + {SelectInlineUnwind 1 Null Nil 0 0 0 0 0 0 Null "select_inline_unwind" "Select Inline Unwind" "Selects an inline unwind frame number for the selected thread." "" } {UpOneFrame 0 Null Nil 0 0 0 0 0 0 UpArrow "up_one_frame" "Up One Frame" "Selects the callstack frame above the currently selected." "" } {DownOneFrame 0 Null Nil 0 0 0 0 0 0 DownArrow "down_one_frame" "Down One Frame" "Selects the callstack frame below the currently selected." "" } {FreezeThread 0 Entity Thread 0 0 0 0 0 1 Locked "freeze_thread" "Freeze Thread" "Freezes the passed thread." "" } diff --git a/src/df/core/generated/df_core.meta.c b/src/df/core/generated/df_core.meta.c index 88fc1a8d..55634ee9 100644 --- a/src/df/core/generated/df_core.meta.c +++ b/src/df/core/generated/df_core.meta.c @@ -212,7 +212,7 @@ DF_CoreCmdKind_Null, DF_CoreCmdKind_Null, }; -DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[221] = +DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[222] = { { str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, { str8_lit_comp("exit"), str8_lit_comp("Exits the debugger."), str8_lit_comp("quit,close,abort"), str8_lit_comp("Exit"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_X}, @@ -247,6 +247,7 @@ DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[221] = { str8_lit_comp("select_thread_window"), str8_lit_comp("Selects a thread for the active window, overriding the global selected thread."), str8_lit_comp(""), str8_lit_comp("Select Thread On Window"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Thread, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Null}, { str8_lit_comp("select_thread_view"), str8_lit_comp("Selects a thread for the active view, overriding the global and per-window selected threads."), str8_lit_comp(""), str8_lit_comp("Select Thread On View"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Thread, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Null}, { str8_lit_comp("select_unwind"), str8_lit_comp("Selects an unwind frame number for the selected thread."), str8_lit_comp(""), str8_lit_comp("Select Unwind"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, +{ str8_lit_comp("select_inline_unwind"), str8_lit_comp("Selects an inline unwind frame number for the selected thread."), str8_lit_comp(""), str8_lit_comp("Select Inline Unwind"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, { str8_lit_comp("up_one_frame"), str8_lit_comp("Selects the callstack frame above the currently selected."), str8_lit_comp(""), str8_lit_comp("Up One Frame"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_UpArrow}, { str8_lit_comp("down_one_frame"), str8_lit_comp("Selects the callstack frame below the currently selected."), str8_lit_comp(""), str8_lit_comp("Down One Frame"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_DownArrow}, { str8_lit_comp("freeze_thread"), str8_lit_comp("Freezes the passed thread."), str8_lit_comp(""), str8_lit_comp("Freeze Thread"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Thread, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Locked}, diff --git a/src/df/core/generated/df_core.meta.h b/src/df/core/generated/df_core.meta.h index c840bb48..fe27d1a6 100644 --- a/src/df/core/generated/df_core.meta.h +++ b/src/df/core/generated/df_core.meta.h @@ -81,6 +81,7 @@ DF_CoreCmdKind_SelectThread, DF_CoreCmdKind_SelectThreadWindow, DF_CoreCmdKind_SelectThreadView, DF_CoreCmdKind_SelectUnwind, +DF_CoreCmdKind_SelectInlineUnwind, DF_CoreCmdKind_UpOneFrame, DF_CoreCmdKind_DownOneFrame, DF_CoreCmdKind_FreezeThread, diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 971c999a..9d65df49 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -4850,74 +4850,8 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) { thread_color = df_rgba_from_entity(thread); } - CTRL_Unwind unwind = df_query_cached_unwind_from_thread(thread); - - //- rjf: compute full call stack, including concrete & inline frames - typedef struct DF_CallStackFrame DF_CallStackFrame; - struct DF_CallStackFrame - { - void *regs; - B32 is_inline_frame; - String8 name; - String8 type_string; - }; - typedef struct DF_CallStackFrameNode DF_CallStackFrameNode; - struct DF_CallStackFrameNode - { - DF_CallStackFrameNode *next; - DF_CallStackFrame v; - }; - DF_CallStackFrame *frames = 0; - U64 frames_count = 0; - { - TG_Graph *graph = tg_graph_begin(bit_size_from_arch(arch)/8, 256); - DF_CallStackFrameNode *first_frame = 0; - DF_CallStackFrameNode *last_frame = 0; - for(U64 unwind_idx = 0; unwind_idx < unwind.frames.count; unwind_idx += 1) - { - CTRL_UnwindFrame *unwind_f = &unwind.frames.v[unwind_idx]; - U64 rip_vaddr = regs_rip_from_arch_block(arch, unwind_f->regs); - DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); - U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr); - DI_Key dbgi_key = df_dbgi_key_from_module(module); - RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); - RDI_Scope *scope = rdi_scope_from_voff(rdi, rip_voff); - RDI_Procedure *procedure = rdi_procedure_from_scope(rdi, scope); - RDI_TypeNode *procedure_type = rdi_element_from_name_idx(rdi, TypeNodes, procedure->type_idx); - - // rjf: add frame for inlines - for(RDI_Scope *s = scope; s->inline_site_idx != 0; s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx)) - { - RDI_InlineSite *site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx); - RDI_TypeNode *site_type = rdi_element_from_name_idx(rdi, TypeNodes, site->type_idx); - DF_CallStackFrameNode *n = push_array(scratch.arena, DF_CallStackFrameNode, 1); - SLLQueuePush(first_frame, last_frame, n); - n->v.regs = unwind_f->regs; - n->v.is_inline_frame = 1; - n->v.name.str = rdi_string_from_idx(rdi, site->name_string_idx, &n->v.name.size); - n->v.type_string = tg_string_from_key(scratch.arena, graph, rdi, tg_key_ext(tg_kind_from_rdi_type_kind(site_type->kind), (U64)site->type_idx)); - frames_count += 1; - } - - // rjf: add frame for concrete frame - DF_CallStackFrameNode *n = push_array(scratch.arena, DF_CallStackFrameNode, 1); - SLLQueuePush(first_frame, last_frame, n); - n->v.regs = unwind_f->regs; - n->v.is_inline_frame = 0; - n->v.name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &n->v.name.size); - n->v.type_string = tg_string_from_key(scratch.arena, graph, rdi, tg_key_ext(tg_kind_from_rdi_type_kind(procedure_type->kind), (U64)procedure->type_idx)); - frames_count += 1; - } - frames = push_array(scratch.arena, DF_CallStackFrame, frames_count); - { - U64 idx = 0; - for(DF_CallStackFrameNode *f = first_frame; f != 0; f = f->next) - { - MemoryCopyStruct(&frames[idx], &f->v); - idx += 1; - } - } - } + CTRL_Unwind base_unwind = df_query_cached_unwind_from_thread(thread); + DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, scope, process, &base_unwind); //- rjf: grab state typedef struct DF_CallStackViewState DF_CallStackViewState; @@ -4948,8 +4882,8 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) scroll_list_params.flags = UI_ScrollListFlag_All; scroll_list_params.row_height_px = floor_f32(ui_top_font_size()*2.5f); scroll_list_params.dim_px = dim_2f32(rect); - scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(3, frames_count)); - scroll_list_params.item_range = r1s64(0, frames_count+1); + scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(3, rich_unwind.frames.count)); + scroll_list_params.item_range = r1s64(0, rich_unwind.frames.count+1); scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1; } UI_ScrollListSignal scroll_list_sig = {0}; @@ -4982,7 +4916,9 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) } //- rjf: frame rows - for(S64 row_num = visible_row_range.min; row_num <= visible_row_range.max && row_num <= frames_count; row_num += 1) + for(S64 row_num = visible_row_range.min; + row_num <= visible_row_range.max && row_num <= rich_unwind.frames.count; + row_num += 1) { if(row_num == 0) { @@ -4992,12 +4928,25 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) // rjf: unpack frame U64 frame_idx = row_num-1; - DF_CallStackFrame *frame = &frames[frame_idx]; + DF_UnwindFrame *frame = &rich_unwind.frames.v[frame_idx]; U64 rip_vaddr = regs_rip_from_arch_block(thread->arch, frame->regs); DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); B32 frame_valid = (rip_vaddr != 0); - String8 symbol_name = frame->name; - String8 symbol_type_string = frame->type_string; + TG_Graph *graph = tg_graph_begin(bit_size_from_arch(thread->arch)/8, 256); + String8 symbol_name = {0}; + String8 symbol_type_string = {0}; + if(frame->procedure != 0) + { + symbol_name.str = rdi_name_from_procedure(frame->rdi, frame->procedure, &symbol_name.size); + RDI_TypeNode *type = rdi_element_from_name_idx(frame->rdi, TypeNodes, frame->procedure->type_idx); + symbol_type_string = tg_string_from_key(scratch.arena, graph, frame->rdi, tg_key_ext(tg_kind_from_rdi_type_kind(type->kind), frame->procedure->type_idx)); + } + if(frame->inline_site != 0) + { + symbol_name.str = rdi_string_from_idx(frame->rdi, frame->inline_site->name_string_idx, &symbol_name.size); + RDI_TypeNode *type = rdi_element_from_name_idx(frame->rdi, TypeNodes, frame->inline_site->type_idx); + symbol_type_string = tg_string_from_key(scratch.arena, graph, frame->rdi, tg_key_ext(tg_kind_from_rdi_type_kind(type->kind), frame->inline_site->type_idx)); + } // rjf: build row if(frame_valid) UI_NamedTableVectorF("###callstack_%p_%I64x", view, frame_idx) @@ -5058,7 +5007,7 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable|UI_BoxFlag_Clip, "frame_%I64x", frame_idx); UI_Parent(box) { - if(frame->is_inline_frame) + if(frame->inline_site != 0) { UI_PrefWidth(ui_text_dim(10, 1)) { From 98290ff29b562cea31520ed1ade5b8caa3668453 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 13 Jun 2024 14:58:18 -0700 Subject: [PATCH 42/44] proper inline frame unwind selection & storage & command parameterization --- src/df/core/df_core.c | 176 ++++++++++++++++++++------- src/df/core/df_core.h | 5 +- src/df/core/df_core.mdesk | 3 +- src/df/core/generated/df_core.meta.c | 7 +- src/df/core/generated/df_core.meta.h | 7 +- src/df/gfx/df_gfx.c | 118 ++++++++++-------- src/df/gfx/df_gfx.h | 28 +++-- src/df/gfx/df_views.c | 36 ++++-- 8 files changed, 255 insertions(+), 125 deletions(-) diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index 39912eb5..a2b09bcf 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -1110,6 +1110,16 @@ df_cmd_params_apply_spec_query(Arena *arena, DF_CtrlCtx *ctrl_ctx, DF_CmdParams params->index = u64; df_cmd_params_mark_slot(params, DF_CmdParamSlot_Index); }break; + case DF_CmdParamSlot_BaseUnwindIndex: + { + params->base_unwind_index = u64; + df_cmd_params_mark_slot(params, DF_CmdParamSlot_BaseUnwindIndex); + }break; + case DF_CmdParamSlot_InlineUnwindIndex: + { + params->inline_unwind_index = u64; + df_cmd_params_mark_slot(params, DF_CmdParamSlot_InlineUnwindIndex); + }break; case DF_CmdParamSlot_ID: { params->id = u64; @@ -2853,7 +2863,7 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) Rng1U64 line_vaddr_rng = {0}; { U64 ip_voff = df_voff_from_vaddr(module, ip_vaddr); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, ip_voff); + DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, ip_voff, 0); Rng1U64 line_voff_rng = line_info.voff_range; if(line_voff_rng.max != 0) { @@ -2867,7 +2877,7 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) // is enabled. This is enabled by default normally. { U64 opl_line_voff_rng = df_voff_from_vaddr(module, line_vaddr_rng.max); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, opl_line_voff_rng); + DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, opl_line_voff_rng, 0); if(line_info.pt.line == 0xf00f00 || line_info.pt.line == 0xfeefee) { line_vaddr_rng.max = df_vaddr_from_voff(module, line_info.voff_range.max); @@ -2978,7 +2988,7 @@ df_trap_net_from_thread__step_into_line(Arena *arena, DF_Entity *thread) Rng1U64 line_vaddr_rng = {0}; { U64 ip_voff = df_voff_from_vaddr(module, ip_vaddr); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, ip_voff); + DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, ip_voff, 0); Rng1U64 line_voff_rng = line_info.voff_range; if(line_voff_rng.max != 0) { @@ -2992,7 +3002,7 @@ df_trap_net_from_thread__step_into_line(Arena *arena, DF_Entity *thread) // is enabled. This is enabled by default normally. { U64 opl_line_voff_rng = df_voff_from_vaddr(module, line_vaddr_rng.max); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, opl_line_voff_rng); + DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, opl_line_voff_rng, 0); if(line_info.pt.line == 0xf00f00 || line_info.pt.line == 0xfeefee) { line_vaddr_rng.max = df_vaddr_from_voff(module, line_info.voff_range.max); @@ -3309,7 +3319,7 @@ df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entit //- rjf: voff -> src lookups internal DF_TextLineDasm2SrcInfo -df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff) +df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff, U64 inline_unwind_idx) { Temp scratch = scratch_begin(0, 0); DI_Scope *scope = di_scope_open(); @@ -3317,16 +3327,33 @@ df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff) DF_TextLineDasm2SrcInfo result = {0}; result.file = &df_g_nil_entity; { - U64 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, voff); - RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); - RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); - RDI_ParsedLineTable unit_line_info = {0}; - rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); - U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff); - if(line_info_idx < unit_line_info.count) + RDI_Unit *unit = rdi_unit_from_voff(rdi, voff); + RDI_LineTable *line_table = rdi_line_table_from_unit(rdi, unit); + RDI_Scope *scope = rdi_scope_from_voff(rdi, voff); { - RDI_Line *line = &unit_line_info.lines[line_info_idx]; - RDI_Column *column = (line_info_idx < unit_line_info.col_count) ? &unit_line_info.cols[line_info_idx] : 0; + U64 idx = 0; + for(RDI_Scope *s = scope; + s->inline_site_idx != 0 && idx < inline_unwind_idx; + s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx), idx += 1) + { + if(idx == inline_unwind_idx) + { + RDI_InlineSite *inline_site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx); + if(inline_site->line_table_idx != 0) + { + line_table = rdi_element_from_name_idx(rdi, LineTables, inline_site->line_table_idx); + } + break; + } + } + } + RDI_ParsedLineTable parsed_line_table = {0}; + rdi_parsed_from_line_table(rdi, line_table, &parsed_line_table); + U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed_line_table, voff); + if(line_info_idx < parsed_line_table.count) + { + RDI_Line *line = &parsed_line_table.lines[line_info_idx]; + RDI_Column *column = (line_info_idx < parsed_line_table.col_count) ? &parsed_line_table.cols[line_info_idx] : 0; RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx); String8 file_normalized_full_path = {0}; file_normalized_full_path.str = rdi_string_from_idx(rdi, file->normal_full_path_string_idx, &file_normalized_full_path.size); @@ -3336,7 +3363,7 @@ df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff) result.file = df_entity_from_path(file_normalized_full_path, DF_EntityFromPathFlag_All); } result.pt = txt_pt(line->line_num, column ? column->col_first : 1); - result.voff_range = r1u64(unit_line_info.voffs[line_info_idx], unit_line_info.voffs[line_info_idx+1]); + result.voff_range = r1u64(parsed_line_table.voffs[line_info_idx], parsed_line_table.voffs[line_info_idx+1]); } } di_scope_close(scope); @@ -3671,6 +3698,7 @@ df_unwind_from_ctrl_unwind(Arena *arena, DI_Scope *di_scope, DF_Entity *process, RDI_Scope *scope = rdi_scope_from_voff(rdi, rip_voff); // rjf: add rich frames for inlines + U64 inline_unwind_idx = 0; for(RDI_Scope *s = scope; s->inline_site_idx != 0; s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx)) { RDI_InlineSite *site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx); @@ -3681,6 +3709,9 @@ df_unwind_from_ctrl_unwind(Arena *arena, DI_Scope *di_scope, DF_Entity *process, n->v.rdi = rdi; n->v.procedure = 0; n->v.inline_site = site; + n->v.base_unwind_idx = base_frame_idx; + n->v.inline_unwind_idx = inline_unwind_idx; + inline_unwind_idx += 1; } // rjf: add frame for concrete frame @@ -3691,6 +3722,9 @@ df_unwind_from_ctrl_unwind(Arena *arena, DI_Scope *di_scope, DF_Entity *process, n->v.rdi = rdi; n->v.procedure = rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx); n->v.inline_site = 0; + n->v.base_unwind_idx = base_frame_idx; + n->v.inline_unwind_idx = inline_unwind_idx; + inline_unwind_idx = 0; } DF_Unwind result = {0}; { @@ -3706,6 +3740,24 @@ df_unwind_from_ctrl_unwind(Arena *arena, DI_Scope *di_scope, DF_Entity *process, return result; } +internal DF_UnwindFrame * +df_frame_from_unwind_idxs(DF_Unwind *unwind, U64 base_unwind_idx, U64 inline_unwind_idx) +{ + DF_UnwindFrame *f = 0; + for(U64 idx = 0; idx < unwind->frames.count; idx += 1) + { + if(unwind->frames.v[idx].base_unwind_idx == base_unwind_idx) + { + f = &unwind->frames.v[idx]; + if(unwind->frames.v[idx].inline_unwind_idx == inline_unwind_idx) + { + break; + } + } + } + return f; +} + //////////////////////////////// //~ rjf: Entity -> Log Entities @@ -3882,6 +3934,7 @@ df_ctrl_run(DF_RunKind run, DF_Entity *run_thread, CTRL_RunFlags flags, CTRL_Tra // rjf: set control context to top unwind df_state->ctrl_ctx.unwind_count = 0; + df_state->ctrl_ctx.inline_unwind_count = 0; scratch_end(scratch); } @@ -6506,13 +6559,15 @@ df_push_cmd__root(DF_CmdParams *params, DF_CmdSpec *spec) { log_infof("| cmd_spec: \"%S\"\n", params->cmd_spec->info.string); } - if(params->string.size != 0) { log_infof("| string: \"%S\"\n", params->string); } - if(params->file_path.size != 0) { log_infof("| file_path: \"%S\"\n", params->file_path); } - if(params->text_point.line != 0){ log_infof("| text_point: [line:%I64d, col:%I64d]\n", params->text_point.line, params->text_point.column); } - if(params->vaddr != 0) { log_infof("| vaddr: 0x%I64x\n", params->vaddr); } - if(params->voff != 0) { log_infof("| voff: 0x%I64x\n", params->voff); } - if(params->index != 0) { log_infof("| index: 0x%I64x\n", params->index); } - if(params->id != 0) { log_infof("| id: 0x%I64x\n", params->id); } + if(params->string.size != 0) { log_infof("| string: \"%S\"\n", params->string); } + if(params->file_path.size != 0) { log_infof("| file_path: \"%S\"\n", params->file_path); } + if(params->text_point.line != 0) { log_infof("| text_point: [line:%I64d, col:%I64d]\n", params->text_point.line, params->text_point.column); } + if(params->vaddr != 0) { log_infof("| vaddr: 0x%I64x\n", params->vaddr); } + if(params->voff != 0) { log_infof("| voff: 0x%I64x\n", params->voff); } + if(params->index != 0) { log_infof("| index: 0x%I64x\n", params->index); } + if(params->base_unwind_index != 0) { log_infof("| base_unwind_index: 0x%I64x\n", params->base_unwind_index); } + if(params->inline_unwind_index != 0){ log_infof("| inline_unwind_index: 0x%I64x\n", params->inline_unwind_index); } + if(params->id != 0) { log_infof("| id: 0x%I64x\n", params->id); } if(params->os_event != 0) { String8 kind_string = str8_lit(""); @@ -6786,7 +6841,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) DF_Entity *module = df_module_from_process_vaddr(process, stop_thread_vaddr); DI_Key dbgi_key = df_dbgi_key_from_module(module); U64 stop_thread_voff = df_voff_from_vaddr(module, stop_thread_vaddr); - DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, stop_thread_voff); + DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, stop_thread_voff, 0); DF_EntityList user_bps = df_query_cached_entity_list_with_kind(DF_EntityKind_Breakpoint); for(DF_EntityNode *n = user_bps.first; n != 0; n = n->next) { @@ -7623,32 +7678,67 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) }break; case DF_CoreCmdKind_SelectUnwind: { + DI_Scope *di_scope = di_scope_open(); DF_Entity *thread = df_entity_from_handle(df_state->ctrl_ctx.thread); - CTRL_Unwind unwind = df_query_cached_unwind_from_thread(thread); - U64 max_unwind = unwind.frames.count ? unwind.frames.count-1 : 0; - U64 index = Clamp(0, params.index, max_unwind); - df_state->ctrl_ctx.unwind_count = index; - df_state->ctrl_ctx.inline_unwind_count = 0; - }break; - case DF_CoreCmdKind_SelectInlineUnwind: - { - + DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); + CTRL_Unwind base_unwind = df_query_cached_unwind_from_thread(thread); + DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind); + DF_UnwindFrame *frame = df_frame_from_unwind_idxs(&rich_unwind, params.base_unwind_index, params.inline_unwind_index); + if(frame != 0) + { + df_state->ctrl_ctx.unwind_count = frame->base_unwind_idx; + df_state->ctrl_ctx.inline_unwind_count = frame->inline_unwind_idx; + } + di_scope_close(di_scope); }break; case DF_CoreCmdKind_UpOneFrame: - { - DF_CtrlCtx ctrl_ctx = df_ctrl_ctx(); - DF_CmdParams p = params; - p.index = (ctrl_ctx.unwind_count > 0 ? ctrl_ctx.unwind_count - 1 : 0); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Index); - df_cmd_list_push(arena, cmds, &p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); - }break; case DF_CoreCmdKind_DownOneFrame: { DF_CtrlCtx ctrl_ctx = df_ctrl_ctx(); - DF_CmdParams p = params; - p.index = ctrl_ctx.unwind_count+1; - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Index); - df_cmd_list_push(arena, cmds, &p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); + DI_Scope *di_scope = di_scope_open(); + DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread); + DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); + CTRL_Unwind base_unwind = df_query_cached_unwind_from_thread(thread); + DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind); + DF_UnwindFrame *current_frame = 0; + for(U64 idx = 0; idx < rich_unwind.frames.count; idx += 1) + { + if(rich_unwind.frames.v[idx].base_unwind_idx == ctrl_ctx.unwind_count && + rich_unwind.frames.v[idx].inline_unwind_idx == ctrl_ctx.inline_unwind_count) + { + current_frame = &rich_unwind.frames.v[idx]; + break; + } + } + if(current_frame == 0 && rich_unwind.frames.count != 0) + { + current_frame = &rich_unwind.frames.v[0]; + } + DF_UnwindFrame *next_frame = current_frame; + switch(core_cmd_kind) + { + default:{}break; + case DF_CoreCmdKind_UpOneFrame: + if(current_frame != 0 && (current_frame - rich_unwind.frames.v) > 0) + { + next_frame -= 1; + }break; + case DF_CoreCmdKind_DownOneFrame: + if(current_frame != 0 && (current_frame - rich_unwind.frames.v)+1 < rich_unwind.frames.count) + { + next_frame += 1; + }break; + } + if(next_frame != 0) + { + DF_CmdParams p = params; + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_InlineUnwindIndex); + p.base_unwind_index = next_frame->base_unwind_idx; + p.inline_unwind_index = next_frame->base_unwind_idx; + df_cmd_list_push(arena, cmds, &p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); + } + di_scope_close(di_scope); }break; case DF_CoreCmdKind_FreezeThread: case DF_CoreCmdKind_ThawThread: diff --git a/src/df/core/df_core.h b/src/df/core/df_core.h index 824cfc38..f4c8029e 100644 --- a/src/df/core/df_core.h +++ b/src/df/core/df_core.h @@ -527,6 +527,8 @@ struct DF_UnwindFrame RDI_Parsed *rdi; RDI_Procedure *procedure; RDI_InlineSite *inline_site; + U64 base_unwind_idx; + U64 inline_unwind_idx; }; typedef struct DF_UnwindFrameNode DF_UnwindFrameNode; @@ -1586,7 +1588,7 @@ internal String8 df_symbol_name_from_process_vaddr(Arena *arena, DF_Entity *proc internal DF_TextLineSrc2DasmInfoListArray df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entity *file, Rng1S64 line_num_range); //- rjf: voff -> src lookups -internal DF_TextLineDasm2SrcInfo df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff); +internal DF_TextLineDasm2SrcInfo df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff, U64 inline_unwind_idx); //- rjf: symbol -> voff lookups internal U64 df_voff_from_dbgi_key_symbol_name(DI_Key *dbgi_key, String8 symbol_name); @@ -1604,6 +1606,7 @@ internal EVAL_String2NumMap *df_push_member_map_from_dbgi_key_voff(Arena *arena, internal B32 df_set_thread_rip(DF_Entity *thread, U64 vaddr); internal DF_Entity *df_module_from_thread_candidates(DF_Entity *thread, DF_EntityList *candidates); internal DF_Unwind df_unwind_from_ctrl_unwind(Arena *arena, DI_Scope *di_scope, DF_Entity *process, CTRL_Unwind *base_unwind); +internal DF_UnwindFrame *df_frame_from_unwind_idxs(DF_Unwind *unwind, U64 base_unwind_idx, U64 inline_unwind_idx); //////////////////////////////// //~ rjf: Entity -> Log Entities diff --git a/src/df/core/df_core.mdesk b/src/df/core/df_core.mdesk index f4c5b70d..a633106b 100644 --- a/src/df/core/df_core.mdesk +++ b/src/df/core/df_core.mdesk @@ -96,6 +96,8 @@ DF_CmdParamSlotTable: {PreferDisassembly prefer_dasm `B32`} {ForceConfirm force_confirm `B32`} {Dir2 dir2 `Dir2`} + {BaseUnwindIndex base_unwind_index `U64`} + {InlineUnwindIndex inline_unwind_index `U64`} } @table(name lister_omit q_slot q_ent_kind q_allow_files q_allow_folders q_keep_oi q_select_oi q_is_code q_required canonical_icon string display_name desc search_tags ) @@ -152,7 +154,6 @@ DF_CoreCmdTable:// | | | {SelectThreadWindow 0 Entity Thread 0 0 0 0 0 1 Null "select_thread_window" "Select Thread On Window" "Selects a thread for the active window, overriding the global selected thread." "" } {SelectThreadView 0 Entity Thread 0 0 0 0 0 1 Null "select_thread_view" "Select Thread On View" "Selects a thread for the active view, overriding the global and per-window selected threads." "" } {SelectUnwind 1 Null Nil 0 0 0 0 0 0 Null "select_unwind" "Select Unwind" "Selects an unwind frame number for the selected thread." "" } - {SelectInlineUnwind 1 Null Nil 0 0 0 0 0 0 Null "select_inline_unwind" "Select Inline Unwind" "Selects an inline unwind frame number for the selected thread." "" } {UpOneFrame 0 Null Nil 0 0 0 0 0 0 UpArrow "up_one_frame" "Up One Frame" "Selects the callstack frame above the currently selected." "" } {DownOneFrame 0 Null Nil 0 0 0 0 0 0 DownArrow "down_one_frame" "Down One Frame" "Selects the callstack frame below the currently selected." "" } {FreezeThread 0 Entity Thread 0 0 0 0 0 1 Locked "freeze_thread" "Freeze Thread" "Freezes the passed thread." "" } diff --git a/src/df/core/generated/df_core.meta.c b/src/df/core/generated/df_core.meta.c index 55634ee9..ffa020e4 100644 --- a/src/df/core/generated/df_core.meta.c +++ b/src/df/core/generated/df_core.meta.c @@ -4,7 +4,7 @@ //- GENERATED CODE C_LINKAGE_BEGIN -Rng1U64 df_g_cmd_param_slot_range_table[22] = +Rng1U64 df_g_cmd_param_slot_range_table[24] = { {0}, {OffsetOf(DF_CmdParams, window), OffsetOf(DF_CmdParams, window) + sizeof(DF_Handle)}, @@ -28,6 +28,8 @@ Rng1U64 df_g_cmd_param_slot_range_table[22] = {OffsetOf(DF_CmdParams, prefer_dasm), OffsetOf(DF_CmdParams, prefer_dasm) + sizeof(B32)}, {OffsetOf(DF_CmdParams, force_confirm), OffsetOf(DF_CmdParams, force_confirm) + sizeof(B32)}, {OffsetOf(DF_CmdParams, dir2), OffsetOf(DF_CmdParams, dir2) + sizeof(Dir2)}, +{OffsetOf(DF_CmdParams, base_unwind_index), OffsetOf(DF_CmdParams, base_unwind_index) + sizeof(U64)}, +{OffsetOf(DF_CmdParams, inline_unwind_index), OffsetOf(DF_CmdParams, inline_unwind_index) + sizeof(U64)}, }; DF_IconKind df_g_entity_kind_icon_kind_table[26] = @@ -212,7 +214,7 @@ DF_CoreCmdKind_Null, DF_CoreCmdKind_Null, }; -DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[222] = +DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[221] = { { str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, { str8_lit_comp("exit"), str8_lit_comp("Exits the debugger."), str8_lit_comp("quit,close,abort"), str8_lit_comp("Exit"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_X}, @@ -247,7 +249,6 @@ DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[222] = { str8_lit_comp("select_thread_window"), str8_lit_comp("Selects a thread for the active window, overriding the global selected thread."), str8_lit_comp(""), str8_lit_comp("Select Thread On Window"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Thread, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Null}, { str8_lit_comp("select_thread_view"), str8_lit_comp("Selects a thread for the active view, overriding the global and per-window selected threads."), str8_lit_comp(""), str8_lit_comp("Select Thread On View"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Thread, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Null}, { str8_lit_comp("select_unwind"), str8_lit_comp("Selects an unwind frame number for the selected thread."), str8_lit_comp(""), str8_lit_comp("Select Unwind"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, -{ str8_lit_comp("select_inline_unwind"), str8_lit_comp("Selects an inline unwind frame number for the selected thread."), str8_lit_comp(""), str8_lit_comp("Select Inline Unwind"), (DF_CmdSpecFlag_OmitFromLists*1), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_Null}, { str8_lit_comp("up_one_frame"), str8_lit_comp("Selects the callstack frame above the currently selected."), str8_lit_comp(""), str8_lit_comp("Up One Frame"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_UpArrow}, { str8_lit_comp("down_one_frame"), str8_lit_comp("Selects the callstack frame below the currently selected."), str8_lit_comp(""), str8_lit_comp("Down One Frame"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Null, DF_EntityKind_Nil, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*0)}, DF_IconKind_DownArrow}, { str8_lit_comp("freeze_thread"), str8_lit_comp("Freezes the passed thread."), str8_lit_comp(""), str8_lit_comp("Freeze Thread"), (DF_CmdSpecFlag_OmitFromLists*0), {DF_CmdParamSlot_Entity, DF_EntityKind_Thread, (DF_CmdQueryFlag_AllowFiles*0)|(DF_CmdQueryFlag_AllowFolders*0)|(DF_CmdQueryFlag_CodeInput*0)|(DF_CmdQueryFlag_KeepOldInput*0)|(DF_CmdQueryFlag_SelectOldInput*0)|(DF_CmdQueryFlag_Required*1)}, DF_IconKind_Locked}, diff --git a/src/df/core/generated/df_core.meta.h b/src/df/core/generated/df_core.meta.h index fe27d1a6..9da5abe2 100644 --- a/src/df/core/generated/df_core.meta.h +++ b/src/df/core/generated/df_core.meta.h @@ -81,7 +81,6 @@ DF_CoreCmdKind_SelectThread, DF_CoreCmdKind_SelectThreadWindow, DF_CoreCmdKind_SelectThreadView, DF_CoreCmdKind_SelectUnwind, -DF_CoreCmdKind_SelectInlineUnwind, DF_CoreCmdKind_UpOneFrame, DF_CoreCmdKind_DownOneFrame, DF_CoreCmdKind_FreezeThread, @@ -393,6 +392,8 @@ DF_CmdParamSlot_ID, DF_CmdParamSlot_PreferDisassembly, DF_CmdParamSlot_ForceConfirm, DF_CmdParamSlot_Dir2, +DF_CmdParamSlot_BaseUnwindIndex, +DF_CmdParamSlot_InlineUnwindIndex, DF_CmdParamSlot_COUNT, } DF_CmdParamSlot; @@ -421,6 +422,8 @@ U64 id; B32 prefer_dasm; B32 force_confirm; Dir2 dir2; +U64 base_unwind_index; +U64 inline_unwind_index; }; DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_DEF(array); @@ -1531,7 +1534,7 @@ struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] = {&DEV_updating_indicator, str8_lit_comp("updating_indicator")}, }; C_LINKAGE_BEGIN -extern Rng1U64 df_g_cmd_param_slot_range_table[22]; +extern Rng1U64 df_g_cmd_param_slot_range_table[24]; extern DF_IconKind df_g_entity_kind_icon_kind_table[26]; extern String8 df_g_entity_kind_display_string_table[26]; extern String8 df_g_entity_kind_name_label_table[26]; diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index cf7f9ebe..7bb5e111 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -522,13 +522,15 @@ df_cmd_params_from_window(DF_Window *window) df_cmd_params_mark_slot(&p, DF_CmdParamSlot_View); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_PreferDisassembly); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_InlineUnwindIndex); p.window = df_handle_from_window(window); p.panel = df_handle_from_panel(window->focused_panel); p.view = df_handle_from_view(df_selected_tab_from_panel(window->focused_panel)); p.prefer_dasm = df_prefer_dasm_from_window(window); p.entity = ctrl_ctx.thread; - p.index = ctrl_ctx.unwind_count; + p.base_unwind_index = ctrl_ctx.unwind_count; + p.inline_unwind_index = ctrl_ctx.inline_unwind_count; return p; } @@ -542,13 +544,15 @@ df_cmd_params_from_panel(DF_Window *window, DF_Panel *panel) df_cmd_params_mark_slot(&p, DF_CmdParamSlot_View); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_PreferDisassembly); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_InlineUnwindIndex); p.window = df_handle_from_window(window); p.panel = df_handle_from_panel(panel); p.view = df_handle_from_view(df_selected_tab_from_panel(panel)); p.prefer_dasm = df_prefer_dasm_from_window(window); p.entity = ctrl_ctx.thread; - p.index = ctrl_ctx.unwind_count; + p.base_unwind_index = ctrl_ctx.unwind_count; + p.inline_unwind_index = ctrl_ctx.inline_unwind_count; return p; } @@ -562,13 +566,15 @@ df_cmd_params_from_view(DF_Window *window, DF_Panel *panel, DF_View *view) df_cmd_params_mark_slot(&p, DF_CmdParamSlot_View); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_PreferDisassembly); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_InlineUnwindIndex); p.window = df_handle_from_window(window); p.panel = df_handle_from_panel(panel); p.view = df_handle_from_view(view); p.prefer_dasm = df_prefer_dasm_from_window(window); p.entity = ctrl_ctx.thread; - p.index = ctrl_ctx.unwind_count; + p.base_unwind_index = ctrl_ctx.unwind_count; + p.inline_unwind_index = ctrl_ctx.inline_unwind_count; return p; } @@ -635,24 +641,18 @@ df_queue_drag_drop(void) } internal void -df_set_hovered_line_info(DI_Key *dbgi_key, U64 voff) +df_set_rich_hover_info(DF_RichHoverInfo *info) { - arena_clear(df_gfx_state->hover_line_arena); - df_gfx_state->hover_line_dbgi_key = di_key_copy(df_gfx_state->hover_line_arena, dbgi_key); - df_gfx_state->hover_line_voff = voff; - df_gfx_state->hover_line_set_this_frame = 1; + arena_clear(df_gfx_state->rich_hover_info_next_arena); + MemoryCopyStruct(&df_gfx_state->rich_hover_info_next, info); + df_gfx_state->rich_hover_info_next.dbgi_key = di_key_copy(df_gfx_state->rich_hover_info_next_arena, &info->dbgi_key); } -internal DI_Key -df_get_hovered_line_info_dbgi_key(void) +internal DF_RichHoverInfo +df_get_rich_hover_info(void) { - return df_gfx_state->hover_line_dbgi_key; -} - -internal U64 -df_get_hovered_line_info_voff(void) -{ - return df_gfx_state->hover_line_voff; + DF_RichHoverInfo info = df_gfx_state->rich_hover_info_current; + return info; } //////////////////////////////// @@ -1264,8 +1264,8 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) case DF_CoreCmdKind_SelectThread:goto thread_locator; case DF_CoreCmdKind_SelectThreadWindow: { + MemoryZeroStruct(&ws->ctrl_ctx_overrides); ws->ctrl_ctx_overrides.thread = params.entity; - ws->ctrl_ctx_overrides.unwind_count = 0; }goto thread_locator; case DF_CoreCmdKind_SelectThreadView: { @@ -1277,8 +1277,8 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) } if(!df_view_is_nil(view)) { + MemoryZeroStruct(&view->ctrl_ctx_overrides); view->ctrl_ctx_overrides.thread = params.entity; - view->ctrl_ctx_overrides.unwind_count = 0; } }goto thread_locator; case DF_CoreCmdKind_SelectUnwind: @@ -2598,11 +2598,12 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) { DI_Scope *scope = di_scope_open(); DF_Entity *thread = df_entity_from_handle(params.entity); - U64 unwind_count = params.index; + U64 base_unwind_index = params.base_unwind_index; + U64 inline_unwind_index = params.inline_unwind_index; if(thread->kind == DF_EntityKind_Thread) { // rjf: grab rip - U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_count); + U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, base_unwind_index); // rjf: extract thread/rip info DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); @@ -2610,7 +2611,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) DI_Key dbgi_key = df_dbgi_key_from_module(module); RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff); + DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff, inline_unwind_index); // rjf: snap to resolved line B32 missing_rip = (rip_vaddr == 0); @@ -2632,11 +2633,12 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) params.entity = df_handle_from_entity(thread); params.voff = rip_voff; params.vaddr = rip_vaddr; - params.index = unwind_count; + params.base_unwind_index = base_unwind_index; + params.inline_unwind_index = inline_unwind_index; df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualOff); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualAddr); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); df_cmd_list_push(arena, cmds, ¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation)); } @@ -2647,7 +2649,8 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) params.entity = df_handle_from_entity(thread); params.voff = rip_voff; params.vaddr = rip_vaddr; - params.index = unwind_count; + params.base_unwind_index = base_unwind_index; + params.inline_unwind_index = inline_unwind_index; df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualOff); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualAddr); @@ -2669,9 +2672,11 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) DF_Entity *selected_thread = df_entity_from_handle(ctrl_ctx.thread); DF_CmdParams params = df_cmd_params_from_window(ws); params.entity = df_handle_from_entity(selected_thread); - params.index = ctrl_ctx.unwind_count; + params.base_unwind_index = ctrl_ctx.unwind_count; + params.inline_unwind_index = ctrl_ctx.inline_unwind_count; df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineUnwindIndex); df_cmd_list_push(arena, cmds, ¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindThread)); }break; @@ -2804,7 +2809,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) // rjf: name resolved to voff * dbg info if(name_resolved != 0 && voff != 0) { - DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&voff_dbgi_key, voff); + DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&voff_dbgi_key, voff, 0); DF_CmdParams p = params; { p.file_path = df_full_path_from_entity(scratch.arena, dasm2src_info.file); @@ -11566,11 +11571,23 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ if(params->line_src2dasm[line_slice_idx].first != 0 && params->line_src2dasm[line_slice_idx].first->v.remap_line == mouse_pt.line) { - df_set_hovered_line_info(¶ms->line_src2dasm[line_slice_idx].first->v.dbgi_key, params->line_src2dasm[line_slice_idx].first->v.voff_range.min); + DF_RichHoverInfo info = {0}; + info.process = df_handle_from_entity(selected_thread_process); + info.vaddr_range = df_vaddr_range_from_voff_range(selected_thread_module, params->line_src2dasm[line_slice_idx].first->v.voff_range); + info.module = df_handle_from_entity(selected_thread_module); + info.dbgi_key = params->line_src2dasm[line_slice_idx].first->v.dbgi_key; + info.voff_range = params->line_src2dasm[line_slice_idx].first->v.voff_range; + df_set_rich_hover_info(&info); } if(params->line_dasm2src[line_slice_idx].first != 0) { - df_set_hovered_line_info(¶ms->line_dasm2src[line_slice_idx].first->v.dbgi_key, params->line_dasm2src[line_slice_idx].first->v.voff_range.min); + DF_RichHoverInfo info = {0}; + info.process = df_handle_from_entity(selected_thread_process); + info.vaddr_range = df_vaddr_range_from_voff_range(selected_thread_module, params->line_dasm2src[line_slice_idx].first->v.voff_range); + info.module = df_handle_from_entity(selected_thread_module); + info.dbgi_key = params->line_dasm2src[line_slice_idx].first->v.dbgi_key; + info.voff_range = params->line_dasm2src[line_slice_idx].first->v.voff_range; + df_set_rich_hover_info(&info); } } @@ -11734,8 +11751,9 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ // UI_Parent(text_container_box) ProfScope("build line text") UI_Focus(UI_FocusKind_Off) { - DI_Key hovered_line_dbgi_key = df_get_hovered_line_info_dbgi_key(); - U64 hovered_line_voff = df_get_hovered_line_info_voff(); + DF_RichHoverInfo rich_hover_info = df_get_rich_hover_info(); + DI_Key hovered_line_dbgi_key = rich_hover_info.dbgi_key; + U64 hovered_line_voff = rich_hover_info.voff_range.min; ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); UI_WidthFill UI_Column @@ -12029,18 +12047,14 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ // rjf: check dasm2src if(dasm2src_list->first != 0) { - DI_Key dbgi_key = dasm2src_list->first->v.dbgi_key; - if(di_key_match(&dbgi_key, &dasm2src_list->first->v.dbgi_key)) + for(DF_TextLineDasm2SrcInfoNode *n = dasm2src_list->first; n != 0; n = n->next) { - for(DF_TextLineDasm2SrcInfoNode *n = dasm2src_list->first; n != 0; n = n->next) + if(n->v.voff_range.min <= hovered_line_voff && + hovered_line_voff < n->v.voff_range.max) { - if(n->v.voff_range.min <= hovered_line_voff && - hovered_line_voff < n->v.voff_range.max) - { - line_info_line_num = n->v.pt.line; - matches = 1; - break; - } + line_info_line_num = n->v.pt.line; + matches = 1; + break; } } } @@ -13129,7 +13143,8 @@ df_gfx_init(OS_WindowRepaintFunctionType *window_repaint_entry_point, DF_StateDe df_gfx_state->repaint_hook = window_repaint_entry_point; df_gfx_state->cfg_main_font_path_arena = arena_alloc(); df_gfx_state->cfg_code_font_path_arena = arena_alloc(); - df_gfx_state->hover_line_arena = arena_alloc(); + df_gfx_state->rich_hover_info_next_arena = arena_alloc(); + df_gfx_state->rich_hover_info_current_arena = arena_alloc(); df_clear_bindings(); // rjf: register gfx layer views @@ -13236,7 +13251,9 @@ internal void df_gfx_begin_frame(Arena *arena, DF_CmdList *cmds) { ProfBeginFunction(); - df_gfx_state->hover_line_set_this_frame = 0; + arena_clear(df_gfx_state->rich_hover_info_current_arena); + MemoryCopyStruct(&df_gfx_state->rich_hover_info_current, &df_gfx_state->rich_hover_info_next); + df_gfx_state->rich_hover_info_current.dbgi_key = di_key_copy(df_gfx_state->rich_hover_info_current_arena, &df_gfx_state->rich_hover_info_current.dbgi_key); //- rjf: animate confirmation { @@ -14152,13 +14169,6 @@ df_gfx_end_frame(void) MemoryZeroStruct(&df_g_drag_drop_payload); } - //- rjf: clear hover line info - if(df_gfx_state->hover_line_set_this_frame == 0) - { - MemoryZeroStruct(&df_gfx_state->hover_line_dbgi_key); - df_gfx_state->hover_line_voff = 0; - } - //- rjf: clear frame request state if(df_gfx_state->num_frames_requested > 0) { diff --git a/src/df/gfx/df_gfx.h b/src/df/gfx/df_gfx.h index 1a91dc25..24f3b5b0 100644 --- a/src/df/gfx/df_gfx.h +++ b/src/df/gfx/df_gfx.h @@ -282,6 +282,19 @@ struct DF_DragDropPayload TxtPt text_point; }; +//////////////////////////////// +//~ rjf: Rich Hover Types + +typedef struct DF_RichHoverInfo DF_RichHoverInfo; +struct DF_RichHoverInfo +{ + DF_Handle process; + Rng1U64 vaddr_range; + DF_Handle module; + Rng1U64 voff_range; + DI_Key dbgi_key; +}; + //////////////////////////////// //~ rjf: View Rule Spec Types @@ -719,11 +732,11 @@ struct DF_GfxState // rjf: drag/drop state machine DF_DragDropState drag_drop_state; - // rjf: hover line info correllation state - Arena *hover_line_arena; - DI_Key hover_line_dbgi_key; - U64 hover_line_voff; - B32 hover_line_set_this_frame; + // rjf: rich hover info + Arena *rich_hover_info_next_arena; + Arena *rich_hover_info_current_arena; + DF_RichHoverInfo rich_hover_info_next; + DF_RichHoverInfo rich_hover_info_current; // rjf: running theme state DF_Theme cfg_theme_target; @@ -880,9 +893,8 @@ internal B32 df_drag_drop(DF_DragDropPayload *out_payload); internal void df_drag_kill(void); internal void df_queue_drag_drop(void); -internal void df_set_hovered_line_info(DI_Key *dbgi_key, U64 voff); -internal DI_Key df_get_hovered_line_info_dbgi_key(void); -internal U64 df_get_hovered_line_info_voff(void); +internal void df_set_rich_hover_info(DF_RichHoverInfo *info); +internal DF_RichHoverInfo df_get_rich_hover_info(void); //////////////////////////////// //~ rjf: View Spec State Functions diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 9d65df49..cd329b61 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -3417,7 +3417,7 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister) if(ui_hovering(sig)) UI_Tooltip { U64 binary_voff = df_voff_from_dbgi_key_symbol_name(&dbgi_key, name); - DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, binary_voff); + DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, binary_voff, 0); String8 file_path = df_full_path_from_entity(scratch.arena, dasm2src_info.file); S64 line_num = dasm2src_info.pt.line; df_code_label(1.f, 0, df_rgba_from_theme_color(DF_ThemeColor_CodeFunction), name); @@ -4808,7 +4808,7 @@ DF_VIEW_UI_FUNCTION_DEF(Scheduler) DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr); DI_Key dbgi_key = df_dbgi_key_from_module(module); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff); + DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff, 0); if(!df_entity_is_nil(line_info.file)) { UI_PrefWidth(ui_children_sum(0)) df_entity_src_loc_button(ws, line_info.file, line_info.pt); @@ -4843,7 +4843,6 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) DF_CtrlCtx ctrl_ctx = df_ctrl_ctx_from_view(ws, view); DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread); Architecture arch = df_architecture_from_entity(thread); - U64 selected_unwind_count = ctrl_ctx.unwind_count; DF_Entity *process = thread->parent; Vec4F32 thread_color = df_rgba_from_theme_color(DF_ThemeColor_PlainText); if(thread->flags & DF_EntityFlag_HasColor) @@ -4960,7 +4959,12 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) UI_TextAlignment(UI_TextAlign_Center) UI_FocusHot((row_selected && cs->cursor.x == 0) ? UI_FocusKind_On : UI_FocusKind_Off) { - String8 selected_string = selected_unwind_count == frame_idx ? df_g_icon_kind_text_table[DF_IconKind_RightArrow] : str8_lit(""); + String8 selected_string = {0}; + if(ctrl_ctx.unwind_count == frame->base_unwind_idx && + ctrl_ctx.inline_unwind_count == frame->inline_unwind_idx) + { + selected_string = df_g_icon_kind_text_table[DF_IconKind_RightArrow]; + } UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable|UI_BoxFlag_DrawText, "%S###selection_%i", selected_string, (int)frame_idx); UI_Signal sig = ui_signal_from_box(box); @@ -4973,8 +4977,10 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) if(ui_double_clicked(sig) || sig.f&UI_SignalFlag_KeyboardPressed) { DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); - params.index = frame_idx; - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineUnwindIndex); + params.base_unwind_index = frame->base_unwind_idx; + params.inline_unwind_index = frame->inline_unwind_idx; df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); } } @@ -5043,8 +5049,10 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) if(ui_double_clicked(sig) || sig.f&UI_SignalFlag_KeyboardPressed) { DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); - params.index = frame_idx; - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineUnwindIndex); + params.base_unwind_index = frame->base_unwind_idx; + params.inline_unwind_index = frame->inline_unwind_idx; df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); } } @@ -5064,8 +5072,10 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) if(ui_double_clicked(sig) || sig.f&UI_SignalFlag_KeyboardPressed) { DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); - params.index = frame_idx; - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineUnwindIndex); + params.base_unwind_index = frame->base_unwind_idx; + params.inline_unwind_index = frame->inline_unwind_idx; df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); } } @@ -5953,7 +5963,7 @@ DF_VIEW_UI_FUNCTION_DEF(Code) DF_Entity *module = df_module_from_process_vaddr(process, last_inst_on_unwound_rip_vaddr); U64 rip_voff = df_voff_from_vaddr(module, last_inst_on_unwound_rip_vaddr); DI_Key dbgi_key = df_dbgi_key_from_module(module); - DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff); + DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff, 0); if(dasm2src_info.file == entity && visible_line_num_range.min <= dasm2src_info.pt.line && dasm2src_info.pt.line <= visible_line_num_range.max) { U64 slice_line_idx = dasm2src_info.pt.line-visible_line_num_range.min; @@ -7093,7 +7103,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly) DF_TextLineDasm2SrcInfoNode *dasm2src_n = push_array(scratch.arena, DF_TextLineDasm2SrcInfoNode, 1); SLLQueuePush(code_slice_params.line_dasm2src[slice_idx].first, code_slice_params.line_dasm2src[slice_idx].last, dasm2src_n); code_slice_params.line_dasm2src[slice_idx].count += 1; - dasm2src_n->v = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, voff); + dasm2src_n->v = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, voff, 0); } } } @@ -7265,7 +7275,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly) DF_Entity *module = df_module_from_process_vaddr(process, vaddr); DI_Key dbgi_key = df_dbgi_key_from_module(module); U64 voff = df_voff_from_vaddr(module, vaddr); - DF_TextLineDasm2SrcInfo dasm2src = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, voff); + DF_TextLineDasm2SrcInfo dasm2src = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, voff, 0); String8 file_path = df_full_path_from_entity(scratch.arena, dasm2src.file); DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); params.text_point = dasm2src.pt; From dc34cdb59a3f54255ae9b658dd9c83355cdff1b8 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 13 Jun 2024 15:04:12 -0700 Subject: [PATCH 43/44] correct thread -> src mapping, given inline info --- src/df/core/df_core.c | 2 +- src/df/gfx/df_views.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index a2b09bcf..47affbc6 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -3333,7 +3333,7 @@ df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff, U64 in { U64 idx = 0; for(RDI_Scope *s = scope; - s->inline_site_idx != 0 && idx < inline_unwind_idx; + s->inline_site_idx != 0 && idx <= inline_unwind_idx; s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx), idx += 1) { if(idx == inline_unwind_idx) diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index cd329b61..9df21f5b 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -5957,13 +5957,14 @@ DF_VIEW_UI_FUNCTION_DEF(Code) { DF_Entity *thread = thread_n->entity; DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); - U64 unwind_count = (thread == selected_thread) ? ctrl_ctx.unwind_count : 0; + U64 base_unwind_count = (thread == selected_thread) ? ctrl_ctx.unwind_count : 0; + U64 inline_unwind_count = (thread == selected_thread) ? ctrl_ctx.inline_unwind_count : 0; U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_count); U64 last_inst_on_unwound_rip_vaddr = rip_vaddr - !!unwind_count; DF_Entity *module = df_module_from_process_vaddr(process, last_inst_on_unwound_rip_vaddr); U64 rip_voff = df_voff_from_vaddr(module, last_inst_on_unwound_rip_vaddr); DI_Key dbgi_key = df_dbgi_key_from_module(module); - DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff, 0); + DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff, inline_unwind_count); if(dasm2src_info.file == entity && visible_line_num_range.min <= dasm2src_info.pt.line && dasm2src_info.pt.line <= visible_line_num_range.max) { U64 slice_line_idx = dasm2src_info.pt.line-visible_line_num_range.min; From 6824ffddc01690cdc856a22601af86a3c8ce82ba Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 13 Jun 2024 15:17:12 -0700 Subject: [PATCH 44/44] intersect line voff ranges across all overlapping line tables when mapping voffs to line info; fixes inline stepping --- project.4coder | 2 +- src/df/core/df_core.c | 56 ++++++++++++++++++++++++++++++------------- 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/project.4coder b/project.4coder index d64a1538..f6eaee9e 100644 --- a/project.4coder +++ b/project.4coder @@ -57,7 +57,7 @@ commands = }, .rjf_f2 = { - .win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main.rdi && rdi_dump mule_main.rdi > mule_main.dump", + .win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main.rdi && rdi_dump mule_main.rdi > mule_main.dump && popd", .linux = "", .out = "*compilation*", .footer_panel = true, diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index 47affbc6..37438c21 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -3328,7 +3328,16 @@ df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff, U64 in result.file = &df_g_nil_entity; { RDI_Unit *unit = rdi_unit_from_voff(rdi, voff); - RDI_LineTable *line_table = rdi_line_table_from_unit(rdi, unit); + RDI_LineTable *unit_line_table = rdi_line_table_from_unit(rdi, unit); + typedef struct LineTableNode LineTableNode; + struct LineTableNode + { + LineTableNode *next; + RDI_ParsedLineTable parsed_line_table; + }; + LineTableNode start_line_table = {0}; + rdi_parsed_from_line_table(rdi, unit_line_table, &start_line_table.parsed_line_table); + LineTableNode *top_line_table = &start_line_table; RDI_Scope *scope = rdi_scope_from_voff(rdi, voff); { U64 idx = 0; @@ -3341,29 +3350,44 @@ df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff, U64 in RDI_InlineSite *inline_site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx); if(inline_site->line_table_idx != 0) { - line_table = rdi_element_from_name_idx(rdi, LineTables, inline_site->line_table_idx); + LineTableNode *n = push_array(scratch.arena, LineTableNode, 1); + SLLStackPush(top_line_table, n); + RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, inline_site->line_table_idx); + rdi_parsed_from_line_table(rdi, line_table, &n->parsed_line_table); } break; } } } - RDI_ParsedLineTable parsed_line_table = {0}; - rdi_parsed_from_line_table(rdi, line_table, &parsed_line_table); - U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed_line_table, voff); - if(line_info_idx < parsed_line_table.count) + for(LineTableNode *n = top_line_table; n == top_line_table; n = n->next) { - RDI_Line *line = &parsed_line_table.lines[line_info_idx]; - RDI_Column *column = (line_info_idx < parsed_line_table.col_count) ? &parsed_line_table.cols[line_info_idx] : 0; - RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx); - String8 file_normalized_full_path = {0}; - file_normalized_full_path.str = rdi_string_from_idx(rdi, file->normal_full_path_string_idx, &file_normalized_full_path.size); - MemoryCopyStruct(&result.dbgi_key, dbgi_key); - if(line->file_idx != 0 && file_normalized_full_path.size != 0) + RDI_ParsedLineTable parsed_line_table = n->parsed_line_table; + U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed_line_table, voff); + if(line_info_idx < parsed_line_table.count) { - result.file = df_entity_from_path(file_normalized_full_path, DF_EntityFromPathFlag_All); + RDI_Line *line = &parsed_line_table.lines[line_info_idx]; + RDI_Column *column = (line_info_idx < parsed_line_table.col_count) ? &parsed_line_table.cols[line_info_idx] : 0; + RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx); + String8 file_normalized_full_path = {0}; + file_normalized_full_path.str = rdi_string_from_idx(rdi, file->normal_full_path_string_idx, &file_normalized_full_path.size); + MemoryCopyStruct(&result.dbgi_key, dbgi_key); + if(line->file_idx != 0 && file_normalized_full_path.size != 0) + { + result.file = df_entity_from_path(file_normalized_full_path, DF_EntityFromPathFlag_All); + } + result.pt = txt_pt(line->line_num, column ? column->col_first : 1); + result.voff_range = r1u64(parsed_line_table.voffs[line_info_idx], parsed_line_table.voffs[line_info_idx+1]); + } + } + for(LineTableNode *n = top_line_table->next; n != 0; n = n->next) + { + RDI_ParsedLineTable parsed_line_table = n->parsed_line_table; + U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed_line_table, voff); + if(line_info_idx < parsed_line_table.count) + { + Rng1U64 voff_range = r1u64(parsed_line_table.voffs[line_info_idx], parsed_line_table.voffs[line_info_idx+1]); + result.voff_range = intersect_1u64(result.voff_range, voff_range); } - result.pt = txt_pt(line->line_num, column ? column->col_first : 1); - result.voff_range = r1u64(parsed_line_table.voffs[line_info_idx], parsed_line_table.voffs[line_info_idx+1]); } } di_scope_close(scope);