// Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) #pragma once #define CV_MinComplexTypeIndex 0x1000 //////////////////////////////// // Aligns #define CV_LeafAlign 4 #define CV_SymbolAlign 1 #define CV_C13SubSectionAlign 4 #define CV_FileCheckSumsAlign 4 //////////////////////////////// //- Symbol and Leaf Headers #define CV_LeafSize_Max max_U16 typedef U16 CV_LeafSize; #define CV_SymSize_Max max_U16 typedef U16 CV_SymSize; typedef struct CV_LeafHeader { CV_LeafSize size; CV_LeafKind kind; } CV_LeafHeader; typedef struct CV_SymbolHeader { CV_SymSize size; CV_SymKind kind; } CV_SymbolHeader; //////////////////////////////// // Type Index Helpers typedef enum CV_TypeIndexSource { CV_TypeIndexSource_NULL, CV_TypeIndexSource_TPI, CV_TypeIndexSource_IPI, CV_TypeIndexSource_COUNT } CV_TypeIndexSource; typedef struct CV_TypeIndexInfo { struct CV_TypeIndexInfo *next; U64 offset; CV_TypeIndexSource source; } CV_TypeIndexInfo; typedef struct CV_TypeIndexInfoList { U64 count; CV_TypeIndexInfo *first; CV_TypeIndexInfo *last; } CV_TypeIndexInfoList; typedef struct CV_TypeIndexArray { U32 count; CV_TypeIndex *v; } CV_TypeIndexArray; //- $$Symbols typedef struct CV_Symbol { CV_SymKind kind; U64 offset; String8 data; } CV_Symbol; typedef struct CV_SymbolNode { struct CV_SymbolNode *next; struct CV_SymbolNode *prev; CV_Symbol data; } CV_SymbolNode; typedef struct CV_SymbolPtrNode { struct CV_SymbolPtrNode *next; CV_Symbol *data; } CV_SymbolPtrNode; typedef struct CV_SymbolList { U64 count; CV_Signature signature; CV_SymbolNode *first; CV_SymbolNode *last; } CV_SymbolList; typedef struct CV_SymbolListArray { U64 count; CV_SymbolList *v; } CV_SymbolListArray; typedef struct CV_SymbolPtrArray { U64 count; CV_SymbolNode **v; } CV_SymbolPtrArray; typedef struct CV_Scope { struct CV_ScopeList *children; struct CV_Scope *next; struct CV_Scope *prev; CV_Symbol symbol; } CV_Scope; typedef struct CV_ScopeList { CV_Scope *first; CV_Scope *last; } CV_ScopeList; typedef struct CV_ScopeFrame { struct CV_ScopeFrame *next; CV_ScopeList *list; CV_Scope *curr; U64 symbol_off; U32 *parent_off_ptr; U32 *end_off_ptr; } CV_ScopeFrame; //- $$FileChksms typedef struct CV_Checksum { CV_C13Checksum *header; String8 value; } CV_Checksum; typedef struct CV_ChecksumNode { struct CV_ChecksumNode *next; CV_Checksum data; } CV_ChecksumNode; typedef struct CV_ChecksumList { U64 count; CV_ChecksumNode *first; CV_ChecksumNode *last; } CV_ChecksumList; //- $$Lines typedef struct CV_LineArray { U32 file_off; U64 line_count; U64 col_count; U64 *voffs; // [line_count + 1] U32 *line_nums; // [line_count] U16 *col_nums; // [line_count * 2] } CV_LineArray; typedef struct CV_File { U32 file_off; CV_LineArray lines; } CV_File; typedef struct CV_C13LinesHeader { U64 sec_idx; U64 sec_off_lo; U64 sec_off_hi; U64 file_off; U64 line_count; U64 col_count; U64 line_array_off; U64 col_array_off; } CV_C13LinesHeader; typedef struct CV_C13LinesHeaderNode { struct CV_C13LinesHeaderNode *next; CV_C13LinesHeader v; } CV_C13LinesHeaderNode; typedef struct CV_C13LinesHeaderList { CV_C13LinesHeaderNode *first; CV_C13LinesHeaderNode *last; U64 count; } CV_C13LinesHeaderList; //////////////////////////////// typedef struct CV_UDTInfo { String8 name; String8 unique_name; CV_TypeProps props; } CV_UDTInfo; typedef struct CV_TypeServerInfo { String8 name; Guid sig; U32 age; } CV_TypeServerInfo; typedef struct CV_TypeServerInfoNode { struct CV_TypeServerInfoNode *next; CV_TypeServerInfo data; } CV_TypeServerInfoNode; typedef struct CV_TypeServerInfoList { CV_TypeServerInfoNode *first; CV_TypeServerInfoNode *last; U64 count; } CV_TypeServerInfoList; typedef struct CV_PrecompInfo { CV_TypeIndex start_index; U32 sig; U32 leaf_count; String8 obj_name; } CV_PrecompInfo; typedef struct CV_ObjInfo { U32 sig; String8 name; } CV_ObjInfo; //////////////////////////////// // Accels typedef struct CV_Line { U64 voff; U32 file_off; U32 line_num; U16 col_num; } CV_Line; typedef struct CV_LinesAccel { U64 map_count; CV_Line *map; } CV_LinesAccel; typedef struct CV_InlineeLinesAccel { U64 bucket_count; U64 bucket_max; CV_C13InlineeLinesParsed **buckets; } CV_InlineeLinesAccel; typedef struct CV_InlineBinaryAnnotsParsed { U64 lines_count; CV_LineArray *lines; Rng1U64List code_ranges; } CV_InlineBinaryAnnotsParsed; typedef struct CV_C13InlineeLinesParsedList { CV_C13InlineeLinesParsedNode *first; CV_C13InlineeLinesParsedNode *last; U64 count; } CV_C13InlineeLinesParsedList; //////////////////////////////// typedef U32 CV_C13SubSectionIdxKind; enum { CV_C13SubSectionIdxKind_NULL, #define X(N,c) CV_C13SubSectionIdxKind_##N, CV_C13SubSectionKindXList(X) #undef X CV_C13SubSectionIdxKind_COUNT }; typedef struct CV_C13SubSectionList { CV_C13SubSectionNode *first; CV_C13SubSectionNode *last; U64 count; } CV_C13SubSectionList; //////////////////////////////// typedef struct CV_DebugS { String8List data_list[CV_C13SubSectionIdxKind_COUNT]; } CV_DebugS; typedef struct CV_DebugT { U64 size; U64 count; U8 **v; } CV_DebugT; //////////////////////////////// //~ Leaf Helpers typedef struct CV_Leaf { CV_LeafKind kind; String8 data; } CV_Leaf; typedef struct CV_LeafNode { struct CV_LeafNode *next; CV_Leaf data; } CV_LeafNode; typedef struct CV_LeafList { U64 count; CV_LeafNode *first; CV_LeafNode *last; } CV_LeafList; //////////////////////////////// //~ String Hash Table typedef struct CV_StringTableRange { struct CV_StringTableRange *next; Rng1U64 range; U64 debug_s_idx; } CV_StringTableRange; typedef struct CV_StringBucket { String8 string; union { struct { U32 idx0; U32 idx1; }; U64 offset; } u; } CV_StringBucket; typedef struct CV_StringHashTable { U64 total_string_size; U64 total_insert_count; U64 bucket_cap; CV_StringBucket **buckets; } CV_StringHashTable; typedef struct CV_StringHashTableResult { U64 string_count; CV_StringBucket **buckets; } CV_StringHashTableResult; //////////////////////////////// //~ Task Contexts typedef struct { U64 cap; union { CV_SymbolNode ***buckets; CV_SymbolNode **deref_buckets; } u; Rng1U64 *ranges; CV_SymbolNode **symbols; } CV_SymbolDeduperTask; typedef struct { CV_SymbolList *list_arr; Rng1U64 *list_range_arr; U64 *symbol_base_arr; CV_SymbolNode **symbol_arr; } CV_SymbolListSyncer; typedef struct { CV_DebugS *arr; CV_StringTableRange **range_lists; U64 *string_counts; U64 bucket_cap; CV_StringBucket **buckets; U64 total_string_size; U64 total_insert_count; } CV_DedupStringTablesTask; typedef struct { U8 *buffer; Rng1U64 *ranges; CV_StringBucket **buckets; } CV_PackStringHashTableTask; typedef struct { CV_DebugT debug_t; Rng1U64 *ranges; String8List *lists; String8Node *nodes; } CV_Str8ListFromDebugT; //////////////////////////////// // Type Index Helpers internal CV_TypeIndexInfo * cv_symbol_type_index_info_push(Arena *arena, CV_TypeIndexInfoList *list, CV_TypeIndexSource source, U64 offset); internal CV_TypeIndexInfoList cv_get_symbol_type_index_offsets(Arena *arena, CV_SymKind kind, String8 data); internal CV_TypeIndexInfoList cv_get_leaf_type_index_offsets(Arena *arena, CV_LeafKind leaf_kind, String8 data); internal CV_TypeIndexInfoList cv_get_inlinee_type_index_offsets(Arena *arena, String8 raw_data); internal String8Array cv_get_data_around_type_indices(Arena *arena, CV_TypeIndexInfoList ti_list, String8 data); internal CV_TypeIndexSource cv_type_index_source_from_leaf_kind(CV_LeafKind leaf_kind); //////////////////////////////// internal U64 cv_name_offset_from_symbol(CV_SymKind kind, String8 data); internal String8 cv_name_from_symbol (CV_SymKind kind, String8 data); internal String8 cv_name_from_udt_info (CV_UDTInfo udt_info); internal B32 cv_is_udt_name_anon (String8 name); internal B32 cv_is_udt (CV_LeafKind kind); internal B32 cv_is_global_symbol (CV_SymKind kind); internal B32 cv_is_typedef (CV_SymKind kind); internal B32 cv_is_scope_symbol (CV_SymKind kind); internal B32 cv_is_end_symbol (CV_SymKind kind); internal B32 cv_is_leaf_type_server(CV_LeafKind kind); internal B32 cv_is_leaf_pch (CV_LeafKind kind); internal CV_ObjInfo cv_obj_info_from_symbol(CV_Symbol symbol); internal CV_TypeServerInfo cv_type_server_info_from_leaf(CV_Leaf leaf); internal CV_PrecompInfo cv_precomp_info_from_leaf(CV_Leaf leaf); internal B32 cv_is_reg_sp(CV_Arch arch, CV_Reg reg); //////////////////////////////// //~ Leaf Helpers internal U64 cv_compute_leaf_record_size(String8 data, U64 align); internal U64 cv_serialize_leaf_to_buffer(U8 *buffer, U64 buffer_cursor, U64 buffer_size, CV_LeafKind kind, String8 data, U64 align); internal String8 cv_serialize_leaf_ex(Arena *arena, CV_LeafKind kind, String8 data, U64 align); internal String8 cv_serialize_leaf(Arena *arena, CV_Leaf *leaf, U64 align); internal CV_Leaf cv_make_leaf(Arena *arena, CV_LeafKind kind, String8 data); internal U64 cv_deserial_leaf(String8 raw_data, U64 off, U64 align, CV_Leaf *leaf_out); internal CV_Leaf cv_leaf_from_string(String8 raw_data); //////////////////////////////// //~ Symbol Helpers internal U64 cv_compute_symbol_record_size(CV_Symbol *symbol, U64 align); internal U64 cv_serialize_symbol_to_buffer(U8 *buffer, U64 buffer_cursor, U64 buffer_size, CV_Symbol *symbol, U64 align); internal String8 cv_serialize_symbol(Arena *arena, CV_Symbol *symbol, U64 align); internal String8 cv_make_symbol(Arena *arena, CV_SymKind kind, String8 data); internal String8 cv_make_obj_name(Arena *arena, String8 obj_path, U32 sig); internal String8 cv_make_comp3(Arena *arena, CV_Compile3Flags flags, CV_Language lang, CV_Arch arch, U16 ver_fe_major, U16 ver_fe_minor, U16 ver_fe_build, U16 ver_feqfe, U16 ver_major, U16 ver_minor, U16 ver_build, U16 ver_qfe, String8 version_string); internal String8 cv_make_envblock(Arena *arena, String8List string_list); internal CV_Symbol cv_make_proc_ref(Arena *arena, CV_ModIndex imod, U32 stream_offset, String8 name, B32 is_local); internal CV_Symbol cv_make_pub32(Arena *arena, CV_Pub32Flags flags, U32 off, U16 isect, String8 name); internal CV_SymbolList cv_make_proc_refs(Arena *arena, CV_ModIndex imod, CV_SymbolList symbol_list); //////////////////////////////// // .debug$S Helpers internal CV_DebugS cv_parse_debug_s_c13(Arena *arena, String8 raw_debug_s); internal CV_DebugS cv_parse_debug_s_c13_list(Arena *arena, String8List raw_debug_s); internal CV_DebugS cv_parse_debug_s(Arena *arena, String8 raw_debug_s); internal void cv_debug_s_concat_in_place(CV_DebugS *dst, CV_DebugS *src); internal String8List cv_data_c13_from_debug_s(Arena *arena, CV_DebugS *debug_s, B32 write_sig); internal CV_C13SubSectionIdxKind cv_c13_sub_section_idx_from_kind(CV_C13SubSectionKind kind); internal String8List * cv_sub_section_ptr_from_debug_s(CV_DebugS *debug_s, CV_C13SubSectionKind kind); internal String8List cv_sub_section_from_debug_s(CV_DebugS debug_s, CV_C13SubSectionKind kind); internal String8 cv_string_table_from_debug_s(CV_DebugS debug_s); internal String8 cv_file_chksms_from_debug_s(CV_DebugS debug_s); //////////////////////////////// //~ .debug$T helpers internal CV_DebugT cv_debug_t_from_data_arr(Arena *arena, String8Array data_arr, U64 align); internal CV_DebugT cv_debug_t_from_data(Arena *arena, String8 data, U64 align); internal CV_Leaf cv_debug_t_get_leaf(CV_DebugT debug_t, U64 leaf_idx); internal String8 cv_debug_t_get_raw_leaf(CV_DebugT debug_t, U64 leaf_idx); internal CV_LeafHeader * cv_debug_t_get_leaf_header(CV_DebugT debug_t, U64 leaf_idx); internal B32 cv_debug_t_is_pch(CV_DebugT debug_t); internal B32 cv_debug_t_is_type_server(CV_DebugT debug_t); internal U64 cv_debug_t_array_count_leaves(U64 count, CV_DebugT *arr); internal String8List cv_str8_list_from_debug_t_parallel(TP_Context *tp, Arena *arena, CV_DebugT types); // $$Symbols internal void cv_parse_symbol_sub_section(Arena *arena, CV_SymbolList *list, U64 offset_base, String8 data, U64 align); internal void cv_symbol_list_push_node(CV_SymbolList *list, CV_SymbolNode *node); internal CV_SymbolNode * cv_symbol_list_push(Arena *arena, CV_SymbolList *list); internal CV_SymbolNode * cv_symbol_list_push_data(Arena *arena, CV_SymbolList *list, CV_SymKind kind, String8 data); internal CV_SymbolNode * cv_symbol_list_push_many(Arena *arena, CV_SymbolList *list, U64 count); internal void cv_symbol_list_remove_node(CV_SymbolList *list, CV_SymbolNode *node); internal void cv_symbol_list_concat_in_place(CV_SymbolList *list, CV_SymbolList *to_concat); internal void cv_symbol_list_concat_in_place_arr(CV_SymbolList *list, U64 count, CV_SymbolList *to_concat); internal U64 cv_symbol_list_arr_get_count(U64 count, CV_SymbolList *list_arr); internal String8List cv_data_from_symbol_list(Arena *arena, CV_SymbolList symbol_list, U64 align); internal CV_SymbolList cv_global_scope_symbols_from_list(Arena *arena, CV_SymbolList list); internal CV_ScopeList cv_symbol_tree_from_symbol_list(Arena *arena, CV_SymbolList list); internal CV_SymbolList cv_build_symbol_tree(Arena *arena, CV_ScopeList symbol_tree, U64 symbol_base, U64 align); internal CV_SymbolPtrArray cv_symbol_ptr_array_from_list(Arena *arena, TP_Context *tp, U64 count, CV_SymbolList *symbol_list_arr); // $$FileChksms #define CV_MAP_STRING_TO_OFFSET_FUNC(name) U64 name(void *ud, String8 string) typedef CV_MAP_STRING_TO_OFFSET_FUNC(CV_MapStringToOffsetFunc); //internal String8 cv_c13_file_chksms_from_sub_sections(String8 c13_data, CV_C13Parsed *ss); internal void cv_c13_patch_string_offsets_in_checksum_list(CV_ChecksumList checksum_list, String8 string_data, U64 string_data_base_offset, CV_StringHashTable string_ht); internal String8List cv_c13_collect_source_file_names(Arena *arena, CV_ChecksumList checksum_list, String8 string_data); // $$Lines internal CV_C13LinesHeaderList cv_c13_lines_from_sub_sections(Arena *arena, String8 c13_data, Rng1U64 ss_range); internal CV_LineArray cv_c13_line_array_from_data(Arena *arena, String8 c13_data, U64 sec_base, CV_C13LinesHeader parsed_lines); // $$InlineeLines internal CV_C13InlineeLinesParsedList cv_c13_inlinee_lines_from_sub_sections(Arena *arena, String8List raw_inlinee_lines); internal CV_InlineBinaryAnnotsParsed cv_c13_parse_inline_binary_annots(Arena *arena, U64 parent_voff, CV_C13InlineeLinesParsed *inlinee_parsed, String8 binary_annots); // $$FrameData internal void cv_c13_patch_checksum_offsets_in_frame_data_list(String8List frame_data, U32 checksum_rebase); //////////////////////////////// // $$Lines Accel internal void cv_make_c13_files(Arena *arena, String8 c13_data, CV_C13SubSectionList lines, U64 *file_count_out, CV_C13File **files_out); internal CV_LinesAccel * cv_make_lines_accel(Arena *arena, U64 lines_count, CV_LineArray *lines); internal CV_Line * cv_line_from_voff(CV_LinesAccel *accel, U64 voff, U64 *out_line_count); //////////////////////////////// // $$InlineeLines Accel internal U64 cv_c13_inlinee_lines_accel_hash(void *buffer, U64 size); internal B32 cv_c13_inlinee_lines_accel_push(CV_InlineeLinesAccel *accel, CV_C13InlineeLinesParsed *parsed); internal CV_C13InlineeLinesParsed * cv_c13_inlinee_lines_accel_find(CV_InlineeLinesAccel *accel, CV_ItemId inlinee); internal CV_InlineeLinesAccel * cv_c13_make_inlinee_lines_accel(Arena *arena, CV_C13InlineeLinesParsedList sub_sects); //////////////////////////////// // String Hash Table internal U64 cv_string_hash_table_hash(String8 string); internal CV_StringHashTable cv_dedup_string_tables(TP_Arena *arena, TP_Context *tp, U64 count, CV_DebugS *arr); internal CV_StringHashTableResult cv_serialize_string_hash_table(Arena *arena, TP_Context *tp, CV_StringHashTable string_ht); internal String8 cv_pack_string_hash_table(Arena *arena, TP_Context *tp, CV_StringHashTable string_ht); //////////////////////////////// internal CV_EncodedFramePtrReg cv_pick_fp_encoding(CV_SymFrameproc *frameproc, B32 is_local_param); internal CV_Reg cv_decode_fp_reg(CV_Arch arch, CV_EncodedFramePtrReg encoded_reg); internal Rng1U64List cv_make_defined_range_list_from_gaps(Arena *arena, Rng1U64 defrange, CV_LvarAddrGap *gaps, U64 gap_count); //////////////////////////////// internal U64 cv_size_from_reg_x86(CV_Reg reg); internal U64 cv_size_from_reg_x64(CV_Reg reg); internal U64 cv_size_from_reg(CV_Arch arch, CV_Reg reg); //////////////////////////////// internal CV_Arch cv_arch_from_coff_machine(COFF_MachineType machine); internal String8 cv_string_from_type_index_source(CV_TypeIndexSource ti_source);