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;