diff --git a/build.bat b/build.bat index 74e5ea3e..75d519e8 100644 --- a/build.bat +++ b/build.bat @@ -43,7 +43,7 @@ if "%asan%"=="1" set auto_compile_flags=%auto_compile_flags% -fsanitize=add :: --- Compile/Link Line Definitions ------------------------------------------ set cl_common= /I..\src\ /I..\local\ /nologo /FC /Z7 set clang_common= -I..\src\ -I..\local\ -gcodeview -fdiagnostics-absolute-paths -Wall -Wno-unknown-warning-option -Wno-missing-braces -Wno-unused-function -Wno-writable-strings -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf -set cl_debug= call cl /Od /DBUILD_DEBUG=1 %cl_common% %auto_compile_flags% +set cl_debug= call cl /Od /Ob1 /DBUILD_DEBUG=1 %cl_common% %auto_compile_flags% set cl_release= call cl /O2 /DBUILD_DEBUG=0 %cl_common% %auto_compile_flags% set clang_debug= call clang -g -O0 -DBUILD_DEBUG=1 %clang_common% %auto_compile_flags% set clang_release= call clang -g -O2 -DBUILD_DEBUG=0 %clang_common% %auto_compile_flags% @@ -98,7 +98,7 @@ if not "%no_meta%"=="1" ( :: --- Build Everything (@build_targets) -------------------------------------- pushd build -if "%raddbg%"=="1" %compile% %gfx% ..\src\raddbg\raddbg_main.c %compile_link% %out%raddbg.exe || exit /b 1 +if "%raddbg%"=="1" %compile% ..\src\raddbg\raddbg_main.c %compile_link% %out%raddbg.exe || exit /b 1 if "%rdi_from_pdb%"=="1" %compile% ..\src\rdi_from_pdb\rdi_from_pdb_main.c %compile_link% %out%rdi_from_pdb.exe || exit /b 1 if "%rdi_from_dwarf%"=="1" %compile% ..\src\rdi_from_dwarf\rdi_from_dwarf.c %compile_link% %out%rdi_from_dwarf.exe || exit /b 1 if "%rdi_dump%"=="1" %compile% ..\src\rdi_dump\rdi_dump_main.c %compile_link% %out%rdi_dump.exe || exit /b 1 diff --git a/project.4coder b/project.4coder index 9f070887..f6eaee9e 100644 --- a/project.4coder +++ b/project.4coder @@ -47,6 +47,7 @@ commands = { .rjf_f1 = { + //.win = "build rdi_from_pdb rdi_dump && pushd build && rdi_from_pdb --pdb:mule_main.pdb --out:mule_main.rdi && rdi_dump mule_main.rdi > mule_main.dump && popd", .win = "build raddbg telemetry", .linux = "", .out = "*compilation*", @@ -56,7 +57,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, @@ -74,7 +75,7 @@ commands = }, .rjf_f4 = { - .win = "build rdi_from_pdb release telemetry && pushd build && rdi_from_pdb.exe --exe:UnrealEditorFortnite.exe --pdb:UnrealEditorFortnite.pdb --out:UnrealEditorFortnite.rdi --capture && popd", + .win = "build rdi_from_pdb release telemetry && pushd build && rdi_from_pdb.exe --pdb:UnrealEditorFortnite.pdb --out:profile.rdi --capture && popd", .linux = "", .out = "*compilation*", .footer_panel = true, diff --git a/src/codeview/codeview.c b/src/codeview/codeview.c index 5e3d5e6c..439a960d 100644 --- a/src/codeview/codeview.c +++ b/src/codeview/codeview.c @@ -7,21 +7,44 @@ #include "generated/codeview.meta.c" //////////////////////////////// -//~ CodeView Common Functions +//~ CodeView Common Decoding Helper Functions + +internal U64 +cv_hash_from_string(String8 string) +{ + U64 result = 5381; + for(U64 i = 0; i < string.size; i += 1) + { + result = ((result << 5) + result) + string.str[i]; + } + return result; +} + +internal U64 +cv_hash_from_item_id(CV_ItemId item_id) +{ + U64 result = cv_hash_from_string(str8_struct(&item_id)); + return result; +} internal CV_NumericParsed -cv_numeric_from_data_range(U8 *first, U8 *opl){ +cv_numeric_from_data_range(U8 *first, U8 *opl) +{ CV_NumericParsed result = {0}; - if (first + 2 <= opl){ + if(first + 2 <= opl) + { U16 x = *(U16*)first; - if (x < 0x8000){ + if(x < 0x8000) + { result.kind = CV_NumericKind_USHORT; result.val = first; result.encoded_size = 2; } - else{ + else + { U64 val_size = 0; - switch (x){ + switch(x) + { case CV_NumericKind_CHAR: val_size = 1; break; case CV_NumericKind_SHORT: case CV_NumericKind_USHORT: val_size = 2; break; @@ -46,21 +69,23 @@ cv_numeric_from_data_range(U8 *first, U8 *opl){ case CV_NumericKind_UTF8STRING:val_size = 0; break; // TODO: ??? case CV_NumericKind_FLOAT16: val_size = 2; break; } - - if (first + 2 + val_size <= opl){ + if(first + 2 + val_size <= opl) + { result.kind = x; result.val = (first + 2); result.encoded_size = 2 + val_size; } } } - return(result); + return result; } internal B32 -cv_numeric_fits_in_u64(CV_NumericParsed *num){ +cv_numeric_fits_in_u64(CV_NumericParsed *num) +{ B32 result = 0; - switch (num->kind){ + switch(num->kind) + { case CV_NumericKind_USHORT: case CV_NumericKind_ULONG: case CV_NumericKind_UQUADWORD: @@ -68,13 +93,15 @@ cv_numeric_fits_in_u64(CV_NumericParsed *num){ result = 1; }break; } - return(result); + return result; } internal B32 -cv_numeric_fits_in_s64(CV_NumericParsed *num){ +cv_numeric_fits_in_s64(CV_NumericParsed *num) +{ B32 result = 0; - switch (num->kind){ + switch(num->kind) + { case CV_NumericKind_CHAR: case CV_NumericKind_SHORT: case CV_NumericKind_LONG: @@ -83,91 +110,63 @@ cv_numeric_fits_in_s64(CV_NumericParsed *num){ result = 1; }break; } - return(result); + return result; } internal B32 -cv_numeric_fits_in_f64(CV_NumericParsed *num){ +cv_numeric_fits_in_f64(CV_NumericParsed *num) +{ B32 result = 0; - switch (num->kind){ + switch(num->kind) + { case CV_NumericKind_FLOAT32: case CV_NumericKind_FLOAT64: { result = 1; }break; } - return(result); + return result; } internal U64 -cv_u64_from_numeric(CV_NumericParsed *num){ +cv_u64_from_numeric(CV_NumericParsed *num) +{ U64 result = 0; - switch (num->kind){ - case CV_NumericKind_USHORT: - { - result = *(U16*)num->val; - }break; - - case CV_NumericKind_ULONG: - { - result = *(U32*)num->val; - }break; - - case CV_NumericKind_UQUADWORD: - { - result = *(U64*)num->val; - }break; + switch(num->kind) + { + case CV_NumericKind_USHORT: {result = *(U16*)num->val;}break; + case CV_NumericKind_ULONG: {result = *(U32*)num->val;}break; + case CV_NumericKind_UQUADWORD:{result = *(U64*)num->val;}break; } - return(result); + return result; } internal S64 -cv_s64_from_numeric(CV_NumericParsed *num){ +cv_s64_from_numeric(CV_NumericParsed *num) +{ S64 result = 0; - switch (num->kind){ - case CV_NumericKind_CHAR: - { - result = *(S8*)num->val; - }break; - - case CV_NumericKind_SHORT: - { - result = *(S16*)num->val; - }break; - - case CV_NumericKind_LONG: - { - result = *(S32*)num->val; - }break; - - case CV_NumericKind_QUADWORD: - { - result = *(S64*)num->val; - }break; + switch(num->kind) + { + case CV_NumericKind_CHAR: {result = *(S8*)num->val;}break; + case CV_NumericKind_SHORT: {result = *(S16*)num->val;}break; + case CV_NumericKind_LONG: {result = *(S32*)num->val;}break; + case CV_NumericKind_QUADWORD: {result = *(S64*)num->val;}break; } return(result); } internal F64 -cv_f64_from_numeric(CV_NumericParsed *num){ +cv_f64_from_numeric(CV_NumericParsed *num) +{ F64 result = 0; - switch (num->kind){ - case CV_NumericKind_FLOAT32: - { - result = *(F32*)num->val; - }break; - - case CV_NumericKind_FLOAT64: - { - result = *(F64*)num->val; - }break; + switch(num->kind) + { + case CV_NumericKind_FLOAT32:{result = *(F32*)num->val;}break; + case CV_NumericKind_FLOAT64:{result = *(F64*)num->val;}break; } return(result); } -//////////////////////////////// -//~ Inline Binary Annotation Helpers - internal U64 cv_decode_inline_annot_u32(String8 data, U64 offset, U32 *out_value) { @@ -238,28 +237,43 @@ cv_decode_inline_annot_s32(String8 data, U64 offset, S32 *out_value) return read_size; } -//////////////////////////////// -//~ CodeView Sym Parser Functions +internal S32 +cv_inline_annot_signed_from_unsigned_operand(U32 value) +{ + if(value & 1) + { + value = -(value >> 1); + } + else + { + value = value >> 1; + } + S32 result = (S32)value; + return result; +} -//- the first pass parser +//////////////////////////////// +//~ CodeView Parsing Functions + +//- rjf: record range stream parsing internal CV_RecRangeStream* -cv_rec_range_stream_from_data(Arena *arena, String8 sym_data, U64 sym_align){ +cv_rec_range_stream_from_data(Arena *arena, String8 sym_data, U64 sym_align) +{ Assert(1 <= sym_align && IsPow2OrZero(sym_align)); - CV_RecRangeStream *result = push_array(arena, CV_RecRangeStream, 1); - U8 *data = sym_data.str; U64 cursor = 0; U64 cap = sym_data.size; - for (;cursor + sizeof(CV_RecHeader) <= cap;){ + for(;cursor + sizeof(CV_RecHeader) <= cap;) + { // setup a new chunk arena_push_align(arena, 64); - CV_RecRangeChunk *cur_chunk = cv_rec_range_stream_push_chunk(arena, result); - + CV_RecRangeChunk *cur_chunk = push_array_no_zero(arena, CV_RecRangeChunk, 1); + SLLQueuePush(result->first_chunk, result->last_chunk, cur_chunk); U64 partial_count = 0; - for (;partial_count < CV_REC_RANGE_CHUNK_SIZE && cursor + sizeof(CV_RecHeader) <= cap; - partial_count += 1){ + for(;partial_count < CV_REC_RANGE_CHUNK_SIZE && cursor + sizeof(CV_RecHeader) <= cap; partial_count += 1) + { // compute cap CV_RecHeader *hdr = (CV_RecHeader*)(data + cursor); U64 symbol_cap_unclamped = cursor + 2 + hdr->size; @@ -273,110 +287,110 @@ cv_rec_range_stream_from_data(Arena *arena, String8 sym_data, U64 sym_align){ U32 next_pos = AlignPow2(symbol_cap, sym_align); cursor = next_pos; } - result->total_count += partial_count; } - - return(result); + return result; } -//- sym +internal CV_RecRangeArray +cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream) +{ + U64 total_count = stream->total_count; + CV_RecRange *ranges = push_array_no_zero(arena, CV_RecRange, total_count); + U64 idx = 0; + for(CV_RecRangeChunk *chunk = stream->first_chunk; chunk != 0; chunk = chunk->next) + { + U64 copy_count_raw = total_count - idx; + U64 copy_count = ClampTop(copy_count_raw, CV_REC_RANGE_CHUNK_SIZE); + MemoryCopy(ranges + idx, chunk->ranges, copy_count*sizeof(CV_RecRange)); + idx += copy_count; + } + CV_RecRangeArray result = {0}; + result.ranges = ranges; + result.count = total_count; + return result; +} -internal CV_SymParsed* -cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align){ +//- rjf: sym stream parsing + +internal CV_SymParsed * +cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align) +{ Assert(1 <= sym_align && IsPow2OrZero(sym_align)); - ProfBegin("cv_sym_from_data"); - + ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); - // gather up symbols + //- rjf: gather symbols CV_RecRangeStream *stream = cv_rec_range_stream_from_data(scratch.arena, sym_data, sym_align); - // convert to result + //- rjf: convert to result, fill basics CV_SymParsed *result = push_array(arena, CV_SymParsed, 1); result->data = sym_data; result->sym_align = sym_align; result->sym_ranges = cv_rec_range_array_from_stream(arena, stream); - cv_sym_top_level_info_from_syms(arena, sym_data, &result->sym_ranges, &result->info); - scratch_end(scratch); - - ProfEnd(); - - return(result); -} - -internal void -cv_sym_top_level_info_from_syms(Arena *arena, String8 sym_data, - CV_RecRangeArray *ranges, - CV_SymTopLevelInfo *info_out){ - MemoryZeroStruct(info_out); - - CV_RecRange *range = ranges->ranges; - CV_RecRange *opl = range + ranges->count; - for (; range < opl; range += 1){ - U8 *first = sym_data.str + range->off + 2; - U64 cap = range->hdr.size - 2; - - switch (range->hdr.kind){ - case CV_SymKind_COMPILE: + //- rjf: extract top-level-info + { + CV_RecRange *range = result->sym_ranges.ranges; + CV_RecRange *opl = range + result->sym_ranges.count; + for(;range < opl; range += 1) + { + U8 *first = sym_data.str + range->off + 2; + U64 cap = range->hdr.size - 2; + switch(range->hdr.kind) { - if (sizeof(CV_SymCompile) <= cap){ + case CV_SymKind_COMPILE: + if(sizeof(CV_SymCompile) <= cap) + { CV_SymCompile *compile = (CV_SymCompile*)first; - String8 ver_str = str8_cstring_capped((char*)(compile + 1), (char *)(first + cap)); - - info_out->arch = compile->machine; - info_out->language = CV_CompileFlags_ExtractLanguage(compile->flags);; - info_out->compiler_name = ver_str; - } - }break; - - case CV_SymKind_COMPILE2: - { - if (sizeof(CV_SymCompile2) <= cap){ + result->info.arch = compile->machine; + result->info.language = CV_CompileFlags_ExtractLanguage(compile->flags);; + result->info.compiler_name = ver_str; + }break; + case CV_SymKind_COMPILE2: + if(sizeof(CV_SymCompile2) <= cap) + { CV_SymCompile2 *compile2 = (CV_SymCompile2*)first; - String8 ver_str = str8_cstring_capped((char*)(compile2 + 1), (char*)(first + cap)); String8 compiler_name = push_str8f(arena, "%.*s %u.%u.%u", str8_varg(ver_str), compile2->ver_major, compile2->ver_minor, compile2->ver_build); - - info_out->arch = compile2->machine; - info_out->language = CV_Compile2Flags_ExtractLanguage(compile2->flags);; - info_out->compiler_name = compiler_name; - } - }break; - - case CV_SymKind_COMPILE3: - { - if (sizeof(CV_SymCompile3) <= cap){ + result->info.arch = compile2->machine; + result->info.language = CV_Compile2Flags_ExtractLanguage(compile2->flags);; + result->info.compiler_name = compiler_name; + }break; + case CV_SymKind_COMPILE3: + if(sizeof(CV_SymCompile3) <= cap) + { CV_SymCompile3 *compile3 = (CV_SymCompile3*)first; - String8 ver_str = str8_cstring_capped((char*)(compile3 + 1), (char *)(first + cap)); String8 compiler_name = push_str8f(arena, "%.*s %u.%u.%u", str8_varg(ver_str), compile3->ver_major, compile3->ver_minor, compile3->ver_build); - - info_out->arch = compile3->machine; - info_out->language = CV_Compile3Flags_ExtractLanguage(compile3->flags);; - info_out->compiler_name = compiler_name; - } - }break; + result->info.arch = compile3->machine; + result->info.language = CV_Compile3Flags_ExtractLanguage(compile3->flags);; + result->info.compiler_name = compiler_name; + }break; + } } } + + scratch_end(scratch); + ProfEnd(); + return result; } -//- leaf +//- rjf: leaf stream parsing -internal CV_LeafParsed* -cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId itype_first){ - ProfBegin("cv_leaf_from_data"); - +internal CV_LeafParsed * +cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId itype_first) +{ + ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); // gather up symbols @@ -390,57 +404,31 @@ cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId itype_first){ result->leaf_ranges = cv_rec_range_array_from_stream(arena, stream); scratch_end(scratch); - ProfEnd(); - - return(result); -} - -//- range streams - -internal CV_RecRangeChunk* -cv_rec_range_stream_push_chunk(Arena *arena, CV_RecRangeStream *stream){ - CV_RecRangeChunk *result = push_array_no_zero(arena, CV_RecRangeChunk, 1); - SLLQueuePush(stream->first_chunk, stream->last_chunk, result); - return(result); -} - -internal CV_RecRangeArray -cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream){ - U64 total_count = stream->total_count; - CV_RecRange *ranges = push_array_no_zero(arena, CV_RecRange, total_count); - U64 idx = 0; - for (CV_RecRangeChunk *chunk = stream->first_chunk; - chunk != 0; - chunk = chunk->next){ - U64 copy_count_raw = total_count - idx; - U64 copy_count = ClampTop(copy_count_raw, CV_REC_RANGE_CHUNK_SIZE); - MemoryCopy(ranges + idx, chunk->ranges, copy_count*sizeof(CV_RecRange)); - idx += copy_count; - } - CV_RecRangeArray result = {0}; - result.ranges = ranges; - result.count = total_count; - return(result); + return result; } //////////////////////////////// //~ CodeView C13 Parser Functions -internal CV_C13Parsed* -cv_c13_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSectionArray *sections){ - ProfBegin("cv_c13_from_data"); +internal CV_C13Parsed * +cv_c13_parsed_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSectionArray *sections) +{ + ProfBeginFunction(); - // gather c13 data + ////////////////////////////// + //- rjf: gather c13 sub-sections + // CV_C13SubSectionNode *file_chksms = 0; CV_C13SubSectionNode *first = 0; CV_C13SubSectionNode *last = 0; U64 count = 0; { U32 cursor = 0; - for (; cursor + sizeof(CV_C13_SubSectionHeader) <= c13_data.size;){ + for(; cursor + sizeof(CV_C13SubSectionHeader) <= c13_data.size;) + { // read header - CV_C13_SubSectionHeader *hdr = (CV_C13_SubSectionHeader*)(c13_data.str + cursor); + CV_C13SubSectionHeader *hdr = (CV_C13SubSectionHeader*)(c13_data.str + cursor); // get sub section info U32 sub_section_off = cursor + sizeof(*hdr); @@ -450,15 +438,16 @@ cv_c13_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSec U32 sub_section_size = after_sub_section_off - sub_section_off; // emit sub section - if (!(hdr->kind & CV_C13_SubSectionKind_IgnoreFlag)){ + if(!(hdr->kind & CV_C13SubSectionKind_IgnoreFlag)) + { CV_C13SubSectionNode *node = push_array(arena, CV_C13SubSectionNode, 1); SLLQueuePush(first, last, node); count += 1; node->kind = hdr->kind; node->off = sub_section_off; node->size = sub_section_size; - - if (hdr->kind == CV_C13_SubSectionKind_FileChksms){ + if(hdr->kind == CV_C13SubSectionKind_FileChksms) + { file_chksms = node; } } @@ -468,112 +457,182 @@ cv_c13_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSec } } - // parse each section - for (CV_C13SubSectionNode *node = first; - node != 0; - node = node->next){ + ////////////////////////////// + //- rjf: parse each sub-section + // + U64 inlinee_lines_parsed_slots_count = 4096; + CV_C13InlineeLinesParsedNode **inlinee_lines_parsed_slots = push_array(arena, CV_C13InlineeLinesParsedNode *, inlinee_lines_parsed_slots_count); + for(CV_C13SubSectionNode *node = first; + node != 0; + node = node->next) + { U8 *first = c13_data.str + node->off; U32 cap = node->size; - - switch (node->kind){ - case CV_C13_SubSectionKind_Lines: + switch(node->kind) + { + default:{}break; + + ////////////////////////// + //- rjf: line info sub-section + // + case CV_C13SubSectionKind_Lines: + if(sizeof(CV_C13SubSecLinesHeader) <= cap) { // read header - if (sizeof(CV_C13_SubSecLinesHeader) <= cap){ - U32 read_off = 0; - U64 read_off_opl = node->size; - CV_C13_SubSecLinesHeader *hdr = (CV_C13_SubSecLinesHeader*)(first + read_off); + U32 read_off = 0; + U64 read_off_opl = node->size; + CV_C13SubSecLinesHeader *hdr = (CV_C13SubSecLinesHeader*)(first + read_off); + read_off += sizeof(*hdr); + + // extract top level info + U32 sec_idx = hdr->sec; + B32 has_cols = !!(hdr->flags & CV_C13SubSecLinesFlag_HasColumns); + U64 secrel_off = hdr->sec_off; + U64 secrel_opl = secrel_off + hdr->len; + U64 sec_base_off = sections->sections[sec_idx - 1].voff; + + // rjf: bad section index -> skip + if(sec_idx < 1 || sections->count < sec_idx) + { + continue; + } + + // read files + for(;read_off+sizeof(CV_C13File) <= read_off_opl;) + { + // rjf: grab next file header + CV_C13File *file = (CV_C13File*)(first + read_off); + U32 file_off = file->file_off; + U32 line_count_unclamped = file->num_lines; + U32 block_size = file->block_size; + + // file_name from file_off + String8 file_name = {0}; + if(file_off + sizeof(CV_C13Checksum) <= file_chksms->size) + { + CV_C13Checksum *checksum = (CV_C13Checksum*)(c13_data.str + file_chksms->off + file_off); + U32 name_off = checksum->name_off; + file_name = pdb_strtbl_string_from_off(strtbl, name_off); + } + + // array layouts + U32 line_item_size = sizeof(CV_C13Line); + if (has_cols){ + line_item_size += sizeof(CV_C13Column); + } + + U32 line_array_off = read_off + sizeof(*file); + U32 line_count_max = (read_off_opl - line_array_off) / line_item_size; + U32 line_count = ClampTop(line_count_unclamped, line_count_max); + + U32 col_array_off = line_array_off + line_count*sizeof(CV_C13Line); + + // parse lines + U64 *voffs = push_array_no_zero(arena, U64, line_count + 1); + U32 *line_nums = push_array_no_zero(arena, U32, line_count); + + { + CV_C13Line *line_ptr = (CV_C13Line*)(first + line_array_off); + CV_C13Line *line_opl = line_ptr + line_count; + + // TODO(allen): check order correctness here + + U32 i = 0; + for (; line_ptr < line_opl; line_ptr += 1, i += 1){ + voffs[i] = line_ptr->off + secrel_off + sec_base_off; + line_nums[i] = CV_C13LineFlags_ExtractLineNumber(line_ptr->flags); + } + voffs[i] = secrel_opl + sec_base_off; + } + + // emit parsed lines + CV_C13LinesParsedNode *lines_parsed_node = push_array(arena, CV_C13LinesParsedNode, 1); + CV_C13LinesParsed *lines_parsed = &lines_parsed_node->v; + lines_parsed->sec_idx = sec_idx; + lines_parsed->file_off = file_off; + lines_parsed->secrel_base_off = secrel_off; + lines_parsed->file_name = file_name; + lines_parsed->voffs = voffs; + lines_parsed->line_nums = line_nums; + lines_parsed->line_count = line_count; + SLLQueuePush(node->lines_first, node->lines_last, lines_parsed_node); + + // rjf: advance + read_off += sizeof(*file); + read_off += line_item_size*line_count; + } + }break; + + ////////////////////////// + //- rjf: inlinee line info sub-section + // + case CV_C13SubSectionKind_InlineeLines: + if(sizeof(CV_C13InlineeLinesSig) <= cap) + { + // rjf: read sig + U32 read_off = 0; + U64 read_off_opl = node->size; + CV_C13InlineeLinesSig *sig = (CV_C13InlineeLinesSig *)(first + read_off); + read_off += sizeof(*sig); + + // rjf: read source lines + for(;read_off + sizeof(CV_C13InlineeSourceLineHeader) <= read_off_opl;) + { + // rjf: read next header + CV_C13InlineeSourceLineHeader *hdr = (CV_C13InlineeSourceLineHeader *)(first + read_off); read_off += sizeof(*hdr); - // extract top level info - U32 sec_idx = hdr->sec; - B32 has_cols = !!(hdr->flags & CV_C13_SubSecLinesFlag_HasColumns); - U64 secrel_off = hdr->sec_off; - U64 secrel_opl = secrel_off + hdr->len; - U64 sec_base_off = sections->sections[sec_idx - 1].voff; - - // rjf: bad section index -> skip - if(sec_idx < 1 || sections->count < sec_idx) + // rjf: file_off -> file_name + String8 file_name = {0}; + if(hdr->file_off + sizeof(CV_C13Checksum) <= file_chksms->size) { - continue; + CV_C13Checksum *checksum = (CV_C13Checksum*)(c13_data.str + file_chksms->off + hdr->file_off); + U32 name_off = checksum->name_off; + file_name = pdb_strtbl_string_from_off(strtbl, name_off); } - // read files - for(;read_off+sizeof(CV_C13_File) <= read_off_opl;) + // rjf: parse extra files + U32 extra_file_count = 0; + U32 *extra_files = 0; + if(*sig == CV_C13InlineeLinesSig_EXTRA_FILES && read_off+sizeof(U32) <= read_off_opl) { - // rjf: grab next file header - CV_C13_File *file = (CV_C13_File*)(first + read_off); - U32 file_off = file->file_off; - U32 line_count_unclamped = file->num_lines; - U32 block_size = file->block_size; - - // file_name from file_off - String8 file_name = {0}; - if (file_off + sizeof(CV_C13_Checksum) <= file_chksms->size){ - CV_C13_Checksum *checksum = (CV_C13_Checksum*)(c13_data.str + file_chksms->off + file_off); - U32 name_off = checksum->name_off; - file_name = pdb_strtbl_string_from_off(strtbl, name_off); - } - - // array layouts - U32 line_item_size = sizeof(CV_C13_Line); - if (has_cols){ - line_item_size += sizeof(CV_C13_Column); - } - - U32 line_array_off = read_off + sizeof(*file); - U32 line_count_max = (read_off_opl - line_array_off) / line_item_size; - U32 line_count = ClampTop(line_count_unclamped, line_count_max); - - U32 col_array_off = line_array_off + line_count*sizeof(CV_C13_Line); - - // parse lines - U64 *voffs = push_array_no_zero(arena, U64, line_count + 1); - U32 *line_nums = push_array_no_zero(arena, U32, line_count); - - { - CV_C13_Line *line_ptr = (CV_C13_Line*)(first + line_array_off); - CV_C13_Line *line_opl = line_ptr + line_count; - - // TODO(allen): check order correctness here - - U32 i = 0; - for (; line_ptr < line_opl; line_ptr += 1, i += 1){ - voffs[i] = line_ptr->off + secrel_off + sec_base_off; - line_nums[i] = CV_C13_LineFlags_ExtractLineNumber(line_ptr->flags); - } - voffs[i] = secrel_opl + sec_base_off; - } - - // emit parsed lines - CV_C13LinesParsedNode *lines_parsed_node = push_array(arena, CV_C13LinesParsedNode, 1); - CV_C13LinesParsed *lines_parsed = &lines_parsed_node->v; - lines_parsed->sec_idx = sec_idx; - lines_parsed->file_off = file_off; - lines_parsed->secrel_base_off = secrel_off; - lines_parsed->file_name = file_name; - lines_parsed->voffs = voffs; - lines_parsed->line_nums = line_nums; - lines_parsed->line_count = line_count; - SLLQueuePush(node->lines_first, node->lines_last, lines_parsed_node); - - // rjf: advance - read_off += sizeof(*file); - read_off += line_item_size*line_count; + U32 *extra_file_count_ptr = (U32 *)(first + read_off); + read_off += sizeof(*extra_file_count_ptr); + U32 max_extra_file_count = (read_off_opl-read_off)/sizeof(U32); + extra_file_count = Min(*extra_file_count_ptr, max_extra_file_count); + extra_files = (U32 *)(first + read_off); + read_off += sizeof(*extra_files)*extra_file_count; } + + // rjf: push node for this inlinee lines parsed into this subsection's list + CV_C13InlineeLinesParsedNode *n = push_array(arena, CV_C13InlineeLinesParsedNode, 1); + SLLQueuePush(node->inlinee_lines_first, node->inlinee_lines_last, n); + n->v.inlinee = hdr->inlinee; + n->v.file_name = file_name; + n->v.first_source_ln = hdr->first_source_ln; + n->v.extra_file_count = extra_file_count; + n->v.extra_files = extra_files; + + // rjf: push node into inlinee parse hash table + U64 hash = cv_hash_from_item_id(hdr->inlinee); + U64 slot_idx = hash%inlinee_lines_parsed_slots_count; + SLLStackPush_N(inlinee_lines_parsed_slots[slot_idx], n, hash_next); } }break; } } - // convert to result + ////////////////////////////// + //- rjf: fill output + // CV_C13Parsed *result = push_array(arena, CV_C13Parsed, 1); + result->data = c13_data; result->first_sub_section = first; result->last_sub_section = last; result->sub_section_count = count; result->file_chksms_sub_section = file_chksms; - + result->inlinee_lines_parsed_slots = inlinee_lines_parsed_slots; + result->inlinee_lines_parsed_slots_count = inlinee_lines_parsed_slots_count; ProfEnd(); - - return(result); + return result; } diff --git a/src/codeview/codeview.h b/src/codeview/codeview.h index 015829d3..b74dabd2 100644 --- a/src/codeview/codeview.h +++ b/src/codeview/codeview.h @@ -2651,9 +2651,9 @@ struct CV_LeafUDTModSrcLine //////////////////////////////// //~ CodeView Format C13 Line Info Types -#define CV_C13_SubSectionKind_IgnoreFlag 0x80000000 +#define CV_C13SubSectionKind_IgnoreFlag 0x80000000 -#define CV_C13_SubSectionKindXList(X)\ +#define CV_C13SubSectionKindXList(X)\ X(Symbols, 0xF1)\ X(Lines, 0xF2)\ X(StringTable, 0xF3)\ @@ -2670,83 +2670,83 @@ X(CoffSymbolRVA, 0xFD)\ X(XfgHashType, 0xFF)\ X(XfgHashVirtual, 0x100) -typedef U32 CV_C13_SubSectionKind; -typedef enum CV_C13_SubSectionKindEnum +typedef U32 CV_C13SubSectionKind; +typedef enum CV_C13SubSectionKindEnum { -#define X(N,c) CV_C13_SubSectionKind_##N = c, - CV_C13_SubSectionKindXList(X) +#define X(N,c) CV_C13SubSectionKind_##N = c, + CV_C13SubSectionKindXList(X) #undef X } -CV_C13_SubSectionKindEnum; +CV_C13SubSectionKindEnum; -typedef struct CV_C13_SubSectionHeader CV_C13_SubSectionHeader; -struct CV_C13_SubSectionHeader +typedef struct CV_C13SubSectionHeader CV_C13SubSectionHeader; +struct CV_C13SubSectionHeader { - CV_C13_SubSectionKind kind; + CV_C13SubSectionKind kind; U32 size; }; //- FileChksms sub-section -typedef U8 CV_C13_ChecksumKind; -typedef enum CV_C13_ChecksumKindEnum +typedef U8 CV_C13ChecksumKind; +typedef enum CV_C13ChecksumKindEnum { - CV_C13_ChecksumKind_Null, - CV_C13_ChecksumKind_MD5, - CV_C13_ChecksumKind_SHA1, - CV_C13_ChecksumKind_SHA256, + CV_C13ChecksumKind_Null, + CV_C13ChecksumKind_MD5, + CV_C13ChecksumKind_SHA1, + CV_C13ChecksumKind_SHA256, } -CV_C13_ChecksumKindEnum; +CV_C13ChecksumKindEnum; -typedef struct CV_C13_Checksum CV_C13_Checksum; -struct CV_C13_Checksum +typedef struct CV_C13Checksum CV_C13Checksum; +struct CV_C13Checksum { U32 name_off; U8 len; - CV_C13_ChecksumKind kind; + CV_C13ChecksumKind kind; }; //- Lines sub-section -typedef U16 CV_C13_SubSecLinesFlags; +typedef U16 CV_C13SubSecLinesFlags; enum { - CV_C13_SubSecLinesFlag_HasColumns = (1 << 0) + CV_C13SubSecLinesFlag_HasColumns = (1 << 0) }; -typedef struct CV_C13_SubSecLinesHeader CV_C13_SubSecLinesHeader; -struct CV_C13_SubSecLinesHeader +typedef struct CV_C13SubSecLinesHeader CV_C13SubSecLinesHeader; +struct CV_C13SubSecLinesHeader { U32 sec_off; CV_SectionIndex sec; - CV_C13_SubSecLinesFlags flags; + CV_C13SubSecLinesFlags flags; U32 len; }; -typedef struct CV_C13_File CV_C13_File; -struct CV_C13_File +typedef struct CV_C13File CV_C13File; +struct CV_C13File { U32 file_off; U32 num_lines; U32 block_size; - // CV_C13_Line[num_lines] lines; - // CV_C13_Column[num_lines] columns; (if HasColumns) + // CV_C13Line[num_lines] lines; + // CV_C13Column[num_lines] columns; (if HasColumns) }; -typedef U32 CV_C13_LineFlags; -#define CV_C13_LineFlags_ExtractLineNumber(f) ((f)&0xFFFFFF) -#define CV_C13_LineFlags_ExtractDeltaToEnd(f) (((f)>>24)&0x7F) -#define CV_C13_LineFlags_ExtractStatement(f) (((f)>>31)&0x1) +typedef U32 CV_C13LineFlags; +#define CV_C13LineFlags_ExtractLineNumber(f) ((f)&0xFFFFFF) +#define CV_C13LineFlags_ExtractDeltaToEnd(f) (((f)>>24)&0x7F) +#define CV_C13LineFlags_ExtractStatement(f) (((f)>>31)&0x1) -typedef struct CV_C13_Line CV_C13_Line; -struct CV_C13_Line +typedef struct CV_C13Line CV_C13Line; +struct CV_C13Line { U32 off; - CV_C13_LineFlags flags; + CV_C13LineFlags flags; }; -typedef struct CV_C13_Column CV_C13_Column; -struct CV_C13_Column +typedef struct CV_C13Column CV_C13Column; +struct CV_C13Column { U16 start; U16 end; @@ -2754,16 +2754,16 @@ struct CV_C13_Column //- FrameData sub-section -typedef U32 CV_C13_FrameDataFlags; +typedef U32 CV_C13FrameDataFlags; enum { - CV_C13_FrameDataFlag_HasStructuredExceptionHandling = (1 << 0), - CV_C13_FrameDataFlag_HasExceptionHandling = (1 << 1), - CV_C13_FrameDataFlag_HasIsFuncStart = (1 << 2), + CV_C13FrameDataFlag_HasStructuredExceptionHandling = (1 << 0), + CV_C13FrameDataFlag_HasExceptionHandling = (1 << 1), + CV_C13FrameDataFlag_HasIsFuncStart = (1 << 2), }; -typedef struct CV_C13_FrameData CV_C13_FrameData; -struct CV_C13_FrameData +typedef struct CV_C13FrameData CV_C13FrameData; +struct CV_C13FrameData { U32 start_voff; U32 code_size; @@ -2773,25 +2773,25 @@ struct CV_C13_FrameData U32 frame_func; U16 prolog_size; U16 saved_reg_size; - CV_C13_FrameDataFlags flags; + CV_C13FrameDataFlags flags; }; //- InlineLines sub-section -typedef U32 CV_C13_InlineeLinesSig; +typedef U32 CV_C13InlineeLinesSig; enum { - CV_C13_InlineeLinesSig_NORMAL, - CV_C13_InlineeLinesSig_EXTRA_FILES, + CV_C13InlineeLinesSig_NORMAL, + CV_C13InlineeLinesSig_EXTRA_FILES, }; -typedef struct CV_C13_InlineeSourceLineHeader CV_C13_InlineeSourceLineHeader; -struct CV_C13_InlineeSourceLineHeader +typedef struct CV_C13InlineeSourceLineHeader CV_C13InlineeSourceLineHeader; +struct CV_C13InlineeSourceLineHeader { CV_ItemId inlinee; // LF_FUNC_ID or LF_MFUNC_ID U32 file_off; // offset into FileChksms sub-section U32 first_source_ln; // base source line number for binary annotations - // if sig set to CV_C13_InlineeLinesSig_EXTRA_FILES + // if sig set to CV_C13InlineeLinesSig_EXTRA_FILES // U32 extra_file_count; // U32 files[]; }; @@ -2871,7 +2871,6 @@ struct CV_SymParsed CV_SymTopLevelInfo info; }; - //////////////////////////////// //~ CodeView Leaf Parser Types @@ -2913,26 +2912,54 @@ struct CV_C13LinesParsedNode CV_C13LinesParsed v; }; +typedef struct CV_C13InlineeLinesParsed CV_C13InlineeLinesParsed; +struct CV_C13InlineeLinesParsed +{ + CV_ItemId inlinee; + String8 file_name; + U32 first_source_ln; + U32 extra_file_count; + U32 *extra_files; +}; + +typedef struct CV_C13InlineeLinesParsedNode CV_C13InlineeLinesParsedNode; +struct CV_C13InlineeLinesParsedNode +{ + CV_C13InlineeLinesParsedNode *next; + CV_C13InlineeLinesParsedNode *hash_next; + CV_C13InlineeLinesParsed v; +}; + typedef struct CV_C13SubSectionNode CV_C13SubSectionNode; struct CV_C13SubSectionNode { struct CV_C13SubSectionNode *next; - CV_C13_SubSectionKind kind; + CV_C13SubSectionKind kind; U32 off; U32 size; CV_C13LinesParsedNode *lines_first; CV_C13LinesParsedNode *lines_last; + CV_C13InlineeLinesParsedNode *inlinee_lines_first; + CV_C13InlineeLinesParsedNode *inlinee_lines_last; }; typedef struct CV_C13Parsed CV_C13Parsed; struct CV_C13Parsed { + // rjf: source data + String8 data; + + // rjf: full sub-section list CV_C13SubSectionNode *first_sub_section; CV_C13SubSectionNode *last_sub_section; U64 sub_section_count; - // accelerator + // rjf: fastpath to file checksums section CV_C13SubSectionNode *file_chksms_sub_section; + + // rjf: fastpath to map inlinee CV_ItemId -> CV_InlineeLinesParsed quickly + CV_C13InlineeLinesParsedNode **inlinee_lines_parsed_slots; + U64 inlinee_lines_parsed_slots_count; }; //////////////////////////////// @@ -2946,52 +2973,45 @@ struct CV_TypeIdArray }; //////////////////////////////// -//~ CodeView Common Functions +//~ CodeView Common Decoding Helper Functions + +internal U64 cv_hash_from_string(String8 string); +internal U64 cv_hash_from_item_id(CV_ItemId item_id); internal CV_NumericParsed cv_numeric_from_data_range(U8 *first, U8 *opl); -internal B32 cv_numeric_fits_in_u64(CV_NumericParsed *num); -internal B32 cv_numeric_fits_in_s64(CV_NumericParsed *num); -internal B32 cv_numeric_fits_in_f64(CV_NumericParsed *num); +internal B32 cv_numeric_fits_in_u64(CV_NumericParsed *num); +internal B32 cv_numeric_fits_in_s64(CV_NumericParsed *num); +internal B32 cv_numeric_fits_in_f64(CV_NumericParsed *num); -internal U64 cv_u64_from_numeric(CV_NumericParsed *num); -internal S64 cv_s64_from_numeric(CV_NumericParsed *num); -internal F64 cv_f64_from_numeric(CV_NumericParsed *num); - -//////////////////////////////// -//~ Inline Binary Annotation Helpers +internal U64 cv_u64_from_numeric(CV_NumericParsed *num); +internal S64 cv_s64_from_numeric(CV_NumericParsed *num); +internal F64 cv_f64_from_numeric(CV_NumericParsed *num); internal U64 cv_decode_inline_annot_u32(String8 data, U64 offset, U32 *out_value); internal U64 cv_decode_inline_annot_s32(String8 data, U64 offset, S32 *out_value); +internal S32 cv_inline_annot_signed_from_unsigned_operand(U32 value); + + //////////////////////////////// -//~ CodeView Sym/Leaf Parser Functions +//~ CodeView Parsing Functions -//- the first pass parser -internal CV_RecRangeStream* cv_rec_range_stream_from_data(Arena *arena, String8 data, U64 align); +//- rjf: record range stream parsing +internal CV_RecRangeStream *cv_rec_range_stream_from_data(Arena *arena, String8 data, U64 align); +internal CV_RecRangeArray cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream); -//- sym -internal CV_SymParsed* cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align); +//- rjf: sym stream parsing +internal CV_SymParsed *cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align); -internal void cv_sym_top_level_info_from_syms(Arena *arena, String8 sym_data, - CV_RecRangeArray *ranges, - CV_SymTopLevelInfo *info_out); - -//- leaf -internal CV_LeafParsed* cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId first); - -//- range streams -internal CV_RecRangeChunk* cv_rec_range_stream_push_chunk(Arena *arena, - CV_RecRangeStream *stream); -// TODO(allen): check why this isn't a pointer return - -// leave a note if there's a good reason, otherwise switch to pointer return -internal CV_RecRangeArray cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream); +//- rjf: leaf stream parsing +internal CV_LeafParsed *cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId first); //////////////////////////////// //~ CodeView C13 Parser Functions typedef struct PDB_Strtbl PDB_Strtbl; typedef struct PDB_CoffSectionArray PDB_CoffSectionArray; -internal CV_C13Parsed* cv_c13_from_data(Arena *arena, String8 c13_data, struct PDB_Strtbl *strtbl, struct PDB_CoffSectionArray *sections); +internal CV_C13Parsed *cv_c13_parsed_from_data(Arena *arena, String8 c13_data, struct PDB_Strtbl *strtbl, struct PDB_CoffSectionArray *sections); #endif // CODEVIEW_H diff --git a/src/codeview/codeview_stringize.c b/src/codeview/codeview_stringize.c index 9c1245ae..8539ab96 100644 --- a/src/codeview/codeview_stringize.c +++ b/src/codeview/codeview_stringize.c @@ -49,12 +49,12 @@ cv_stringize_lvar_addr_gap_list(Arena *arena, String8List *out, void *first, voi } internal String8 -cv_string_from_c13_sub_section_kind(CV_C13_SubSectionKind kind){ +cv_string_from_c13_sub_section_kind(CV_C13SubSectionKind kind){ String8 result = str8_lit("UNRECOGNIZED_C13_SUB_SECTION_KIND"); switch (kind){ case 0: str8_lit("PARSE_ERROR"); break; -#define X(N,c) case CV_C13_SubSectionKind_##N: result = str8_lit(#N); break; - CV_C13_SubSectionKindXList(X) +#define X(N,c) case CV_C13SubSectionKind_##N: result = str8_lit(#N); break; + CV_C13SubSectionKindXList(X) #undef X } return(result); @@ -2280,7 +2280,7 @@ cv_stringize_c13_parsed(Arena *arena, String8List *out, CV_C13Parsed *c13){ switch(node->kind) { - case CV_C13_SubSectionKind_Lines: + case CV_C13SubSectionKind_Lines: { if (node->lines_first == 0) { @@ -2309,12 +2309,12 @@ cv_stringize_c13_parsed(Arena *arena, String8List *out, CV_C13Parsed *c13){ } }break; - case CV_C13_SubSectionKind_FileChksms: + case CV_C13SubSectionKind_FileChksms: { str8_list_push(arena, out, str8_lit(" no stringizer path\n")); }break; - case CV_C13_SubSectionKind_InlineeLines: + case CV_C13SubSectionKind_InlineeLines: { str8_list_push(arena, out, str8_lit(" no stringizer path\n")); }break; diff --git a/src/codeview/codeview_stringize.h b/src/codeview/codeview_stringize.h index b37cd904..9a94d9c4 100644 --- a/src/codeview/codeview_stringize.h +++ b/src/codeview/codeview_stringize.h @@ -27,7 +27,7 @@ internal void cv_stringize_lvar_addr_gap_list(Arena *arena, String8List *out, void *first, void *opl); internal String8 cv_string_from_basic_type(CV_BasicType basic_type); -internal String8 cv_string_from_c13_sub_section_kind(CV_C13_SubSectionKind kind); +internal String8 cv_string_from_c13_sub_section_kind(CV_C13SubSectionKind kind); internal String8 cv_string_from_reg(CV_Arch arch, CV_Reg reg); internal String8 cv_string_from_pointer_kind(CV_PointerKind ptr_kind); internal String8 cv_string_from_pointer_mode(CV_PointerMode ptr_mode); diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 7296cae6..6189dac8 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -418,11 +418,11 @@ ctrl_event_list_concat_in_place(CTRL_EventList *dst, CTRL_EventList *to_push) //- rjf: serialization internal String8 -ctrl_serialized_string_from_event(Arena *arena, CTRL_Event *event) +ctrl_serialized_string_from_event(Arena *arena, CTRL_Event *event, U64 max) { Temp scratch = scratch_begin(&arena, 1); String8List srl = {0}; - str8_serial_begin(scratch.arena, &srl);; + str8_serial_begin(scratch.arena, &srl); { str8_serial_push_struct(scratch.arena, &srl, &event->kind); str8_serial_push_struct(scratch.arena, &srl, &event->cause); @@ -440,8 +440,10 @@ ctrl_serialized_string_from_event(Arena *arena, CTRL_Event *event) str8_serial_push_struct(scratch.arena, &srl, &event->tls_root); str8_serial_push_struct(scratch.arena, &srl, &event->timestamp); str8_serial_push_struct(scratch.arena, &srl, &event->exception_code); - str8_serial_push_struct(scratch.arena, &srl, &event->string.size); - str8_serial_push_data(scratch.arena, &srl, event->string.str, event->string.size); + String8 string = event->string; + string.size = Min(string.size, max-srl.total_size); + str8_serial_push_struct(scratch.arena, &srl, &string.size); + str8_serial_push_data(scratch.arena, &srl, string.str, string.size); } String8 string = str8_serial_end(arena, &srl); scratch_end(scratch); @@ -913,6 +915,7 @@ ctrl_init(void) ctrl_state->u2c_ring_mutex = os_mutex_alloc(); ctrl_state->u2c_ring_cv = os_condition_variable_alloc(); ctrl_state->c2u_ring_size = KB(64); + ctrl_state->c2u_ring_max_string_size = ctrl_state->c2u_ring_size/2; ctrl_state->c2u_ring_base = push_array_no_zero(arena, U8, ctrl_state->c2u_ring_size); ctrl_state->c2u_ring_mutex = os_mutex_alloc(); ctrl_state->c2u_ring_cv = os_condition_variable_alloc(); @@ -2757,7 +2760,7 @@ ctrl_c2u_push_events(CTRL_EventList *events) for(CTRL_EventNode *n = events->first; n != 0; n = n ->next) { Temp scratch = scratch_begin(0, 0); - String8 event_srlzed = ctrl_serialized_string_from_event(scratch.arena, &n->v); + String8 event_srlzed = ctrl_serialized_string_from_event(scratch.arena, &n->v, ctrl_state->c2u_ring_size-sizeof(U64)); OS_MutexScope(ctrl_state->c2u_ring_mutex) for(;;) { U64 unconsumed_size = (ctrl_state->c2u_ring_write_pos-ctrl_state->c2u_ring_read_pos); @@ -2944,11 +2947,11 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_MachineID m // rjf: filename -> src_id U32 src_id = 0; { - RDI_NameMap *mapptr = rdi_name_map_from_kind(rdi, RDI_NameMapKind_NormalSourcePaths); + RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); if(mapptr != 0) { RDI_ParsedNameMap map = {0}; - rdi_name_map_parse(rdi, mapptr, &map); + rdi_parsed_from_name_map(rdi, mapptr, &map); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, filename_normalized.str, filename_normalized.size); if(node != 0) { @@ -2964,9 +2967,10 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_MachineID m // rjf: src_id * pt -> push { - RDI_SourceFile *src = rdi_element_from_idx(rdi, source_files, src_id); - RDI_ParsedLineMap line_map = {0}; - rdi_line_map_from_source_file(rdi, src, &line_map); + RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id); + RDI_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx); + RDI_ParsedSourceLineMap line_map = {0}; + rdi_parsed_from_source_line_map(rdi, src_line_map, &line_map); U32 voff_count = 0; U64 *voffs = rdi_line_voffs_from_num(&line_map, pt.line, &voff_count); for(U32 i = 0; i < voff_count; i += 1) @@ -2983,26 +2987,21 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_MachineID m { String8 symbol_name = bp->string; U64 voff = bp->u64; - if(rdi != 0 && rdi->procedures != 0) + RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures); + RDI_ParsedNameMap map = {0}; + rdi_parsed_from_name_map(rdi, mapptr, &map); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, symbol_name.str, symbol_name.size); + if(node != 0) { - RDI_NameMap *mapptr = rdi_name_map_from_kind(rdi, RDI_NameMapKind_Procedures); - if(mapptr != 0) + U32 id_count = 0; + U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); + for(U32 match_i = 0; match_i < id_count; match_i += 1) { - RDI_ParsedNameMap map = {0}; - rdi_name_map_parse(rdi, mapptr, &map); - RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, symbol_name.str, symbol_name.size); - if(node != 0) - { - U32 id_count = 0; - U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); - for(U32 match_i = 0; match_i < id_count; match_i += 1) - { - U64 proc_voff = rdi_first_voff_from_proc(rdi, ids[match_i]); - U64 proc_vaddr = proc_voff + base_vaddr; - DMN_Trap trap = {process, proc_vaddr + voff, (U64)bp}; - dmn_trap_chunk_list_push(arena, traps_out, 256, &trap); - } - } + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, ids[match_i]); + U64 proc_voff = rdi_first_voff_from_procedure(rdi, procedure); + U64 proc_vaddr = proc_voff + base_vaddr; + DMN_Trap trap = {process, proc_vaddr + voff, (U64)bp}; + dmn_trap_chunk_list_push(arena, traps_out, 256, &trap); } } }break; @@ -3445,11 +3444,10 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, CTRL_Entity *dbg_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath); DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp}; RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, max_U64); - RDI_NameMap *unparsed_map = rdi_name_map_from_kind(rdi, RDI_NameMapKind_GlobalVariables); - if(rdi->global_variables != 0 && unparsed_map != 0) + RDI_NameMap *unparsed_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_GlobalVariables); { RDI_ParsedNameMap map = {0}; - rdi_name_map_parse(rdi, unparsed_map, &map); + rdi_parsed_from_name_map(rdi, unparsed_map, &map); String8 name = str8_lit("__asan_shadow_memory_dynamic_address"); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, name.str, name.size); if(node != 0) @@ -3458,7 +3456,7 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); if(id_count > 0) { - RDI_GlobalVariable *global_var = rdi_element_from_idx(rdi, global_variables, ids[0]); + RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, ids[0]); U64 global_var_voff = global_var->voff; U64 global_var_vaddr = global_var->voff + module->vaddr_range.min; Architecture arch = process->arch; @@ -3672,13 +3670,17 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg, }break; case DMN_EventKind_DebugString: { - CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); - out_evt->kind = CTRL_EventKind_DebugString; - out_evt->msg_id = msg->msg_id; - out_evt->machine_id = CTRL_MachineID_Local; - out_evt->entity = event->thread; - out_evt->parent = event->process; - out_evt->string = event->string; + U64 num_strings = (event->string.size + ctrl_state->c2u_ring_max_string_size-1) / ctrl_state->c2u_ring_max_string_size; + for(U64 string_idx = 0; string_idx < num_strings; string_idx += 1) + { + CTRL_Event *out_evt = ctrl_event_list_push(scratch.arena, &evts); + out_evt->kind = CTRL_EventKind_DebugString; + out_evt->msg_id = msg->msg_id; + out_evt->machine_id = CTRL_MachineID_Local; + out_evt->entity = event->thread; + out_evt->parent = event->process; + out_evt->string = str8_substr(event->string, r1u64(string_idx*ctrl_state->c2u_ring_max_string_size, (string_idx+1)*ctrl_state->c2u_ring_max_string_size)); + } }break; case DMN_EventKind_SetThreadName: { @@ -4247,9 +4249,9 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) CTRL_Entity *dbg_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath); DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp}; RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, max_U64); - RDI_NameMap *unparsed_map = rdi_name_map_from_kind(rdi, RDI_NameMapKind_Procedures); + RDI_NameMap *unparsed_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures); RDI_ParsedNameMap map = {0}; - rdi_name_map_parse(rdi, unparsed_map, &map); + rdi_parsed_from_name_map(rdi, unparsed_map, &map); //- rjf: add traps for user-specified entry points on this message, if specified B32 entries_found = 0; @@ -4268,7 +4270,8 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) procedure_id = ids[0]; } } - U64 voff = rdi_first_voff_from_proc(rdi, procedure_id); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); + U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { entries_found = 1; @@ -4296,7 +4299,8 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) procedure_id = ids[0]; } } - U64 voff = rdi_first_voff_from_proc(rdi, procedure_id); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); + U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { entries_found = 1; @@ -4323,7 +4327,8 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) procedure_id = ids[0]; } } - U64 voff = rdi_first_voff_from_proc(rdi, procedure_id); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); + U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { DMN_Trap trap = {process->handle, module_base_vaddr + voff}; @@ -4356,7 +4361,8 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) procedure_id = ids[0]; } } - U64 voff = rdi_first_voff_from_proc(rdi, procedure_id); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); + U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { entries_found = 1; @@ -4400,7 +4406,8 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg) procedure_id = ids[0]; } } - U64 voff = rdi_first_voff_from_proc(rdi, procedure_id); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_id); + U64 voff = rdi_first_voff_from_procedure(rdi, procedure); if(voff != 0) { entries_found = 1; diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index 004df9f6..a5ad6540 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -579,6 +579,7 @@ struct CTRL_State // rjf: ctrl -> user event ring buffer U64 c2u_ring_size; + U64 c2u_ring_max_string_size; U8 *c2u_ring_base; U64 c2u_ring_write_pos; U64 c2u_ring_read_pos; @@ -677,7 +678,7 @@ internal CTRL_Event *ctrl_event_list_push(Arena *arena, CTRL_EventList *list); internal void ctrl_event_list_concat_in_place(CTRL_EventList *dst, CTRL_EventList *to_push); //- rjf: serialization -internal String8 ctrl_serialized_string_from_event(Arena *arena, CTRL_Event *event); +internal String8 ctrl_serialized_string_from_event(Arena *arena, CTRL_Event *event, U64 max); internal CTRL_Event ctrl_event_from_serialized_string(Arena *arena, String8 string); //////////////////////////////// diff --git a/src/dasm_cache/dasm_cache.c b/src/dasm_cache/dasm_cache.c index ef3418f1..ae248831 100644 --- a/src/dasm_cache/dasm_cache.c +++ b/src/dasm_cache/dasm_cache.c @@ -73,7 +73,10 @@ dasm_inst_array_idx_from_code_off__linear_scan(DASM_InstArray *array, U64 off) if(array->v[idx].code_off <= off && off < next_off) { result = idx; - break; + if(!(array->v[idx].flags & DASM_InstFlag_Decorative)) + { + break; + } } } return result; @@ -433,7 +436,7 @@ dasm_parse_thread__entry_point(void *p) ud_set_syntax(&udc, params.syntax == DASM_Syntax_Intel ? UD_SYN_INTEL : UD_SYN_ATT); // rjf: disassemble - RDI_SourceFile *last_file = &rdi_source_file_nil; + RDI_SourceFile *last_file = &rdi_nil_element_union.source_file; RDI_Line *last_line = 0; for(U64 off = 0; off < data.size;) { @@ -455,15 +458,16 @@ dasm_parse_thread__entry_point(void *p) if(rdi != &di_rdi_parsed_nil) { U64 voff = (params.vaddr+off) - params.base_vaddr; - U32 unit_idx = rdi_vmap_idx_from_voff(rdi->unit_vmap, rdi->unit_vmap_count, voff); - RDI_Unit *unit = rdi_element_from_idx(rdi, units, unit_idx); - RDI_ParsedLineInfo unit_line_info = {0}; - rdi_line_info_from_unit(rdi, unit, &unit_line_info); + U32 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, voff); + RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); + RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); + RDI_ParsedLineTable unit_line_info = {0}; + rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff); if(line_info_idx < unit_line_info.count) { RDI_Line *line = &unit_line_info.lines[line_info_idx]; - RDI_SourceFile *file = rdi_element_from_idx(rdi, source_files, line->file_idx); + RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx); String8 file_normalized_full_path = {0}; file_normalized_full_path.str = rdi_string_from_idx(rdi, file->normal_full_path_string_idx, &file_normalized_full_path.size); if(file != last_file) @@ -471,15 +475,19 @@ dasm_parse_thread__entry_point(void *p) if(params.style_flags & DASM_StyleFlag_SourceFilesNames && file->normal_full_path_string_idx != 0 && file_normalized_full_path.size != 0) { - DASM_Inst inst = {0}; + String8 inst_string = push_str8f(scratch.arena, "> %S", file_normalized_full_path); + DASM_Inst inst = {u32_from_u64_saturate(off), DASM_InstFlag_Decorative, 0, r1u64(inst_strings.total_size + inst_strings.node_count, + inst_strings.total_size + inst_strings.node_count + inst_string.size)}; dasm_inst_chunk_list_push(scratch.arena, &inst_list, 1024, &inst); - str8_list_pushf(scratch.arena, &inst_strings, "> %S", file_normalized_full_path); + str8_list_push(scratch.arena, &inst_strings, inst_string); } if(params.style_flags & DASM_StyleFlag_SourceFilesNames && file->normal_full_path_string_idx == 0) { - DASM_Inst inst = {0}; + String8 inst_string = str8_lit(">"); + DASM_Inst inst = {u32_from_u64_saturate(off), DASM_InstFlag_Decorative, 0, r1u64(inst_strings.total_size + inst_strings.node_count, + inst_strings.total_size + inst_strings.node_count + inst_string.size)}; dasm_inst_chunk_list_push(scratch.arena, &inst_list, 1024, &inst); - str8_list_pushf(scratch.arena, &inst_strings, ">"); + str8_list_push(scratch.arena, &inst_strings, inst_string); } last_file = file; } @@ -511,9 +519,11 @@ dasm_parse_thread__entry_point(void *p) String8 line_text = str8_skip_chop_whitespace(str8_substr(data, text_info.lines_ranges[line->line_num-1])); if(line_text.size != 0) { - DASM_Inst inst = {0}; + String8 inst_string = push_str8f(scratch.arena, "> %S", line_text); + DASM_Inst inst = {u32_from_u64_saturate(off), DASM_InstFlag_Decorative, 0, r1u64(inst_strings.total_size + inst_strings.node_count, + inst_strings.total_size + inst_strings.node_count + inst_string.size)}; dasm_inst_chunk_list_push(scratch.arena, &inst_list, 1024, &inst); - str8_list_pushf(scratch.arena, &inst_strings, "> %S", line_text); + str8_list_push(scratch.arena, &inst_strings, inst_string); } } } @@ -551,12 +561,12 @@ dasm_parse_thread__entry_point(void *p) String8 symbol_part = {0}; if(jump_dst_vaddr != 0 && rdi != &di_rdi_parsed_nil && params.style_flags & DASM_StyleFlag_SymbolNames) { - RDI_U32 scope_idx = rdi_vmap_idx_from_voff(rdi->scope_vmap, rdi->scope_vmap_count, jump_dst_vaddr-params.base_vaddr); + RDI_U32 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, jump_dst_vaddr-params.base_vaddr); if(scope_idx != 0) { - RDI_Scope *scope = rdi_element_from_idx(rdi, scopes, scope_idx); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); RDI_U32 procedure_idx = scope->proc_idx; - RDI_Procedure *procedure = rdi_element_from_idx(rdi, procedures, procedure_idx); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_idx); String8 procedure_name = {0}; procedure_name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &procedure_name.size); if(procedure_name.size != 0) @@ -566,8 +576,8 @@ dasm_parse_thread__entry_point(void *p) } } String8 inst_string = push_str8f(scratch.arena, "%S%S%s%S", addr_part, code_bytes_part, udc.asm_buf, symbol_part); - DASM_Inst inst = {off, rel_voff, r1u64(inst_strings.total_size + inst_strings.node_count, - inst_strings.total_size + inst_strings.node_count + inst_string.size)}; + DASM_Inst inst = {u32_from_u64_saturate(off), 0, rel_voff, r1u64(inst_strings.total_size + inst_strings.node_count, + inst_strings.total_size + inst_strings.node_count + inst_string.size)}; dasm_inst_chunk_list_push(scratch.arena, &inst_list, 1024, &inst); str8_list_push(scratch.arena, &inst_strings, inst_string); diff --git a/src/dasm_cache/dasm_cache.h b/src/dasm_cache/dasm_cache.h index 5c588b56..bb3e33e8 100644 --- a/src/dasm_cache/dasm_cache.h +++ b/src/dasm_cache/dasm_cache.h @@ -42,10 +42,17 @@ struct DASM_Params //////////////////////////////// //~ rjf: Instruction Types +typedef U32 DASM_InstFlags; +enum +{ + DASM_InstFlag_Decorative = (1<<0), +}; + typedef struct DASM_Inst DASM_Inst; struct DASM_Inst { - U64 code_off; + U32 code_off; + DASM_InstFlags flags; U64 addr; Rng1U64 text_range; }; diff --git a/src/dbgi/dbgi.h b/src/dbgi/dbgi.h index ece98ae6..80e84c73 100644 --- a/src/dbgi/dbgi.h +++ b/src/dbgi/dbgi.h @@ -192,41 +192,7 @@ struct DI_Shared global DI_Shared *di_shared = 0; thread_static DI_TCTX *di_tctx = 0; -global RDI_Parsed di_rdi_parsed_nil = -{ - 0, - 0, - 0, - 0, - {0}, - 0, - 0, - 0, - 0, - 0, - 0, - &rdi_top_level_info_nil, - &rdi_binary_section_nil, 1, - &rdi_file_path_node_nil, 1, - &rdi_source_file_nil, 1, - &rdi_unit_nil, 1, - &rdi_vmap_entry_nil, 1, - &rdi_type_node_nil, 1, - &rdi_udt_nil, 1, - &rdi_member_nil, 1, - &rdi_enum_member_nil, 1, - &rdi_global_variable_nil, 1, - &rdi_vmap_entry_nil, 1, - &rdi_thread_variable_nil, 1, - &rdi_procedure_nil, 1, - &rdi_scope_nil, 1, - &rdi_voff_nil, 1, - &rdi_vmap_entry_nil, 1, - &rdi_local_nil, 1, - &rdi_location_block_nil, 1, - 0, 0, - 0, 0, -}; +global RDI_Parsed di_rdi_parsed_nil = {0}; //////////////////////////////// //~ rjf: Basic Helpers diff --git a/src/demon/demon_core.h b/src/demon/demon_core.h index 48a2cb63..53d3ef99 100644 --- a/src/demon/demon_core.h +++ b/src/demon/demon_core.h @@ -15,7 +15,7 @@ typedef struct DMN_CtrlCtx DMN_CtrlCtx; struct DMN_CtrlCtx { - U64 u64 [1]; + U64 u64[1]; }; //////////////////////////////// diff --git a/src/demon/win32/demon_core_win32.c b/src/demon/win32/demon_core_win32.c index 14bf4c00..9b66a259 100644 --- a/src/demon/win32/demon_core_win32.c +++ b/src/demon/win32/demon_core_win32.c @@ -1554,6 +1554,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) // U64 begin_time = os_now_microseconds(); String8List debug_strings = {0}; + DMN_Event *debug_strings_event = 0; for(B32 keep_going = 1; keep_going;) { keep_going = 0; @@ -1588,13 +1589,17 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) } if(resume_good) { - evt_good = !!WaitForDebugEvent(&evt, INFINITE); + evt_good = !!WaitForDebugEvent(&evt, 100); if(evt_good) { dmn_w32_shared->resume_needed = 1; dmn_w32_shared->resume_pid = evt.dwProcessId; dmn_w32_shared->resume_tid = evt.dwThreadId; } + else + { + keep_going = 1; + } ins_atomic_u64_inc_eval(&dmn_w32_shared->run_gen); ins_atomic_u64_inc_eval(&dmn_w32_shared->mem_gen); ins_atomic_u64_inc_eval(&dmn_w32_shared->reg_gen); @@ -2159,6 +2164,10 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) debug_string.size -= 1; } + // rjf: make debug string event + debug_strings_event = dmn_event_list_push(arena, &events); + debug_strings_event->kind = DMN_EventKind_DebugString; + // rjf: push into debug strings str8_list_push(scratch.arena, &debug_strings, debug_string); keep_going = 1; @@ -2205,13 +2214,10 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) //////////////////////// //- rjf: send out event for any remaining debug strings // - if(debug_strings.total_size != 0) + if(debug_strings.total_size != 0 && debug_strings_event != 0) { String8 debug_strings_joined = str8_list_join(arena, &debug_strings, 0); - MemoryZeroStruct(&debug_strings); - DMN_Event *e = dmn_event_list_push(arena, &events); - e->kind = DMN_EventKind_DebugString; - e->string = debug_strings_joined; + debug_strings_event->string = debug_strings_joined; } //////////////////////// diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index c627903c..37438c21 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -1110,6 +1110,16 @@ df_cmd_params_apply_spec_query(Arena *arena, DF_CtrlCtx *ctrl_ctx, DF_CmdParams params->index = u64; df_cmd_params_mark_slot(params, DF_CmdParamSlot_Index); }break; + case DF_CmdParamSlot_BaseUnwindIndex: + { + params->base_unwind_index = u64; + df_cmd_params_mark_slot(params, DF_CmdParamSlot_BaseUnwindIndex); + }break; + case DF_CmdParamSlot_InlineUnwindIndex: + { + params->inline_unwind_index = u64; + df_cmd_params_mark_slot(params, DF_CmdParamSlot_InlineUnwindIndex); + }break; case DF_CmdParamSlot_ID: { params->id = u64; @@ -2853,7 +2863,7 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) Rng1U64 line_vaddr_rng = {0}; { U64 ip_voff = df_voff_from_vaddr(module, ip_vaddr); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, ip_voff); + DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, ip_voff, 0); Rng1U64 line_voff_rng = line_info.voff_range; if(line_voff_rng.max != 0) { @@ -2867,7 +2877,7 @@ df_trap_net_from_thread__step_over_line(Arena *arena, DF_Entity *thread) // is enabled. This is enabled by default normally. { U64 opl_line_voff_rng = df_voff_from_vaddr(module, line_vaddr_rng.max); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, opl_line_voff_rng); + DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, opl_line_voff_rng, 0); if(line_info.pt.line == 0xf00f00 || line_info.pt.line == 0xfeefee) { line_vaddr_rng.max = df_vaddr_from_voff(module, line_info.voff_range.max); @@ -2978,7 +2988,7 @@ df_trap_net_from_thread__step_into_line(Arena *arena, DF_Entity *thread) Rng1U64 line_vaddr_rng = {0}; { U64 ip_voff = df_voff_from_vaddr(module, ip_vaddr); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, ip_voff); + DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, ip_voff, 0); Rng1U64 line_voff_rng = line_info.voff_range; if(line_voff_rng.max != 0) { @@ -2992,7 +3002,7 @@ df_trap_net_from_thread__step_into_line(Arena *arena, DF_Entity *thread) // is enabled. This is enabled by default normally. { U64 opl_line_voff_rng = df_voff_from_vaddr(module, line_vaddr_rng.max); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, opl_line_voff_rng); + DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, opl_line_voff_rng, 0); if(line_info.pt.line == 0xf00f00 || line_info.pt.line == 0xfeefee) { line_vaddr_rng.max = df_vaddr_from_voff(module, line_info.voff_range.max); @@ -3168,20 +3178,20 @@ df_symbol_name_from_dbgi_key_voff(Arena *arena, DI_Key *dbgi_key, U64 voff) Temp scratch = scratch_begin(&arena, 1); DI_Scope *scope = di_scope_open(); RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 0); - if(result.size == 0 && rdi->scope_vmap != 0) + if(result.size == 0) { - U64 scope_idx = rdi_vmap_idx_from_voff(rdi->scope_vmap, rdi->scope_vmap_count, voff); - RDI_Scope *scope = rdi_element_from_idx(rdi, scopes, scope_idx); + U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); U64 proc_idx = scope->proc_idx; - RDI_Procedure *procedure = &rdi->procedures[proc_idx]; + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx); U64 name_size = 0; U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); result = push_str8_copy(arena, str8(name_ptr, name_size)); } - if(result.size == 0 && rdi->global_vmap != 0) + if(result.size == 0) { - U64 global_idx = rdi_vmap_idx_from_voff(rdi->global_vmap, rdi->global_vmap_count, voff); - RDI_GlobalVariable *global_var = rdi_element_from_idx(rdi, global_variables, global_idx); + U64 global_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_GlobalVMap, voff); + RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, global_idx); U64 name_size = 0; U8 *name_ptr = rdi_string_from_idx(rdi, global_var->name_string_idx, &name_size); result = push_str8_copy(arena, str8(name_ptr, name_size)); @@ -3239,21 +3249,18 @@ df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entit U32 src_id = 0; if(rdi != &di_rdi_parsed_nil) { - RDI_NameMap *mapptr = rdi_name_map_from_kind(rdi, RDI_NameMapKind_NormalSourcePaths); - if(mapptr != 0) + RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); + RDI_ParsedNameMap map = {0}; + rdi_parsed_from_name_map(rdi, mapptr, &map); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, file_path_normalized.str, file_path_normalized.size); + if(node != 0) { - RDI_ParsedNameMap map = {0}; - rdi_name_map_parse(rdi, mapptr, &map); - RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, file_path_normalized.str, file_path_normalized.size); - if(node != 0) + U32 id_count = 0; + U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); + if(id_count > 0) { - U32 id_count = 0; - U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); - if(id_count > 0) - { - good_src_id = 1; - src_id = ids[0]; - } + good_src_id = 1; + src_id = ids[0]; } } } @@ -3261,9 +3268,10 @@ df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entit // rjf: good src-id -> look up line info for visible range if(good_src_id) { - RDI_SourceFile *src = rdi->source_files+src_id; - RDI_ParsedLineMap line_map = {0}; - rdi_line_map_from_source_file(rdi, src, &line_map); + RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id); + RDI_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx); + RDI_ParsedSourceLineMap line_map = {0}; + rdi_parsed_from_source_line_map(rdi, src_line_map, &line_map); U64 line_idx = 0; for(S64 line_num = line_num_range.min; line_num <= line_num_range.max; @@ -3275,10 +3283,11 @@ df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entit for(U64 idx = 0; idx < voff_count; idx += 1) { U64 base_voff = voffs[idx]; - U64 unit_idx = rdi_vmap_idx_from_voff(rdi->unit_vmap, rdi->unit_vmap_count, base_voff); - RDI_Unit *unit = &rdi->units[unit_idx]; - RDI_ParsedLineInfo unit_line_info = {0}; - rdi_line_info_from_unit(rdi, unit, &unit_line_info); + U64 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, base_voff); + RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); + RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); + RDI_ParsedLineTable unit_line_info = {0}; + rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff); if(unit_line_info.voffs != 0) { @@ -3310,34 +3319,75 @@ df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entit //- rjf: voff -> src lookups internal DF_TextLineDasm2SrcInfo -df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff) +df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff, U64 inline_unwind_idx) { Temp scratch = scratch_begin(0, 0); DI_Scope *scope = di_scope_open(); RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 0); DF_TextLineDasm2SrcInfo result = {0}; result.file = &df_g_nil_entity; - if(rdi->unit_vmap != 0 && rdi->units != 0 && rdi->source_files != 0) { - U64 unit_idx = rdi_vmap_idx_from_voff(rdi->unit_vmap, rdi->unit_vmap_count, voff); - RDI_Unit *unit = &rdi->units[unit_idx]; - RDI_ParsedLineInfo unit_line_info = {0}; - rdi_line_info_from_unit(rdi, unit, &unit_line_info); - U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, voff); - if(line_info_idx < unit_line_info.count) + RDI_Unit *unit = rdi_unit_from_voff(rdi, voff); + RDI_LineTable *unit_line_table = rdi_line_table_from_unit(rdi, unit); + typedef struct LineTableNode LineTableNode; + struct LineTableNode { - 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]; - String8 file_normalized_full_path = {0}; - file_normalized_full_path.str = rdi_string_from_idx(rdi, file->normal_full_path_string_idx, &file_normalized_full_path.size); - MemoryCopyStruct(&result.dbgi_key, dbgi_key); - if(line->file_idx != 0 && file_normalized_full_path.size != 0) + LineTableNode *next; + RDI_ParsedLineTable parsed_line_table; + }; + LineTableNode start_line_table = {0}; + rdi_parsed_from_line_table(rdi, unit_line_table, &start_line_table.parsed_line_table); + LineTableNode *top_line_table = &start_line_table; + RDI_Scope *scope = rdi_scope_from_voff(rdi, voff); + { + U64 idx = 0; + for(RDI_Scope *s = scope; + s->inline_site_idx != 0 && idx <= inline_unwind_idx; + s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx), idx += 1) { - result.file = df_entity_from_path(file_normalized_full_path, DF_EntityFromPathFlag_All); + if(idx == inline_unwind_idx) + { + RDI_InlineSite *inline_site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx); + if(inline_site->line_table_idx != 0) + { + LineTableNode *n = push_array(scratch.arena, LineTableNode, 1); + SLLStackPush(top_line_table, n); + RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, inline_site->line_table_idx); + rdi_parsed_from_line_table(rdi, line_table, &n->parsed_line_table); + } + break; + } + } + } + for(LineTableNode *n = top_line_table; n == top_line_table; n = n->next) + { + RDI_ParsedLineTable parsed_line_table = n->parsed_line_table; + U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed_line_table, voff); + if(line_info_idx < parsed_line_table.count) + { + RDI_Line *line = &parsed_line_table.lines[line_info_idx]; + RDI_Column *column = (line_info_idx < parsed_line_table.col_count) ? &parsed_line_table.cols[line_info_idx] : 0; + RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx); + String8 file_normalized_full_path = {0}; + file_normalized_full_path.str = rdi_string_from_idx(rdi, file->normal_full_path_string_idx, &file_normalized_full_path.size); + MemoryCopyStruct(&result.dbgi_key, dbgi_key); + if(line->file_idx != 0 && file_normalized_full_path.size != 0) + { + result.file = df_entity_from_path(file_normalized_full_path, DF_EntityFromPathFlag_All); + } + result.pt = txt_pt(line->line_num, column ? column->col_first : 1); + result.voff_range = r1u64(parsed_line_table.voffs[line_info_idx], parsed_line_table.voffs[line_info_idx+1]); + } + } + for(LineTableNode *n = top_line_table->next; n != 0; n = n->next) + { + RDI_ParsedLineTable parsed_line_table = n->parsed_line_table; + U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed_line_table, voff); + if(line_info_idx < parsed_line_table.count) + { + Rng1U64 voff_range = r1u64(parsed_line_table.voffs[line_info_idx], parsed_line_table.voffs[line_info_idx+1]); + result.voff_range = intersect_1u64(result.voff_range, voff_range); } - result.pt = txt_pt(line->line_num, column ? column->col_first : 1); - result.voff_range = r1u64(unit_line_info.voffs[line_info_idx], unit_line_info.voffs[line_info_idx+1]); } } di_scope_close(scope); @@ -3368,9 +3418,9 @@ df_voff_from_dbgi_key_symbol_name(DI_Key *dbgi_key, String8 symbol_name) name_map_kind_idx += 1) { RDI_NameMapKind name_map_kind = name_map_kinds[name_map_kind_idx]; - RDI_NameMap *name_map = rdi_name_map_from_kind(rdi, name_map_kind); + RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, name_map_kind); RDI_ParsedNameMap parsed_name_map = {0}; - rdi_name_map_parse(rdi, name_map, &parsed_name_map); + rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, symbol_name.str, symbol_name.size); // rjf: node -> num @@ -3402,14 +3452,14 @@ df_voff_from_dbgi_key_symbol_name(DI_Key *dbgi_key, String8 symbol_name) default:{}break; case RDI_NameMapKind_GlobalVariables: { - RDI_GlobalVariable *global_var = rdi_element_from_idx(rdi, global_variables, entity_num-1); + RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, entity_num-1); voff = global_var->voff; }break; case RDI_NameMapKind_Procedures: { - RDI_Procedure *procedure = rdi_element_from_idx(rdi, procedures, entity_num-1); - RDI_Scope *scope = rdi_element_from_idx(rdi, scopes, procedure->root_scope_idx); - voff = rdi->scope_voffs[scope->voff_range_first]; + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, entity_num-1); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx); + voff = *rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_first); }break; } @@ -3436,9 +3486,9 @@ df_type_num_from_dbgi_key_name(DI_Key *dbgi_key, String8 name) U64 result = 0; { RDI_Parsed *rdi = di_rdi_from_key(scope, dbgi_key, 0); - RDI_NameMap *name_map = rdi_name_map_from_kind(rdi, RDI_NameMapKind_Types); + RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Types); RDI_ParsedNameMap parsed_name_map = {0}; - rdi_name_map_parse(rdi, name_map, &parsed_name_map); + rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, name.str, name.size); U64 entity_num = 0; if(node != 0) @@ -3655,6 +3705,83 @@ df_module_from_thread_candidates(DF_Entity *thread, DF_EntityList *candidates) return module; } +internal DF_Unwind +df_unwind_from_ctrl_unwind(Arena *arena, DI_Scope *di_scope, DF_Entity *process, CTRL_Unwind *base_unwind) +{ + Temp scratch = scratch_begin(&arena, 1); + DF_UnwindFrameList rich_frames_list = {0}; + Architecture arch = df_architecture_from_entity(process); + for(U64 base_frame_idx = 0; base_frame_idx < base_unwind->frames.count; base_frame_idx += 1) + { + CTRL_UnwindFrame *base_frame = &base_unwind->frames.v[base_frame_idx]; + U64 rip_vaddr = regs_rip_from_arch_block(arch, base_frame->regs); + DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); + U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr); + DI_Key dbgi_key = df_dbgi_key_from_module(module); + RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 0); + RDI_Scope *scope = rdi_scope_from_voff(rdi, rip_voff); + + // rjf: add rich frames for inlines + U64 inline_unwind_idx = 0; + for(RDI_Scope *s = scope; s->inline_site_idx != 0; s = rdi_element_from_name_idx(rdi, Scopes, s->parent_scope_idx)) + { + RDI_InlineSite *site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx); + DF_UnwindFrameNode *n = push_array(scratch.arena, DF_UnwindFrameNode, 1); + SLLQueuePush(rich_frames_list.first, rich_frames_list.last, n); + rich_frames_list.count += 1; + n->v.regs = base_frame->regs; + n->v.rdi = rdi; + n->v.procedure = 0; + n->v.inline_site = site; + n->v.base_unwind_idx = base_frame_idx; + n->v.inline_unwind_idx = inline_unwind_idx; + inline_unwind_idx += 1; + } + + // rjf: add frame for concrete frame + DF_UnwindFrameNode *n = push_array(scratch.arena, DF_UnwindFrameNode, 1); + SLLQueuePush(rich_frames_list.first, rich_frames_list.last, n); + rich_frames_list.count += 1; + n->v.regs = base_frame->regs; + n->v.rdi = rdi; + n->v.procedure = rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx); + n->v.inline_site = 0; + n->v.base_unwind_idx = base_frame_idx; + n->v.inline_unwind_idx = inline_unwind_idx; + inline_unwind_idx = 0; + } + DF_Unwind result = {0}; + { + result.frames.count = rich_frames_list.count; + result.frames.v = push_array(arena, DF_UnwindFrame, result.frames.count); + U64 idx = 0; + for(DF_UnwindFrameNode *n = rich_frames_list.first; n != 0; n = n->next, idx += 1) + { + MemoryCopyStruct(&result.frames.v[idx], &n->v); + } + } + scratch_end(scratch); + return result; +} + +internal DF_UnwindFrame * +df_frame_from_unwind_idxs(DF_Unwind *unwind, U64 base_unwind_idx, U64 inline_unwind_idx) +{ + DF_UnwindFrame *f = 0; + for(U64 idx = 0; idx < unwind->frames.count; idx += 1) + { + if(unwind->frames.v[idx].base_unwind_idx == base_unwind_idx) + { + f = &unwind->frames.v[idx]; + if(unwind->frames.v[idx].inline_unwind_idx == inline_unwind_idx) + { + break; + } + } + } + return f; +} + //////////////////////////////// //~ rjf: Entity -> Log Entities @@ -3831,6 +3958,7 @@ df_ctrl_run(DF_RunKind run, DF_Entity *run_thread, CTRL_RunFlags flags, CTRL_Tra // rjf: set control context to top unwind df_state->ctrl_ctx.unwind_count = 0; + df_state->ctrl_ctx.inline_unwind_count = 0; scratch_end(scratch); } @@ -3925,21 +4053,18 @@ df_eval_parse_ctx_from_src_loc(DI_Scope *scope, DF_Entity *file, TxtPt pt) B32 good_src_id = 0; U32 src_id = 0; { - RDI_NameMap *mapptr = rdi_name_map_from_kind(rdi, RDI_NameMapKind_NormalSourcePaths); - if(mapptr != 0) + RDI_NameMap *mapptr = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); + RDI_ParsedNameMap map = {0}; + rdi_parsed_from_name_map(rdi, mapptr, &map); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, file_path_normalized.str, file_path_normalized.size); + if(node != 0) { - RDI_ParsedNameMap map = {0}; - rdi_name_map_parse(rdi, mapptr, &map); - RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map, file_path_normalized.str, file_path_normalized.size); - if(node != 0) + U32 id_count = 0; + U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); + if(id_count > 0) { - U32 id_count = 0; - U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); - if(id_count > 0) - { - good_src_id = 1; - src_id = ids[0]; - } + good_src_id = 1; + src_id = ids[0]; } } } @@ -3947,18 +4072,20 @@ df_eval_parse_ctx_from_src_loc(DI_Scope *scope, DF_Entity *file, TxtPt pt) // rjf: good src-id -> look up line info for visible range if(good_src_id) { - RDI_SourceFile *src = rdi->source_files+src_id; - RDI_ParsedLineMap line_map = {0}; - rdi_line_map_from_source_file(rdi, src, &line_map); + RDI_SourceFile *src = rdi_element_from_name_idx(rdi, SourceFiles, src_id); + RDI_SourceLineMap *src_line_map = rdi_element_from_name_idx(rdi, SourceLineMaps, src->source_line_map_idx); + RDI_ParsedSourceLineMap line_map = {0}; + rdi_parsed_from_source_line_map(rdi, src_line_map, &line_map); U32 voff_count = 0; U64 *voffs = rdi_line_voffs_from_num(&line_map, (U32)pt.line, &voff_count); for(U64 idx = 0; idx < voff_count; idx += 1) { U64 base_voff = voffs[idx]; - U64 unit_idx = rdi_vmap_idx_from_voff(rdi->unit_vmap, rdi->unit_vmap_count, base_voff); - RDI_Unit *unit = &rdi->units[unit_idx]; - RDI_ParsedLineInfo unit_line_info = {0}; - rdi_line_info_from_unit(rdi, unit, &unit_line_info); + U64 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, base_voff); + RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); + RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); + RDI_ParsedLineTable unit_line_info = {0}; + rdi_parsed_from_line_table(rdi, line_table, &unit_line_info); U64 line_info_idx = rdi_line_info_idx_from_voff(&unit_line_info, base_voff); 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; @@ -4265,12 +4392,12 @@ df_dynamically_typed_eval_from_eval(TG_Graph *graph, RDI_Parsed *rdi, DF_CtrlCtx U64 vtable_vaddr = 0; MemoryCopy(&vtable_vaddr, vtable_base_ptr_memory.str, addr_size); U64 vtable_voff = df_voff_from_vaddr(module, vtable_vaddr); - U64 global_idx = rdi_vmap_idx_from_voff(rdi->global_vmap, rdi->global_vmap_count, vtable_voff); - RDI_GlobalVariable *global_var = rdi_element_from_idx(rdi, global_variables, global_idx); + U64 global_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_GlobalVMap, vtable_voff); + RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, global_idx); if(global_var->link_flags & RDI_LinkFlag_TypeScoped) { - RDI_UDT *udt = rdi_element_from_idx(rdi, udts, global_var->container_idx); - RDI_TypeNode *type = rdi_element_from_idx(rdi, type_nodes, udt->self_type_idx); + RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, global_var->container_idx); + RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); TG_Key derived_type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type->kind), (U64)udt->self_type_idx); TG_Key ptr_to_derived_type_key = tg_cons_type_make(graph, TG_Kind_Ptr, derived_type_key, 0); eval.type_key = ptr_to_derived_type_key; @@ -5654,6 +5781,7 @@ df_ctrl_ctx_apply_overrides(DF_CtrlCtx *ctx, DF_CtrlCtx *overrides) { ctx->thread = overrides->thread; ctx->unwind_count = overrides->unwind_count; + ctx->inline_unwind_count = overrides->inline_unwind_count; } } @@ -6455,13 +6583,15 @@ df_push_cmd__root(DF_CmdParams *params, DF_CmdSpec *spec) { log_infof("| cmd_spec: \"%S\"\n", params->cmd_spec->info.string); } - if(params->string.size != 0) { log_infof("| string: \"%S\"\n", params->string); } - if(params->file_path.size != 0) { log_infof("| file_path: \"%S\"\n", params->file_path); } - if(params->text_point.line != 0){ log_infof("| text_point: [line:%I64d, col:%I64d]\n", params->text_point.line, params->text_point.column); } - if(params->vaddr != 0) { log_infof("| vaddr: 0x%I64x\n", params->vaddr); } - if(params->voff != 0) { log_infof("| voff: 0x%I64x\n", params->voff); } - if(params->index != 0) { log_infof("| index: 0x%I64x\n", params->index); } - if(params->id != 0) { log_infof("| id: 0x%I64x\n", params->id); } + if(params->string.size != 0) { log_infof("| string: \"%S\"\n", params->string); } + if(params->file_path.size != 0) { log_infof("| file_path: \"%S\"\n", params->file_path); } + if(params->text_point.line != 0) { log_infof("| text_point: [line:%I64d, col:%I64d]\n", params->text_point.line, params->text_point.column); } + if(params->vaddr != 0) { log_infof("| vaddr: 0x%I64x\n", params->vaddr); } + if(params->voff != 0) { log_infof("| voff: 0x%I64x\n", params->voff); } + if(params->index != 0) { log_infof("| index: 0x%I64x\n", params->index); } + if(params->base_unwind_index != 0) { log_infof("| base_unwind_index: 0x%I64x\n", params->base_unwind_index); } + if(params->inline_unwind_index != 0){ log_infof("| inline_unwind_index: 0x%I64x\n", params->inline_unwind_index); } + if(params->id != 0) { log_infof("| id: 0x%I64x\n", params->id); } if(params->os_event != 0) { String8 kind_string = str8_lit(""); @@ -6735,7 +6865,7 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) DF_Entity *module = df_module_from_process_vaddr(process, stop_thread_vaddr); DI_Key dbgi_key = df_dbgi_key_from_module(module); U64 stop_thread_voff = df_voff_from_vaddr(module, stop_thread_vaddr); - DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, stop_thread_voff); + DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, stop_thread_voff, 0); DF_EntityList user_bps = df_query_cached_entity_list_with_kind(DF_EntityKind_Breakpoint); for(DF_EntityNode *n = user_bps.first; n != 0; n = n->next) { @@ -7567,32 +7697,72 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) //- rjf: debug control context management operations case DF_CoreCmdKind_SelectThread: { + MemoryZeroStruct(&df_state->ctrl_ctx); df_state->ctrl_ctx.thread = params.entity; - df_state->ctrl_ctx.unwind_count = 0; }break; case DF_CoreCmdKind_SelectUnwind: { + DI_Scope *di_scope = di_scope_open(); DF_Entity *thread = df_entity_from_handle(df_state->ctrl_ctx.thread); - CTRL_Unwind unwind = df_query_cached_unwind_from_thread(thread); - U64 max_unwind = unwind.frames.count ? unwind.frames.count-1 : 0; - U64 index = Clamp(0, params.index, max_unwind); - df_state->ctrl_ctx.unwind_count = index; + DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); + CTRL_Unwind base_unwind = df_query_cached_unwind_from_thread(thread); + DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind); + DF_UnwindFrame *frame = df_frame_from_unwind_idxs(&rich_unwind, params.base_unwind_index, params.inline_unwind_index); + if(frame != 0) + { + df_state->ctrl_ctx.unwind_count = frame->base_unwind_idx; + df_state->ctrl_ctx.inline_unwind_count = frame->inline_unwind_idx; + } + di_scope_close(di_scope); }break; case DF_CoreCmdKind_UpOneFrame: - { - DF_CtrlCtx ctrl_ctx = df_ctrl_ctx(); - DF_CmdParams p = params; - p.index = (ctrl_ctx.unwind_count > 0 ? ctrl_ctx.unwind_count - 1 : 0); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Index); - df_cmd_list_push(arena, cmds, &p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); - }break; case DF_CoreCmdKind_DownOneFrame: { DF_CtrlCtx ctrl_ctx = df_ctrl_ctx(); - DF_CmdParams p = params; - p.index = ctrl_ctx.unwind_count+1; - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Index); - df_cmd_list_push(arena, cmds, &p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); + DI_Scope *di_scope = di_scope_open(); + DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread); + DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); + CTRL_Unwind base_unwind = df_query_cached_unwind_from_thread(thread); + DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind); + DF_UnwindFrame *current_frame = 0; + for(U64 idx = 0; idx < rich_unwind.frames.count; idx += 1) + { + if(rich_unwind.frames.v[idx].base_unwind_idx == ctrl_ctx.unwind_count && + rich_unwind.frames.v[idx].inline_unwind_idx == ctrl_ctx.inline_unwind_count) + { + current_frame = &rich_unwind.frames.v[idx]; + break; + } + } + if(current_frame == 0 && rich_unwind.frames.count != 0) + { + current_frame = &rich_unwind.frames.v[0]; + } + DF_UnwindFrame *next_frame = current_frame; + switch(core_cmd_kind) + { + default:{}break; + case DF_CoreCmdKind_UpOneFrame: + if(current_frame != 0 && (current_frame - rich_unwind.frames.v) > 0) + { + next_frame -= 1; + }break; + case DF_CoreCmdKind_DownOneFrame: + if(current_frame != 0 && (current_frame - rich_unwind.frames.v)+1 < rich_unwind.frames.count) + { + next_frame += 1; + }break; + } + if(next_frame != 0) + { + DF_CmdParams p = params; + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_InlineUnwindIndex); + p.base_unwind_index = next_frame->base_unwind_idx; + p.inline_unwind_index = next_frame->base_unwind_idx; + df_cmd_list_push(arena, cmds, &p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); + } + di_scope_close(di_scope); }break; case DF_CoreCmdKind_FreezeThread: case DF_CoreCmdKind_ThawThread: diff --git a/src/df/core/df_core.h b/src/df/core/df_core.h index a8a72850..f4c8029e 100644 --- a/src/df/core/df_core.h +++ b/src/df/core/df_core.h @@ -77,6 +77,7 @@ struct DF_CtrlCtx { DF_Handle thread; U64 unwind_count; + U64 inline_unwind_count; }; //////////////////////////////// @@ -516,6 +517,48 @@ struct DF_EntityFuzzyItemArray U64 count; }; +//////////////////////////////// +//~ rjf: Rich (Including Inline) Unwind Types + +typedef struct DF_UnwindFrame DF_UnwindFrame; +struct DF_UnwindFrame +{ + void *regs; + RDI_Parsed *rdi; + RDI_Procedure *procedure; + RDI_InlineSite *inline_site; + U64 base_unwind_idx; + U64 inline_unwind_idx; +}; + +typedef struct DF_UnwindFrameNode DF_UnwindFrameNode; +struct DF_UnwindFrameNode +{ + DF_UnwindFrameNode *next; + DF_UnwindFrame v; +}; + +typedef struct DF_UnwindFrameList DF_UnwindFrameList; +struct DF_UnwindFrameList +{ + DF_UnwindFrameNode *first; + DF_UnwindFrameNode *last; + U64 count; +}; + +typedef struct DF_UnwindFrameArray DF_UnwindFrameArray; +struct DF_UnwindFrameArray +{ + DF_UnwindFrame *v; + U64 count; +}; + +typedef struct DF_Unwind DF_Unwind; +struct DF_Unwind +{ + DF_UnwindFrameArray frames; +}; + //////////////////////////////// //~ rjf: Source <-> Disasm Types @@ -1545,7 +1588,7 @@ internal String8 df_symbol_name_from_process_vaddr(Arena *arena, DF_Entity *proc internal DF_TextLineSrc2DasmInfoListArray df_text_line_src2dasm_info_list_array_from_src_line_range(Arena *arena, DF_Entity *file, Rng1S64 line_num_range); //- rjf: voff -> src lookups -internal DF_TextLineDasm2SrcInfo df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff); +internal DF_TextLineDasm2SrcInfo df_text_line_dasm2src_info_from_dbgi_key_voff(DI_Key *dbgi_key, U64 voff, U64 inline_unwind_idx); //- rjf: symbol -> voff lookups internal U64 df_voff_from_dbgi_key_symbol_name(DI_Key *dbgi_key, String8 symbol_name); @@ -1562,6 +1605,8 @@ internal EVAL_String2NumMap *df_push_locals_map_from_dbgi_key_voff(Arena *arena, internal EVAL_String2NumMap *df_push_member_map_from_dbgi_key_voff(Arena *arena, DI_Scope *scope, DI_Key *dbgi_key, U64 voff); internal B32 df_set_thread_rip(DF_Entity *thread, U64 vaddr); internal DF_Entity *df_module_from_thread_candidates(DF_Entity *thread, DF_EntityList *candidates); +internal DF_Unwind df_unwind_from_ctrl_unwind(Arena *arena, DI_Scope *di_scope, DF_Entity *process, CTRL_Unwind *base_unwind); +internal DF_UnwindFrame *df_frame_from_unwind_idxs(DF_Unwind *unwind, U64 base_unwind_idx, U64 inline_unwind_idx); //////////////////////////////// //~ rjf: Entity -> Log Entities diff --git a/src/df/core/df_core.mdesk b/src/df/core/df_core.mdesk index 55af7f03..c10743c3 100644 --- a/src/df/core/df_core.mdesk +++ b/src/df/core/df_core.mdesk @@ -96,6 +96,8 @@ DF_CmdParamSlotTable: {PreferDisassembly prefer_dasm `B32`} {ForceConfirm force_confirm `B32`} {Dir2 dir2 `Dir2`} + {BaseUnwindIndex base_unwind_index `U64`} + {InlineUnwindIndex inline_unwind_index `U64`} } @table(name lister_omit q_slot q_ent_kind q_allow_files q_allow_folders q_keep_oi q_select_oi q_is_code q_required canonical_icon string display_name desc search_tags ) diff --git a/src/df/core/generated/df_core.meta.c b/src/df/core/generated/df_core.meta.c index ff75bd24..3a6bad7e 100644 --- a/src/df/core/generated/df_core.meta.c +++ b/src/df/core/generated/df_core.meta.c @@ -4,7 +4,7 @@ //- GENERATED CODE C_LINKAGE_BEGIN -Rng1U64 df_g_cmd_param_slot_range_table[22] = +Rng1U64 df_g_cmd_param_slot_range_table[24] = { {0}, {OffsetOf(DF_CmdParams, window), OffsetOf(DF_CmdParams, window) + sizeof(DF_Handle)}, @@ -28,6 +28,8 @@ Rng1U64 df_g_cmd_param_slot_range_table[22] = {OffsetOf(DF_CmdParams, prefer_dasm), OffsetOf(DF_CmdParams, prefer_dasm) + sizeof(B32)}, {OffsetOf(DF_CmdParams, force_confirm), OffsetOf(DF_CmdParams, force_confirm) + sizeof(B32)}, {OffsetOf(DF_CmdParams, dir2), OffsetOf(DF_CmdParams, dir2) + sizeof(Dir2)}, +{OffsetOf(DF_CmdParams, base_unwind_index), OffsetOf(DF_CmdParams, base_unwind_index) + sizeof(U64)}, +{OffsetOf(DF_CmdParams, inline_unwind_index), OffsetOf(DF_CmdParams, inline_unwind_index) + sizeof(U64)}, }; DF_IconKind df_g_entity_kind_icon_kind_table[26] = diff --git a/src/df/core/generated/df_core.meta.h b/src/df/core/generated/df_core.meta.h index be5c9d1f..28819624 100644 --- a/src/df/core/generated/df_core.meta.h +++ b/src/df/core/generated/df_core.meta.h @@ -394,6 +394,8 @@ DF_CmdParamSlot_ID, DF_CmdParamSlot_PreferDisassembly, DF_CmdParamSlot_ForceConfirm, DF_CmdParamSlot_Dir2, +DF_CmdParamSlot_BaseUnwindIndex, +DF_CmdParamSlot_InlineUnwindIndex, DF_CmdParamSlot_COUNT, } DF_CmdParamSlot; @@ -422,6 +424,8 @@ U64 id; B32 prefer_dasm; B32 force_confirm; Dir2 dir2; +U64 base_unwind_index; +U64 inline_unwind_index; }; DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_DEF(array); @@ -1534,7 +1538,7 @@ struct {B32 *value_ptr; String8 name;} DEV_toggle_table[] = {&DEV_updating_indicator, str8_lit_comp("updating_indicator")}, }; C_LINKAGE_BEGIN -extern Rng1U64 df_g_cmd_param_slot_range_table[22]; +extern Rng1U64 df_g_cmd_param_slot_range_table[24]; extern DF_IconKind df_g_entity_kind_icon_kind_table[26]; extern String8 df_g_entity_kind_display_string_table[26]; extern String8 df_g_entity_kind_name_label_table[26]; diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index 99931256..7e9c5994 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -522,13 +522,15 @@ df_cmd_params_from_window(DF_Window *window) df_cmd_params_mark_slot(&p, DF_CmdParamSlot_View); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_PreferDisassembly); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_InlineUnwindIndex); p.window = df_handle_from_window(window); p.panel = df_handle_from_panel(window->focused_panel); p.view = df_handle_from_view(df_selected_tab_from_panel(window->focused_panel)); p.prefer_dasm = df_prefer_dasm_from_window(window); p.entity = ctrl_ctx.thread; - p.index = ctrl_ctx.unwind_count; + p.base_unwind_index = ctrl_ctx.unwind_count; + p.inline_unwind_index = ctrl_ctx.inline_unwind_count; return p; } @@ -542,13 +544,15 @@ df_cmd_params_from_panel(DF_Window *window, DF_Panel *panel) df_cmd_params_mark_slot(&p, DF_CmdParamSlot_View); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_PreferDisassembly); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_InlineUnwindIndex); p.window = df_handle_from_window(window); p.panel = df_handle_from_panel(panel); p.view = df_handle_from_view(df_selected_tab_from_panel(panel)); p.prefer_dasm = df_prefer_dasm_from_window(window); p.entity = ctrl_ctx.thread; - p.index = ctrl_ctx.unwind_count; + p.base_unwind_index = ctrl_ctx.unwind_count; + p.inline_unwind_index = ctrl_ctx.inline_unwind_count; return p; } @@ -562,13 +566,15 @@ df_cmd_params_from_view(DF_Window *window, DF_Panel *panel, DF_View *view) df_cmd_params_mark_slot(&p, DF_CmdParamSlot_View); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_PreferDisassembly); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Entity); - df_cmd_params_mark_slot(&p, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_InlineUnwindIndex); p.window = df_handle_from_window(window); p.panel = df_handle_from_panel(panel); p.view = df_handle_from_view(view); p.prefer_dasm = df_prefer_dasm_from_window(window); p.entity = ctrl_ctx.thread; - p.index = ctrl_ctx.unwind_count; + p.base_unwind_index = ctrl_ctx.unwind_count; + p.inline_unwind_index = ctrl_ctx.inline_unwind_count; return p; } @@ -635,24 +641,18 @@ df_queue_drag_drop(void) } internal void -df_set_hovered_line_info(DI_Key *dbgi_key, U64 voff) +df_set_rich_hover_info(DF_RichHoverInfo *info) { - arena_clear(df_gfx_state->hover_line_arena); - df_gfx_state->hover_line_dbgi_key = di_key_copy(df_gfx_state->hover_line_arena, dbgi_key); - df_gfx_state->hover_line_voff = voff; - df_gfx_state->hover_line_set_this_frame = 1; + arena_clear(df_gfx_state->rich_hover_info_next_arena); + MemoryCopyStruct(&df_gfx_state->rich_hover_info_next, info); + df_gfx_state->rich_hover_info_next.dbgi_key = di_key_copy(df_gfx_state->rich_hover_info_next_arena, &info->dbgi_key); } -internal DI_Key -df_get_hovered_line_info_dbgi_key(void) +internal DF_RichHoverInfo +df_get_rich_hover_info(void) { - return df_gfx_state->hover_line_dbgi_key; -} - -internal U64 -df_get_hovered_line_info_voff(void) -{ - return df_gfx_state->hover_line_voff; + DF_RichHoverInfo info = df_gfx_state->rich_hover_info_current; + return info; } //////////////////////////////// @@ -1264,8 +1264,8 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) case DF_CoreCmdKind_SelectThread:goto thread_locator; case DF_CoreCmdKind_SelectThreadWindow: { + MemoryZeroStruct(&ws->ctrl_ctx_overrides); ws->ctrl_ctx_overrides.thread = params.entity; - ws->ctrl_ctx_overrides.unwind_count = 0; }goto thread_locator; case DF_CoreCmdKind_SelectThreadView: { @@ -1277,8 +1277,8 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) } if(!df_view_is_nil(view)) { + MemoryZeroStruct(&view->ctrl_ctx_overrides); view->ctrl_ctx_overrides.thread = params.entity; - view->ctrl_ctx_overrides.unwind_count = 0; } }goto thread_locator; case DF_CoreCmdKind_SelectUnwind: @@ -2598,11 +2598,12 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) { DI_Scope *scope = di_scope_open(); DF_Entity *thread = df_entity_from_handle(params.entity); - U64 unwind_count = params.index; + U64 base_unwind_index = params.base_unwind_index; + U64 inline_unwind_index = params.inline_unwind_index; if(thread->kind == DF_EntityKind_Thread) { // rjf: grab rip - U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_count); + U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, base_unwind_index); // rjf: extract thread/rip info DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); @@ -2610,7 +2611,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) DI_Key dbgi_key = df_dbgi_key_from_module(module); RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff); + DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff, inline_unwind_index); // rjf: snap to resolved line B32 missing_rip = (rip_vaddr == 0); @@ -2632,11 +2633,12 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) params.entity = df_handle_from_entity(thread); params.voff = rip_voff; params.vaddr = rip_vaddr; - params.index = unwind_count; + params.base_unwind_index = base_unwind_index; + params.inline_unwind_index = inline_unwind_index; df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualOff); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualAddr); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); df_cmd_list_push(arena, cmds, ¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation)); } @@ -2647,7 +2649,8 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) params.entity = df_handle_from_entity(thread); params.voff = rip_voff; params.vaddr = rip_vaddr; - params.index = unwind_count; + params.base_unwind_index = base_unwind_index; + params.inline_unwind_index = inline_unwind_index; df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualOff); df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_VirtualAddr); @@ -2669,9 +2672,11 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) DF_Entity *selected_thread = df_entity_from_handle(ctrl_ctx.thread); DF_CmdParams params = df_cmd_params_from_window(ws); params.entity = df_handle_from_entity(selected_thread); - params.index = ctrl_ctx.unwind_count; + params.base_unwind_index = ctrl_ctx.unwind_count; + params.inline_unwind_index = ctrl_ctx.inline_unwind_count; df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Entity); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineUnwindIndex); df_cmd_list_push(arena, cmds, ¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindThread)); }break; @@ -2804,7 +2809,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) // rjf: name resolved to voff * dbg info if(name_resolved != 0 && voff != 0) { - DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&voff_dbgi_key, voff); + DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&voff_dbgi_key, voff, 0); DF_CmdParams p = params; { p.file_path = df_full_path_from_entity(scratch.arena, dasm2src_info.file); @@ -4100,24 +4105,37 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) { if(ui_clicked(df_icon_buttonf(DF_IconKind_Clipboard, 0, "Copy Call Stack"))) { + DI_Scope *di_scope = di_scope_open(); DF_Entity *process = df_entity_ancestor_from_kind(entity, DF_EntityKind_Process); - CTRL_Unwind unwind = df_query_cached_unwind_from_thread(entity); + CTRL_Unwind base_unwind = df_query_cached_unwind_from_thread(entity); + DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind); String8List lines = {0}; - for(U64 frame_idx = 0; frame_idx < unwind.frames.count; frame_idx += 1) + for(U64 frame_idx = 0; frame_idx < rich_unwind.frames.count; frame_idx += 1) { - U64 rip_vaddr = regs_rip_from_arch_block(entity->arch, unwind.frames.v[frame_idx].regs); + U64 rip_vaddr = regs_rip_from_arch_block(entity->arch, rich_unwind.frames.v[frame_idx].regs); DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); - DI_Key dbgi_key = df_dbgi_key_from_module(module); - U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr); - String8 symbol = df_symbol_name_from_dbgi_key_voff(scratch.arena, &dbgi_key, rip_voff); - if(symbol.size != 0) + RDI_Parsed *rdi = rich_unwind.frames.v[frame_idx].rdi; + RDI_Procedure *procedure = rich_unwind.frames.v[frame_idx].procedure; + RDI_InlineSite *inline_site = rich_unwind.frames.v[frame_idx].inline_site; + if(procedure != 0) { - str8_list_pushf(scratch.arena, &lines, "0x%I64x: %S", rip_vaddr, symbol); + String8 name = {0}; + name.str = rdi_name_from_procedure(rdi, procedure, &name.size); + str8_list_pushf(scratch.arena, &lines, "0x%I64x: \"%S\"%s%S", rip_vaddr, name, df_entity_is_nil(module) ? "" : " in ", module->name); + } + else if(inline_site != 0) + { + String8 name = {0}; + name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size); + str8_list_pushf(scratch.arena, &lines, "0x%I64x: [inlined] \"%S\"%s%S", rip_vaddr, name, df_entity_is_nil(module) ? "" : " in ", module->name); + } + else if(!df_entity_is_nil(module)) + { + str8_list_pushf(scratch.arena, &lines, "0x%I64x: [??? in %S]", rip_vaddr, module->name); } else { - String8 module_filename = str8_skip_last_slash(module->name); - str8_list_pushf(scratch.arena, &lines, "0x%I64x: [??? in %S]", rip_vaddr, module_filename); + str8_list_pushf(scratch.arena, &lines, "0x%I64x: [??? in ???]", rip_vaddr); } } StringJoin join = {0}; @@ -4125,6 +4143,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) String8 text = str8_list_join(scratch.arena, &lines, &join); os_set_clipboard_text(text); ui_ctx_menu_close(); + di_scope_close(di_scope); } } @@ -10079,29 +10098,51 @@ df_entity_tooltips(DF_Entity *entity) UI_PrefWidth(ui_text_dim(10, 1)) ui_label(arch_str); } ui_spacer(ui_em(1.5f, 1.f)); + DI_Scope *di_scope = di_scope_open(); DF_Entity *process = df_entity_ancestor_from_kind(entity, DF_EntityKind_Process); - CTRL_Unwind unwind = df_query_cached_unwind_from_thread(entity); - for(U64 idx = 0; idx < unwind.frames.count; idx += 1) + CTRL_Unwind base_unwind = df_query_cached_unwind_from_thread(entity); + DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind); + for(U64 idx = 0; idx < rich_unwind.frames.count; idx += 1) { - U64 rip_vaddr = regs_rip_from_arch_block(entity->arch, unwind.frames.v[idx].regs); + DF_UnwindFrame *f = &rich_unwind.frames.v[idx]; + RDI_Parsed *rdi = f->rdi; + RDI_Procedure *procedure = f->procedure; + RDI_InlineSite *inline_site = f->inline_site; + U64 rip_vaddr = regs_rip_from_arch_block(entity->arch, f->regs); DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); - DI_Key dbgi_key = df_dbgi_key_from_module(module); - U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr); - String8 symbol = df_symbol_name_from_dbgi_key_voff(scratch.arena, &dbgi_key, rip_voff); + String8 module_name = df_entity_is_nil(module) ? str8_lit("???") : str8_skip_last_slash(module->name); + String8 name = {0}; + String8 info = {0}; + if(procedure != 0) + { + name.str = rdi_name_from_procedure(rdi, procedure, &name.size); + } + else if(inline_site != 0) + { + name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size); + info = str8_lit("[inlined]"); + } UI_PrefWidth(ui_children_sum(1)) UI_Row { UI_Font(df_font_from_slot(DF_FontSlot_Code)) UI_PrefWidth(ui_em(18.f, 1.f)) UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText)) ui_labelf("0x%I64x", rip_vaddr); - if(symbol.size != 0) + if(info.size != 0) { - UI_Font(df_font_from_slot(DF_FontSlot_Code)) UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_CodeFunction)) UI_PrefWidth(ui_text_dim(10, 1)) ui_labelf("%S", symbol); + UI_Font(df_font_from_slot(DF_FontSlot_Code)) UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText)) UI_PrefWidth(ui_text_dim(10, 1)) ui_label(info); + } + if(name.size != 0) + { + UI_Font(df_font_from_slot(DF_FontSlot_Code))UI_PrefWidth(ui_text_dim(10, 1)) + { + df_code_label(1.f, 0, df_rgba_from_theme_color(DF_ThemeColor_CodeFunction), name); + } } else { - String8 module_filename = str8_skip_last_slash(module->name); - UI_Font(df_font_from_slot(DF_FontSlot_Code)) UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText)) UI_PrefWidth(ui_text_dim(10, 1)) ui_labelf("[??? in %S]", module_filename); + UI_Font(df_font_from_slot(DF_FontSlot_Code)) UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText)) UI_PrefWidth(ui_text_dim(10, 1)) ui_labelf("[??? in %S]", module_name); } } } + di_scope_close(di_scope); }break; case DF_EntityKind_Breakpoint: UI_Flags(0) UI_Tooltip UI_PrefWidth(ui_text_dim(10, 1)) @@ -11566,11 +11607,23 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ if(params->line_src2dasm[line_slice_idx].first != 0 && params->line_src2dasm[line_slice_idx].first->v.remap_line == mouse_pt.line) { - df_set_hovered_line_info(¶ms->line_src2dasm[line_slice_idx].first->v.dbgi_key, params->line_src2dasm[line_slice_idx].first->v.voff_range.min); + DF_RichHoverInfo info = {0}; + info.process = df_handle_from_entity(selected_thread_process); + info.vaddr_range = df_vaddr_range_from_voff_range(selected_thread_module, params->line_src2dasm[line_slice_idx].first->v.voff_range); + info.module = df_handle_from_entity(selected_thread_module); + info.dbgi_key = params->line_src2dasm[line_slice_idx].first->v.dbgi_key; + info.voff_range = params->line_src2dasm[line_slice_idx].first->v.voff_range; + df_set_rich_hover_info(&info); } if(params->line_dasm2src[line_slice_idx].first != 0) { - df_set_hovered_line_info(¶ms->line_dasm2src[line_slice_idx].first->v.dbgi_key, params->line_dasm2src[line_slice_idx].first->v.voff_range.min); + DF_RichHoverInfo info = {0}; + info.process = df_handle_from_entity(selected_thread_process); + info.vaddr_range = df_vaddr_range_from_voff_range(selected_thread_module, params->line_dasm2src[line_slice_idx].first->v.voff_range); + info.module = df_handle_from_entity(selected_thread_module); + info.dbgi_key = params->line_dasm2src[line_slice_idx].first->v.dbgi_key; + info.voff_range = params->line_dasm2src[line_slice_idx].first->v.voff_range; + df_set_rich_hover_info(&info); } } @@ -11734,8 +11787,9 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ // UI_Parent(text_container_box) ProfScope("build line text") UI_Focus(UI_FocusKind_Off) { - DI_Key hovered_line_dbgi_key = df_get_hovered_line_info_dbgi_key(); - U64 hovered_line_voff = df_get_hovered_line_info_voff(); + DF_RichHoverInfo rich_hover_info = df_get_rich_hover_info(); + DI_Key hovered_line_dbgi_key = rich_hover_info.dbgi_key; + U64 hovered_line_voff = rich_hover_info.voff_range.min; ui_set_next_pref_height(ui_px(params->line_height_px*(dim_1s64(params->line_num_range)+1), 1.f)); UI_WidthFill UI_Column @@ -12029,17 +12083,14 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ // rjf: check dasm2src if(dasm2src_list->first != 0) { - DI_Key dbgi_key = dasm2src_list->first->v.dbgi_key; - if(di_key_match(&dbgi_key, &dasm2src_list->first->v.dbgi_key)) + for(DF_TextLineDasm2SrcInfoNode *n = dasm2src_list->first; n != 0; n = n->next) { - for(DF_TextLineDasm2SrcInfoNode *n = dasm2src_list->first; n != 0; n = n->next) + if(n->v.voff_range.min <= hovered_line_voff && + hovered_line_voff < n->v.voff_range.max) { - if(n->v.voff_range.min <= hovered_line_voff && hovered_line_voff < n->v.voff_range.max) - { - line_info_line_num = n->v.pt.line; - matches = 1; - break; - } + line_info_line_num = n->v.pt.line; + matches = 1; + break; } } } @@ -13128,7 +13179,8 @@ df_gfx_init(OS_WindowRepaintFunctionType *window_repaint_entry_point, DF_StateDe df_gfx_state->repaint_hook = window_repaint_entry_point; df_gfx_state->cfg_main_font_path_arena = arena_alloc(); df_gfx_state->cfg_code_font_path_arena = arena_alloc(); - df_gfx_state->hover_line_arena = arena_alloc(); + df_gfx_state->rich_hover_info_next_arena = arena_alloc(); + df_gfx_state->rich_hover_info_current_arena = arena_alloc(); df_clear_bindings(); // rjf: register gfx layer views @@ -13235,7 +13287,9 @@ internal void df_gfx_begin_frame(Arena *arena, DF_CmdList *cmds) { ProfBeginFunction(); - df_gfx_state->hover_line_set_this_frame = 0; + arena_clear(df_gfx_state->rich_hover_info_current_arena); + MemoryCopyStruct(&df_gfx_state->rich_hover_info_current, &df_gfx_state->rich_hover_info_next); + df_gfx_state->rich_hover_info_current.dbgi_key = di_key_copy(df_gfx_state->rich_hover_info_current_arena, &df_gfx_state->rich_hover_info_current.dbgi_key); //- rjf: animate confirmation { @@ -13694,7 +13748,7 @@ df_gfx_begin_frame(Arena *arena, DF_CmdList *cmds) DF_CfgNode *project_cfg_node = df_cfg_node_child_from_string(op, str8_lit("project"), StringMatchFlag_CaseInsensitive); if(project_cfg_node != &df_g_nil_cfg_node) { - project_path = project_cfg_node->first->string; + project_path = path_absolute_dst_from_relative_dst_src(scratch.arena, project_cfg_node->first->string, cfg_folder); } } @@ -14151,13 +14205,6 @@ df_gfx_end_frame(void) MemoryZeroStruct(&df_g_drag_drop_payload); } - //- rjf: clear hover line info - if(df_gfx_state->hover_line_set_this_frame == 0) - { - MemoryZeroStruct(&df_gfx_state->hover_line_dbgi_key); - df_gfx_state->hover_line_voff = 0; - } - //- rjf: clear frame request state if(df_gfx_state->num_frames_requested > 0) { diff --git a/src/df/gfx/df_gfx.h b/src/df/gfx/df_gfx.h index 1a91dc25..24f3b5b0 100644 --- a/src/df/gfx/df_gfx.h +++ b/src/df/gfx/df_gfx.h @@ -282,6 +282,19 @@ struct DF_DragDropPayload TxtPt text_point; }; +//////////////////////////////// +//~ rjf: Rich Hover Types + +typedef struct DF_RichHoverInfo DF_RichHoverInfo; +struct DF_RichHoverInfo +{ + DF_Handle process; + Rng1U64 vaddr_range; + DF_Handle module; + Rng1U64 voff_range; + DI_Key dbgi_key; +}; + //////////////////////////////// //~ rjf: View Rule Spec Types @@ -719,11 +732,11 @@ struct DF_GfxState // rjf: drag/drop state machine DF_DragDropState drag_drop_state; - // rjf: hover line info correllation state - Arena *hover_line_arena; - DI_Key hover_line_dbgi_key; - U64 hover_line_voff; - B32 hover_line_set_this_frame; + // rjf: rich hover info + Arena *rich_hover_info_next_arena; + Arena *rich_hover_info_current_arena; + DF_RichHoverInfo rich_hover_info_next; + DF_RichHoverInfo rich_hover_info_current; // rjf: running theme state DF_Theme cfg_theme_target; @@ -880,9 +893,8 @@ internal B32 df_drag_drop(DF_DragDropPayload *out_payload); internal void df_drag_kill(void); internal void df_queue_drag_drop(void); -internal void df_set_hovered_line_info(DI_Key *dbgi_key, U64 voff); -internal DI_Key df_get_hovered_line_info_dbgi_key(void); -internal U64 df_get_hovered_line_info_voff(void); +internal void df_set_rich_hover_info(DF_RichHoverInfo *info); +internal DF_RichHoverInfo df_get_rich_hover_info(void); //////////////////////////////// //~ rjf: View Spec State Functions diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 4ddcd837..9df21f5b 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -3272,8 +3272,10 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister) { for(U64 idx = 0; idx < rdis_count; idx += 1) { - rdis[idx] = di_rdi_from_key(di_scope, &dbgi_keys.v[idx], endt_us); - graphs[idx] = tg_graph_begin(rdi_addr_size_from_arch(rdis[idx]->top_level_info->arch), 256); + RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_keys.v[idx], endt_us); + RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); + rdis[idx] = rdi; + graphs[idx] = tg_graph_begin(rdi_addr_size_from_arch(tli->arch), 256); } } @@ -3302,9 +3304,11 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister) for(U64 rdi_idx = 0; rdi_idx < rdis_count; rdi_idx += 1) { RDI_Parsed *rdi = rdis[rdi_idx]; - if(base_idx <= item->idx && item->idx < base_idx + rdi->procedures_count) + U64 rdi_procedures_count = 0; + rdi_section_raw_table_from_kind(rdi, RDI_SectionKind_Procedures, &rdi_procedures_count); + if(base_idx <= item->idx && item->idx < base_idx + rdi_procedures_count) { - RDI_Procedure *procedure = rdi_element_from_idx(rdi, procedures, item->idx-base_idx); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, item->idx-base_idx); U64 name_size = 0; U8 *name_base = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); String8 name = str8(name_base, name_size); @@ -3317,7 +3321,7 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister) } break; } - base_idx += rdi->procedures_count; + base_idx += rdi_procedures_count; } } @@ -3360,23 +3364,25 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister) { for(U64 rdi_idx = 0; rdi_idx < rdis_count; rdi_idx += 1) { - if(base_idx <= item->idx && item->idx < base_idx + rdis[rdi_idx]->procedures_count) + U64 procedures_count = 0; + rdi_section_raw_table_from_kind(rdis[rdi_idx], RDI_SectionKind_Procedures, &procedures_count); + if(base_idx <= item->idx && item->idx < base_idx + procedures_count) { dbgi_key = dbgi_keys.v[rdi_idx]; rdi = rdis[rdi_idx]; graph = graphs[rdi_idx]; break; } - base_idx += rdis[rdi_idx]->procedures_count; + base_idx += procedures_count; } } //- rjf: unpack this item's info - RDI_Procedure *procedure = rdi_element_from_idx(rdi, procedures, item->idx-base_idx); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, item->idx-base_idx); U64 name_size = 0; U8 *name_base = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); String8 name = str8(name_base, name_size); - RDI_TypeNode *type_node = rdi_element_from_idx(rdi, type_nodes, procedure->type_idx); + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, procedure->type_idx); TG_Key type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), procedure->type_idx); //- rjf: build item button @@ -3411,7 +3417,7 @@ DF_VIEW_UI_FUNCTION_DEF(SymbolLister) if(ui_hovering(sig)) UI_Tooltip { U64 binary_voff = df_voff_from_dbgi_key_symbol_name(&dbgi_key, name); - DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, binary_voff); + DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, binary_voff, 0); String8 file_path = df_full_path_from_entity(scratch.arena, dasm2src_info.file); S64 line_num = dasm2src_info.pt.line; df_code_label(1.f, 0, df_rgba_from_theme_color(DF_ThemeColor_CodeFunction), name); @@ -3461,8 +3467,9 @@ DF_VIEW_CMD_FUNCTION_DEF(Target) { DF_Cmd *cmd = &n->cmd; - // rjf: mismatched view => skip - if(df_panel_from_handle(cmd->params.panel) != panel) + // rjf: mismatched window/panel => skip + if(df_window_from_handle(cmd->params.window) != ws || + df_panel_from_handle(cmd->params.panel) != panel) { continue; } @@ -4801,7 +4808,7 @@ DF_VIEW_UI_FUNCTION_DEF(Scheduler) DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr); DI_Key dbgi_key = df_dbgi_key_from_module(module); - DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff); + DF_TextLineDasm2SrcInfo line_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff, 0); if(!df_entity_is_nil(line_info.file)) { UI_PrefWidth(ui_children_sum(0)) df_entity_src_loc_button(ws, line_info.file, line_info.pt); @@ -4835,14 +4842,15 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) DI_Scope *scope = di_scope_open(); DF_CtrlCtx ctrl_ctx = df_ctrl_ctx_from_view(ws, view); DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread); - U64 selected_unwind_count = ctrl_ctx.unwind_count; + Architecture arch = df_architecture_from_entity(thread); DF_Entity *process = thread->parent; Vec4F32 thread_color = df_rgba_from_theme_color(DF_ThemeColor_PlainText); if(thread->flags & DF_EntityFlag_HasColor) { thread_color = df_rgba_from_entity(thread); } - CTRL_Unwind unwind = df_query_cached_unwind_from_thread(thread); + CTRL_Unwind base_unwind = df_query_cached_unwind_from_thread(thread); + DF_Unwind rich_unwind = df_unwind_from_ctrl_unwind(scratch.arena, scope, process, &base_unwind); //- rjf: grab state typedef struct DF_CallStackViewState DF_CallStackViewState; @@ -4873,8 +4881,8 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) scroll_list_params.flags = UI_ScrollListFlag_All; scroll_list_params.row_height_px = floor_f32(ui_top_font_size()*2.5f); scroll_list_params.dim_px = dim_2f32(rect); - scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(3, unwind.frames.count)); - scroll_list_params.item_range = r1s64(0, unwind.frames.count+1); + scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(3, rich_unwind.frames.count)); + scroll_list_params.item_range = r1s64(0, rich_unwind.frames.count+1); scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1; } UI_ScrollListSignal scroll_list_sig = {0}; @@ -4907,7 +4915,9 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) } //- rjf: frame rows - for(S64 row_num = visible_row_range.min; row_num <= visible_row_range.max && row_num <= unwind.frames.count; row_num += 1) + for(S64 row_num = visible_row_range.min; + row_num <= visible_row_range.max && row_num <= rich_unwind.frames.count; + row_num += 1) { if(row_num == 0) { @@ -4917,28 +4927,24 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) // rjf: unpack frame U64 frame_idx = row_num-1; - CTRL_UnwindFrame *frame = &unwind.frames.v[frame_idx]; + DF_UnwindFrame *frame = &rich_unwind.frames.v[frame_idx]; U64 rip_vaddr = regs_rip_from_arch_block(thread->arch, frame->regs); DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); B32 frame_valid = (rip_vaddr != 0); - U64 rip_voff = df_voff_from_vaddr(module, rip_vaddr); - DI_Key dbgi_key = df_dbgi_key_from_module(module); - RDI_Parsed *rdi = di_rdi_from_key(scope, &dbgi_key, 0); + TG_Graph *graph = tg_graph_begin(bit_size_from_arch(thread->arch)/8, 256); String8 symbol_name = {0}; String8 symbol_type_string = {0}; - if(rdi->scope_vmap != 0) + if(frame->procedure != 0) { - U64 scope_idx = rdi_vmap_idx_from_voff(rdi->scope_vmap, rdi->scope_vmap_count, rip_voff); - RDI_Scope *scope = rdi_element_from_idx(rdi, scopes, scope_idx); - U64 proc_idx = scope->proc_idx; - RDI_Procedure *procedure = &rdi->procedures[proc_idx]; - RDI_TypeNode *type_node = rdi_element_from_idx(rdi, type_nodes, procedure->type_idx); - TG_Key type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), procedure->type_idx); - U64 name_size = 0; - U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); - TG_Graph *graph = tg_graph_begin(rdi_addr_size_from_arch(rdi->top_level_info->arch), 256); - symbol_name = str8(name_ptr, name_size); - symbol_type_string = tg_string_from_key(scratch.arena, graph, rdi, type_key); + symbol_name.str = rdi_name_from_procedure(frame->rdi, frame->procedure, &symbol_name.size); + RDI_TypeNode *type = rdi_element_from_name_idx(frame->rdi, TypeNodes, frame->procedure->type_idx); + symbol_type_string = tg_string_from_key(scratch.arena, graph, frame->rdi, tg_key_ext(tg_kind_from_rdi_type_kind(type->kind), frame->procedure->type_idx)); + } + if(frame->inline_site != 0) + { + symbol_name.str = rdi_string_from_idx(frame->rdi, frame->inline_site->name_string_idx, &symbol_name.size); + RDI_TypeNode *type = rdi_element_from_name_idx(frame->rdi, TypeNodes, frame->inline_site->type_idx); + symbol_type_string = tg_string_from_key(scratch.arena, graph, frame->rdi, tg_key_ext(tg_kind_from_rdi_type_kind(type->kind), frame->inline_site->type_idx)); } // rjf: build row @@ -4953,7 +4959,12 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) UI_TextAlignment(UI_TextAlign_Center) UI_FocusHot((row_selected && cs->cursor.x == 0) ? UI_FocusKind_On : UI_FocusKind_Off) { - String8 selected_string = selected_unwind_count == frame_idx ? df_g_icon_kind_text_table[DF_IconKind_RightArrow] : str8_lit(""); + String8 selected_string = {0}; + if(ctrl_ctx.unwind_count == frame->base_unwind_idx && + ctrl_ctx.inline_unwind_count == frame->inline_unwind_idx) + { + selected_string = df_g_icon_kind_text_table[DF_IconKind_RightArrow]; + } UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable|UI_BoxFlag_DrawText, "%S###selection_%i", selected_string, (int)frame_idx); UI_Signal sig = ui_signal_from_box(box); @@ -4966,8 +4977,10 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) if(ui_double_clicked(sig) || sig.f&UI_SignalFlag_KeyboardPressed) { DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); - params.index = frame_idx; - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineUnwindIndex); + params.base_unwind_index = frame->base_unwind_idx; + params.inline_unwind_index = frame->inline_unwind_idx; df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); } } @@ -5000,6 +5013,14 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable|UI_BoxFlag_Clip, "frame_%I64x", frame_idx); UI_Parent(box) { + if(frame->inline_site != 0) + { + UI_PrefWidth(ui_text_dim(10, 1)) + { + ui_set_next_text_color(df_rgba_from_theme_color(DF_ThemeColor_WeakText)); + ui_label(str8_lit("[inlined]")); + } + } if(symbol_name.size == 0) { ui_set_next_text_color(df_rgba_from_theme_color(DF_ThemeColor_WeakText)); @@ -5028,8 +5049,10 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) if(ui_double_clicked(sig) || sig.f&UI_SignalFlag_KeyboardPressed) { DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); - params.index = frame_idx; - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineUnwindIndex); + params.base_unwind_index = frame->base_unwind_idx; + params.inline_unwind_index = frame->inline_unwind_idx; df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); } } @@ -5049,8 +5072,10 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) if(ui_double_clicked(sig) || sig.f&UI_SignalFlag_KeyboardPressed) { DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); - params.index = frame_idx; - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_Index); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_BaseUnwindIndex); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_InlineUnwindIndex); + params.base_unwind_index = frame->base_unwind_idx; + params.inline_unwind_index = frame->inline_unwind_idx; df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_SelectUnwind)); } } @@ -5932,13 +5957,14 @@ DF_VIEW_UI_FUNCTION_DEF(Code) { DF_Entity *thread = thread_n->entity; DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); - U64 unwind_count = (thread == selected_thread) ? ctrl_ctx.unwind_count : 0; + U64 base_unwind_count = (thread == selected_thread) ? ctrl_ctx.unwind_count : 0; + U64 inline_unwind_count = (thread == selected_thread) ? ctrl_ctx.inline_unwind_count : 0; U64 rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, unwind_count); U64 last_inst_on_unwound_rip_vaddr = rip_vaddr - !!unwind_count; DF_Entity *module = df_module_from_process_vaddr(process, last_inst_on_unwound_rip_vaddr); U64 rip_voff = df_voff_from_vaddr(module, last_inst_on_unwound_rip_vaddr); DI_Key dbgi_key = df_dbgi_key_from_module(module); - DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff); + DF_TextLineDasm2SrcInfo dasm2src_info = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, rip_voff, inline_unwind_count); if(dasm2src_info.file == entity && visible_line_num_range.min <= dasm2src_info.pt.line && dasm2src_info.pt.line <= visible_line_num_range.max) { U64 slice_line_idx = dasm2src_info.pt.line-visible_line_num_range.min; @@ -6614,10 +6640,10 @@ DF_VIEW_CMD_FUNCTION_DEF(Disassembly) // DF_Entity *process = df_entity_from_handle(dv->process); Architecture arch = df_architecture_from_entity(process); - U64 dasm_base_vaddr = AlignDownPow2(dv->base_vaddr, KB(64)); + U64 dasm_base_vaddr = AlignDownPow2(dv->base_vaddr, KB(16)); DF_Entity *dasm_module = df_module_from_process_vaddr(process, dasm_base_vaddr); DI_Key dasm_dbgi_key = df_dbgi_key_from_module(dasm_module); - Rng1U64 dasm_vaddr_range = r1u64(dasm_base_vaddr, dasm_base_vaddr+KB(64)); + Rng1U64 dasm_vaddr_range = r1u64(dasm_base_vaddr, dasm_base_vaddr+KB(16)); U128 dasm_key = ctrl_hash_store_key_from_process_vaddr_range(process->ctrl_machine_id, process->ctrl_handle, dasm_vaddr_range, 0); U128 dasm_data_hash = {0}; DASM_Params dasm_params = {0}; @@ -7078,7 +7104,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly) DF_TextLineDasm2SrcInfoNode *dasm2src_n = push_array(scratch.arena, DF_TextLineDasm2SrcInfoNode, 1); SLLQueuePush(code_slice_params.line_dasm2src[slice_idx].first, code_slice_params.line_dasm2src[slice_idx].last, dasm2src_n); code_slice_params.line_dasm2src[slice_idx].count += 1; - dasm2src_n->v = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, voff); + dasm2src_n->v = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, voff, 0); } } } @@ -7250,7 +7276,7 @@ DF_VIEW_UI_FUNCTION_DEF(Disassembly) DF_Entity *module = df_module_from_process_vaddr(process, vaddr); DI_Key dbgi_key = df_dbgi_key_from_module(module); U64 voff = df_voff_from_vaddr(module, vaddr); - DF_TextLineDasm2SrcInfo dasm2src = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, voff); + DF_TextLineDasm2SrcInfo dasm2src = df_text_line_dasm2src_info_from_dbgi_key_voff(&dbgi_key, voff, 0); String8 file_path = df_full_path_from_entity(scratch.arena, dasm2src.file); DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); params.text_point = dasm2src.pt; diff --git a/src/eval/eval_parser.c b/src/eval/eval_parser.c index bbfeca81..81f70d33 100644 --- a/src/eval/eval_parser.c +++ b/src/eval/eval_parser.c @@ -73,10 +73,9 @@ eval_push_locals_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff) //- rjf: voff -> tightest scope RDI_Scope *tightest_scope = 0; - if(rdi->scope_vmap != 0 && rdi->scopes != 0) { - U64 scope_idx = rdi_vmap_idx_from_voff(rdi->scope_vmap, rdi->scope_vmap_count, voff); - RDI_Scope *scope = &rdi->scopes[scope_idx]; + U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); Task *task = push_array(scratch.arena, Task, 1); task->scope = scope; SLLQueuePush(first_task, last_task, task); @@ -84,10 +83,10 @@ eval_push_locals_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff) } //- rjf: voff-1 -> scope - if(voff > 0 && rdi->scope_vmap != 0 && rdi->scopes != 0) + if(voff > 0) { - U64 scope_idx = rdi_vmap_idx_from_voff(rdi->scope_vmap, rdi->scope_vmap_count, voff-1); - RDI_Scope *scope = &rdi->scopes[scope_idx]; + U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff-1); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); if(scope != tightest_scope) { Task *task = push_array(scratch.arena, Task, 1); @@ -99,9 +98,10 @@ eval_push_locals_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff) //- rjf: tightest scope -> walk up the tree & build tasks for each parent scope if(tightest_scope != 0) { - for(RDI_Scope *scope = &rdi->scopes[tightest_scope->parent_scope_idx]; - scope != 0 && scope != &rdi->scopes[0]; - scope = &rdi->scopes[scope->parent_scope_idx]) + RDI_Scope *nil_scope = rdi_element_from_name_idx(rdi, Scopes, 0); + for(RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, tightest_scope->parent_scope_idx); + scope != 0 && scope != nil_scope; + scope = rdi_element_from_name_idx(rdi, Scopes, scope->parent_scope_idx)) { Task *task = push_array(scratch.arena, Task, 1); task->scope = scope; @@ -122,7 +122,7 @@ eval_push_locals_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff) U32 local_opl_idx = scope->local_first + scope->local_count; for(U32 local_idx = scope->local_first; local_idx < local_opl_idx; local_idx += 1) { - RDI_Local *local_var = &rdi->locals[local_idx]; + RDI_Local *local_var = rdi_element_from_name_idx(rdi, Locals, local_idx); U64 local_name_size = 0; U8 *local_name_str = rdi_string_from_idx(rdi, local_var->name_string_idx, &local_name_size); String8 name = push_str8_copy(arena, str8(local_name_str, local_name_size)); @@ -139,52 +139,30 @@ internal EVAL_String2NumMap * eval_push_member_map_from_rdi_voff(Arena *arena, RDI_Parsed *rdi, U64 voff) { //- rjf: voff -> tightest scope - RDI_Scope *tightest_scope = 0; - if(rdi->scope_vmap != 0 && rdi->scopes != 0) - { - U64 scope_idx = rdi_vmap_idx_from_voff(rdi->scope_vmap, rdi->scope_vmap_count, voff); - tightest_scope = &rdi->scopes[scope_idx]; - } + U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); + RDI_Scope *tightest_scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); //- rjf: tightest scope -> procedure - RDI_Procedure *procedure = 0; - if(tightest_scope != 0 && rdi->procedures != 0) - { - U32 proc_idx = tightest_scope->proc_idx; - if(0 < proc_idx && proc_idx < rdi->procedures_count) - { - procedure = &rdi->procedures[proc_idx]; - } - } + U32 proc_idx = tightest_scope->proc_idx; + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx); //- rjf: procedure -> udt - RDI_UDT *udt = 0; - if(procedure != 0 && rdi->udts != 0 && procedure->link_flags & RDI_LinkFlag_TypeScoped) - { - U32 udt_idx = procedure->container_idx; - if(0 < udt_idx && udt_idx < rdi->udts_count) - { - udt = &rdi->udts[udt_idx]; - } - } + U32 udt_idx = procedure->container_idx; + RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, udt_idx); //- rjf: build blank map EVAL_String2NumMap *map = push_array(arena, EVAL_String2NumMap, 1); *map = eval_string2num_map_make(arena, 64); //- rjf: udt -> fill member map - if(udt != 0 && !(udt->flags & RDI_UDTFlag_EnumMembers) && rdi->members != 0) + if(!(udt->flags & RDI_UDTFlag_EnumMembers)) { U64 data_member_num = 1; for(U32 member_idx = udt->member_first; member_idx < udt->member_first+udt->member_count; member_idx += 1) { - if(member_idx < 1 || rdi->members_count <= member_idx) - { - break; - } - RDI_Member *m = &rdi->members[member_idx]; + RDI_Member *m = rdi_element_from_name_idx(rdi, Members, member_idx); if(m->kind == RDI_MemberKind_DataField) { String8 name = {0}; @@ -476,11 +454,10 @@ eval_leaf_type_from_name(RDI_Parsed *rdi, String8 name) { TG_Key key = zero_struct; B32 found = 0; - if(rdi->type_nodes != 0) { - RDI_NameMap *name_map = rdi_name_map_from_kind(rdi, RDI_NameMapKind_Types); + RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Types); RDI_ParsedNameMap parsed_name_map = {0}; - rdi_name_map_parse(rdi, name_map, &parsed_name_map); + rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, name.str, name.size); if(node != 0) { @@ -488,7 +465,7 @@ eval_leaf_type_from_name(RDI_Parsed *rdi, String8 name) U32 *matches = rdi_matches_from_map_node(rdi, node, &match_count); if(match_count != 0) { - RDI_TypeNode *type_node = rdi_element_from_idx(rdi, type_nodes, matches[0]); + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, matches[0]); found = type_node->kind != RDI_TypeKind_NULL; key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)matches[0]); } @@ -838,12 +815,11 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8 //- rjf: form namespaceified fallback versions of this lookup string String8List namespaceified_token_strings = {0}; - if(ctx->rdi->procedures != 0 && ctx->rdi->scopes != 0 && ctx->rdi->scope_vmap != 0) { - U64 scope_idx = rdi_vmap_idx_from_voff(ctx->rdi->scope_vmap, ctx->rdi->scope_vmap_count, ctx->ip_voff); - RDI_Scope *scope = &ctx->rdi->scopes[scope_idx]; + U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(ctx->rdi, RDI_SectionKind_ScopeVMap, ctx->ip_voff); + RDI_Scope *scope = rdi_element_from_name_idx(ctx->rdi, Scopes, scope_idx); U64 proc_idx = scope->proc_idx; - RDI_Procedure *procedure = &ctx->rdi->procedures[proc_idx]; + RDI_Procedure *procedure = rdi_element_from_name_idx(ctx->rdi, Procedures, proc_idx); U64 name_size = 0; U8 *name_ptr = rdi_string_from_idx(ctx->rdi, procedure->name_string_idx, &name_size); String8 containing_procedure_name = str8(name_ptr, name_size); @@ -883,8 +859,8 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8 { mapped_identifier = 1; identifier_type_is_possibly_dynamically_overridden = 1; - RDI_Local *local_var = rdi_element_from_idx(ctx->rdi, locals, local_num-1); - RDI_TypeNode *type_node = rdi_element_from_idx(ctx->rdi, type_nodes, local_var->type_idx); + RDI_Local *local_var = rdi_element_from_name_idx(ctx->rdi, Locals, local_num-1); + RDI_TypeNode *type_node = rdi_element_from_name_idx(ctx->rdi, TypeNodes, local_var->type_idx); type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)local_var->type_idx); // rjf: grab location info @@ -892,19 +868,21 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8 loc_block_idx < local_var->location_opl; loc_block_idx += 1) { - RDI_LocationBlock *block = &ctx->rdi->location_blocks[loc_block_idx]; + RDI_LocationBlock *block = rdi_element_from_name_idx(ctx->rdi, LocationBlocks, loc_block_idx); if(block->scope_off_first <= ctx->ip_voff && ctx->ip_voff < block->scope_off_opl) { - loc_kind = *((RDI_LocationKind *)(ctx->rdi->location_data + block->location_data_off)); + U64 all_location_data_size = 0; + U8 *all_location_data = rdi_table_from_name(ctx->rdi, LocationData, &all_location_data_size); + loc_kind = *((RDI_LocationKind *)(all_location_data + block->location_data_off)); switch(loc_kind) { default:{mapped_identifier = 0;}break; case RDI_LocationKind_AddrBytecodeStream: case RDI_LocationKind_ValBytecodeStream: { - U8 *bytecode_base = ctx->rdi->location_data + block->location_data_off + sizeof(RDI_LocationKind); + U8 *bytecode_base = all_location_data + block->location_data_off + sizeof(RDI_LocationKind); U64 bytecode_size = 0; - for(U64 idx = 0; idx < ctx->rdi->location_data_size; idx += 1) + for(U64 idx = 0; idx < all_location_data_size; idx += 1) { U8 op = bytecode_base[idx]; if(op == 0) @@ -920,11 +898,11 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8 case RDI_LocationKind_AddrRegPlusU16: case RDI_LocationKind_AddrAddrRegPlusU16: { - MemoryCopy(&loc_reg_u16, (ctx->rdi->location_data + block->location_data_off), sizeof(loc_reg_u16)); + MemoryCopy(&loc_reg_u16, (all_location_data + block->location_data_off), sizeof(loc_reg_u16)); }break; case RDI_LocationKind_ValReg: { - MemoryCopy(&loc_reg, (ctx->rdi->location_data + block->location_data_off), sizeof(loc_reg)); + MemoryCopy(&loc_reg, (all_location_data + block->location_data_off), sizeof(loc_reg)); }break; } } @@ -959,120 +937,102 @@ eval_parse_expr_from_text_tokens__prec(Arena *arena, EVAL_ParseCtx *ctx, String8 //- rjf: try global variables if(mapped_identifier == 0) { - RDI_NameMap *name_map = rdi_name_map_from_kind(ctx->rdi, RDI_NameMapKind_GlobalVariables); - if(name_map != 0 && ctx->rdi->global_variables != 0) + RDI_NameMap *name_map = rdi_element_from_name_idx(ctx->rdi, NameMaps, RDI_NameMapKind_GlobalVariables); + RDI_ParsedNameMap parsed_name_map = {0}; + rdi_parsed_from_name_map(ctx->rdi, name_map, &parsed_name_map); + RDI_NameMapNode *node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, token_string.str, token_string.size); + U32 matches_count = 0; + U32 *matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); + for(String8Node *n = namespaceified_token_strings.first; + n != 0 && matches_count == 0; + n = n->next) { - RDI_ParsedNameMap parsed_name_map = {0}; - rdi_name_map_parse(ctx->rdi, name_map, &parsed_name_map); - RDI_NameMapNode *node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, token_string.str, token_string.size); - U32 matches_count = 0; - U32 *matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); - for(String8Node *n = namespaceified_token_strings.first; - n != 0 && matches_count == 0; - n = n->next) - { - node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, n->string.str, n->string.size); - matches_count = 0; - matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); - } - if(matches_count != 0) - { - // NOTE(rjf): apparently, PDBs can be produced such that they - // also keep stale *GLOBAL VARIABLE SYMBOLS* around too. I - // don't know of a magic hash table fixup path in PDBs, so - // in this case, I'm going to prefer the latest-added global. - U32 match_idx = matches[matches_count-1]; - RDI_GlobalVariable *global_var = &ctx->rdi->global_variables[match_idx]; - EVAL_OpList oplist = {0}; - eval_oplist_push_op(arena, &oplist, RDI_EvalOp_ModuleOff, global_var->voff); - loc_kind = RDI_LocationKind_AddrBytecodeStream; - loc_bytecode = eval_bytecode_from_oplist(arena, &oplist); - U32 type_idx = global_var->type_idx; - if(type_idx < ctx->rdi->type_nodes_count) - { - RDI_TypeNode *type_node = &ctx->rdi->type_nodes[type_idx]; - type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)type_idx); - } - mapped_identifier = 1; - } + node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, n->string.str, n->string.size); + matches_count = 0; + matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); + } + if(matches_count != 0) + { + // NOTE(rjf): apparently, PDBs can be produced such that they + // also keep stale *GLOBAL VARIABLE SYMBOLS* around too. I + // don't know of a magic hash table fixup path in PDBs, so + // in this case, I'm going to prefer the latest-added global. + U32 match_idx = matches[matches_count-1]; + RDI_GlobalVariable *global_var = rdi_element_from_name_idx(ctx->rdi, GlobalVariables, match_idx); + EVAL_OpList oplist = {0}; + eval_oplist_push_op(arena, &oplist, RDI_EvalOp_ModuleOff, global_var->voff); + loc_kind = RDI_LocationKind_AddrBytecodeStream; + loc_bytecode = eval_bytecode_from_oplist(arena, &oplist); + U32 type_idx = global_var->type_idx; + RDI_TypeNode *type_node = rdi_element_from_name_idx(ctx->rdi, TypeNodes, type_idx); + type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)type_idx); + mapped_identifier = 1; } } //- rjf: try thread variables if(mapped_identifier == 0) { - RDI_NameMap *name_map = rdi_name_map_from_kind(ctx->rdi, RDI_NameMapKind_ThreadVariables); - if(name_map != 0 && ctx->rdi->global_variables != 0) + RDI_NameMap *name_map = rdi_element_from_name_idx(ctx->rdi, NameMaps, RDI_NameMapKind_ThreadVariables); + RDI_ParsedNameMap parsed_name_map = {0}; + rdi_parsed_from_name_map(ctx->rdi, name_map, &parsed_name_map); + RDI_NameMapNode *node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, token_string.str, token_string.size); + U32 matches_count = 0; + U32 *matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); + for(String8Node *n = namespaceified_token_strings.first; + n != 0 && matches_count == 0; + n = n->next) { - RDI_ParsedNameMap parsed_name_map = {0}; - rdi_name_map_parse(ctx->rdi, name_map, &parsed_name_map); - RDI_NameMapNode *node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, token_string.str, token_string.size); - U32 matches_count = 0; - U32 *matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); - for(String8Node *n = namespaceified_token_strings.first; - n != 0 && matches_count == 0; - n = n->next) - { - node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, n->string.str, n->string.size); - matches_count = 0; - matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); - } - if(matches_count != 0) - { - U32 match_idx = matches[0]; - RDI_ThreadVariable *thread_var = &ctx->rdi->thread_variables[match_idx]; - EVAL_OpList oplist = {0}; - eval_oplist_push_op(arena, &oplist, RDI_EvalOp_TLSOff, thread_var->tls_off); - loc_kind = RDI_LocationKind_AddrBytecodeStream; - loc_bytecode = eval_bytecode_from_oplist(arena, &oplist); - U32 type_idx = thread_var->type_idx; - if(type_idx < ctx->rdi->type_nodes_count) - { - RDI_TypeNode *type_node = &ctx->rdi->type_nodes[type_idx]; - type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)type_idx); - } - mapped_identifier = 1; - } + node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, n->string.str, n->string.size); + matches_count = 0; + matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); + } + if(matches_count != 0) + { + U32 match_idx = matches[0]; + RDI_ThreadVariable *thread_var = rdi_element_from_name_idx(ctx->rdi, ThreadVariables, match_idx); + EVAL_OpList oplist = {0}; + eval_oplist_push_op(arena, &oplist, RDI_EvalOp_TLSOff, thread_var->tls_off); + loc_kind = RDI_LocationKind_AddrBytecodeStream; + loc_bytecode = eval_bytecode_from_oplist(arena, &oplist); + U32 type_idx = thread_var->type_idx; + RDI_TypeNode *type_node = rdi_element_from_name_idx(ctx->rdi, TypeNodes, type_idx); + type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)type_idx); + mapped_identifier = 1; } } //- rjf: try procedures if(mapped_identifier == 0) { - RDI_NameMap *name_map = rdi_name_map_from_kind(ctx->rdi, RDI_NameMapKind_Procedures); - if(name_map != 0 && ctx->rdi->procedures != 0 && ctx->rdi->scopes != 0 && ctx->rdi->scope_voffs) + RDI_NameMap *name_map = rdi_element_from_name_idx(ctx->rdi, NameMaps, RDI_NameMapKind_Procedures); + RDI_ParsedNameMap parsed_name_map = {0}; + rdi_parsed_from_name_map(ctx->rdi, name_map, &parsed_name_map); + RDI_NameMapNode *node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, token_string.str, token_string.size); + U32 matches_count = 0; + U32 *matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); + for(String8Node *n = namespaceified_token_strings.first; + n != 0 && matches_count == 0; + n = n->next) { - RDI_ParsedNameMap parsed_name_map = {0}; - rdi_name_map_parse(ctx->rdi, name_map, &parsed_name_map); - RDI_NameMapNode *node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, token_string.str, token_string.size); - U32 matches_count = 0; - U32 *matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); - for(String8Node *n = namespaceified_token_strings.first; - n != 0 && matches_count == 0; - n = n->next) - { - node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, n->string.str, n->string.size); - matches_count = 0; - matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); - } - if(matches_count != 0) - { - U32 match_idx = matches[0]; - RDI_Procedure *procedure = &ctx->rdi->procedures[match_idx]; - RDI_Scope *scope = &ctx->rdi->scopes[procedure->root_scope_idx]; - U64 voff = ctx->rdi->scope_voffs[scope->voff_range_first]; - EVAL_OpList oplist = {0}; - eval_oplist_push_op(arena, &oplist, RDI_EvalOp_ModuleOff, voff); - loc_kind = RDI_LocationKind_ValBytecodeStream; - loc_bytecode = eval_bytecode_from_oplist(arena, &oplist); - U32 type_idx = procedure->type_idx; - if(type_idx < ctx->rdi->type_nodes_count) - { - RDI_TypeNode *type_node = &ctx->rdi->type_nodes[type_idx]; - type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)type_idx); - } - mapped_identifier = 1; - } + node = rdi_name_map_lookup(ctx->rdi, &parsed_name_map, n->string.str, n->string.size); + matches_count = 0; + matches = rdi_matches_from_map_node(ctx->rdi, node, &matches_count); + } + if(matches_count != 0) + { + U32 match_idx = matches[0]; + RDI_Procedure *procedure = rdi_element_from_name_idx(ctx->rdi, Procedures, match_idx); + RDI_Scope *scope = rdi_element_from_name_idx(ctx->rdi, Scopes, procedure->root_scope_idx); + U64 voff = *rdi_element_from_name_idx(ctx->rdi, ScopeVOffData, scope->voff_range_first); + EVAL_OpList oplist = {0}; + eval_oplist_push_op(arena, &oplist, RDI_EvalOp_ModuleOff, voff); + loc_kind = RDI_LocationKind_ValBytecodeStream; + loc_bytecode = eval_bytecode_from_oplist(arena, &oplist); + U32 type_idx = procedure->type_idx; + RDI_TypeNode *type_node = rdi_element_from_name_idx(ctx->rdi, TypeNodes, type_idx); + type_key = tg_key_ext(tg_kind_from_rdi_type_kind(type_node->kind), (U64)type_idx); + mapped_identifier = 1; } } diff --git a/src/fuzzy_search/fuzzy_search.c b/src/fuzzy_search/fuzzy_search.c index 24cc8b13..7744e2f0 100644 --- a/src/fuzzy_search/fuzzy_search.c +++ b/src/fuzzy_search/fuzzy_search.c @@ -52,29 +52,29 @@ fzy_item_string_from_rdi_target_element_idx(RDI_Parsed *rdi, FZY_Target target, // NOTE(rjf): no default - warn if we miss a case case FZY_Target_Procedures: { - RDI_Procedure *proc = rdi_element_from_idx(rdi, procedures, element_idx); + RDI_Procedure *proc = rdi_element_from_name_idx(rdi, Procedures, element_idx); U64 name_size = 0; U8 *name_base = rdi_string_from_idx(rdi, proc->name_string_idx, &name_size); result = str8(name_base, name_size); }break; case FZY_Target_GlobalVariables: { - RDI_GlobalVariable *gvar = rdi_element_from_idx(rdi, global_variables, element_idx); + RDI_GlobalVariable *gvar = rdi_element_from_name_idx(rdi, GlobalVariables, element_idx); U64 name_size = 0; U8 *name_base = rdi_string_from_idx(rdi, gvar->name_string_idx, &name_size); result = str8(name_base, name_size); }break; case FZY_Target_ThreadVariables: { - RDI_ThreadVariable *tvar = rdi_element_from_idx(rdi, thread_variables, element_idx); + RDI_ThreadVariable *tvar = rdi_element_from_name_idx(rdi, ThreadVariables, element_idx); U64 name_size = 0; U8 *name_base = rdi_string_from_idx(rdi, tvar->name_string_idx, &name_size); result = str8(name_base, name_size); }break; case FZY_Target_UDTs: { - RDI_UDT *udt = rdi_element_from_idx(rdi, udts, element_idx); - RDI_TypeNode *type_node = rdi_element_from_idx(rdi, type_nodes, udt->self_type_idx); + RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, element_idx); + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); U64 name_size = 0; U8 *name_base = rdi_string_from_idx(rdi, type_node->user_defined.name_string_idx, &name_size); result = str8(name_base, name_size); @@ -407,10 +407,8 @@ fzy_search_thread__entry_point(void *p) //////////////////////////// //- rjf: search target -> info about search space // - U64 table_ptr_off = 0; - U64 table_count_off = 0; + RDI_SectionKind section_kind = RDI_SectionKind_NULL; U64 element_name_idx_off = 0; - U64 element_size = 0; if(task_is_good) { switch(params.target) @@ -419,30 +417,22 @@ fzy_search_thread__entry_point(void *p) case FZY_Target_COUNT:{}break; case FZY_Target_Procedures: { - table_ptr_off = OffsetOf(RDI_Parsed, procedures); - table_count_off = OffsetOf(RDI_Parsed, procedures_count); + section_kind = RDI_SectionKind_Procedures; element_name_idx_off = OffsetOf(RDI_Procedure, name_string_idx); - element_size = sizeof(RDI_Procedure); }break; case FZY_Target_GlobalVariables: { - table_ptr_off = OffsetOf(RDI_Parsed, global_variables); - table_count_off = OffsetOf(RDI_Parsed, global_variables_count); + section_kind = RDI_SectionKind_GlobalVariables; element_name_idx_off = OffsetOf(RDI_GlobalVariable, name_string_idx); - element_size = sizeof(RDI_GlobalVariable); }break; case FZY_Target_ThreadVariables: { - table_ptr_off = OffsetOf(RDI_Parsed, thread_variables); - table_count_off = OffsetOf(RDI_Parsed, thread_variables_count); + section_kind = RDI_SectionKind_ThreadVariables; element_name_idx_off = OffsetOf(RDI_ThreadVariable, name_string_idx); - element_size = sizeof(RDI_ThreadVariable); }break; case FZY_Target_UDTs: { - table_ptr_off = OffsetOf(RDI_Parsed, udts); - table_count_off = OffsetOf(RDI_Parsed, udts_count); - element_size = sizeof(RDI_UDT); + section_kind = RDI_SectionKind_UDTs; }break; } } @@ -457,16 +447,17 @@ fzy_search_thread__entry_point(void *p) for(U64 rdi_idx = 0; rdi_idx < rdis_count; rdi_idx += 1) { RDI_Parsed *rdi = rdis[rdi_idx]; - void *table_base = (U8*)rdi + table_ptr_off; - U64 element_count = *MemberFromOffset(U64 *, rdi, table_count_off); + U64 element_count = 0; + void *table_base = rdi_section_raw_table_from_kind(rdi, section_kind, &element_count); + U64 element_size = rdi_section_element_size_table[section_kind]; for(U64 idx = 1; task_is_good && idx < element_count; idx += 1) { - void *element = (U8 *)(*(void **)table_base) + element_size*idx; + void *element = (U8 *)table_base + element_size*idx; U32 *name_idx_ptr = (U32 *)((U8 *)element + element_name_idx_off); if(params.target == FZY_Target_UDTs) { RDI_UDT *udt = (RDI_UDT *)element; - RDI_TypeNode *type_node = rdi_element_from_idx(rdi, type_nodes, udt->self_type_idx); + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); name_idx_ptr = &type_node->user_defined.name_string_idx; } U32 name_idx = *name_idx_ptr; diff --git a/src/lib_rdi_format/rdi_format.c b/src/lib_rdi_format/rdi_format.c index ef9eea1b..71243041 100644 --- a/src/lib_rdi_format/rdi_format.c +++ b/src/lib_rdi_format/rdi_format.c @@ -10,6 +10,88 @@ #ifndef RDI_FORMAT_C #define RDI_FORMAT_C +RDI_U16 rdi_section_element_size_table[37] = +{ +sizeof(RDI_U8), +sizeof(RDI_TopLevelInfo), +sizeof(RDI_U8), +sizeof(RDI_U32), +sizeof(RDI_U32), +sizeof(RDI_BinarySection), +sizeof(RDI_FilePathNode), +sizeof(RDI_SourceFile), +sizeof(RDI_LineTable), +sizeof(RDI_U64), +sizeof(RDI_Line), +sizeof(RDI_Column), +sizeof(RDI_SourceLineMap), +sizeof(RDI_U32), +sizeof(RDI_U32), +sizeof(RDI_U64), +sizeof(RDI_Unit), +sizeof(RDI_VMapEntry), +sizeof(RDI_TypeNode), +sizeof(RDI_UDT), +sizeof(RDI_Member), +sizeof(RDI_EnumMember), +sizeof(RDI_GlobalVariable), +sizeof(RDI_VMapEntry), +sizeof(RDI_ThreadVariable), +sizeof(RDI_Procedure), +sizeof(RDI_Scope), +sizeof(RDI_U64), +sizeof(RDI_VMapEntry), +sizeof(RDI_InlineSite), +sizeof(RDI_Local), +sizeof(RDI_LocationBlock), +sizeof(RDI_U8), +sizeof(RDI_NameMap), +sizeof(RDI_NameMapBucket), +sizeof(RDI_NameMapNode), +sizeof(RDI_U8), +}; + +RDI_U8 rdi_section_is_required_table[37] = +{ +0, +0, +1, +1, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +}; + RDI_U8 rdi_eval_op_ctrlbits_table[45] = { RDI_EVAL_CTRLBITS(0, 0, 0), diff --git a/src/lib_rdi_format/rdi_format.h b/src/lib_rdi_format/rdi_format.h index ddd1cf7e..aba064e5 100644 --- a/src/lib_rdi_format/rdi_format.h +++ b/src/lib_rdi_format/rdi_format.h @@ -40,62 +40,71 @@ typedef int32_t RDI_S32; typedef int64_t RDI_S64; #endif +//////////////////////////////////////////////////////////////// +//~ Overridable Enabling/Disabling Of Table Index Typechecking + +#if !defined(RDI_DISABLE_TABLE_INDEX_TYPECHECKING) +# define RDI_DISABLE_TABLE_INDEX_TYPECHECKING 0 +#endif + //////////////////////////////////////////////////////////////// //~ Format Constants // \"raddbg\0\0\" #define RDI_MAGIC_CONSTANT 0x0000676264646172 -#define RDI_ENCODING_VERSION 1 +#define RDI_ENCODING_VERSION 6 //////////////////////////////////////////////////////////////// //~ Format Types & Functions -typedef RDI_U32 RDI_DataSectionTag; -typedef enum RDI_DataSectionTagEnum +typedef RDI_U32 RDI_SectionKind; +typedef enum RDI_SectionKindEnum { -RDI_DataSectionTag_NULL = 0x0000, -RDI_DataSectionTag_TopLevelInfo = 0x0001, -RDI_DataSectionTag_StringData = 0x0002, -RDI_DataSectionTag_StringTable = 0x0003, -RDI_DataSectionTag_IndexRuns = 0x0004, -RDI_DataSectionTag_BinarySections = 0x0005, -RDI_DataSectionTag_FilePathNodes = 0x0006, -RDI_DataSectionTag_SourceFiles = 0x0007, -RDI_DataSectionTag_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_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_DataSectionTagEnum; +RDI_SectionKind_NULL = 0x0000, +RDI_SectionKind_TopLevelInfo = 0x0001, +RDI_SectionKind_StringData = 0x0002, +RDI_SectionKind_StringTable = 0x0003, +RDI_SectionKind_IndexRuns = 0x0004, +RDI_SectionKind_BinarySections = 0x0005, +RDI_SectionKind_FilePathNodes = 0x0006, +RDI_SectionKind_SourceFiles = 0x0007, +RDI_SectionKind_LineTables = 0x0008, +RDI_SectionKind_LineInfoVOffs = 0x0009, +RDI_SectionKind_LineInfoLines = 0x000A, +RDI_SectionKind_LineInfoColumns = 0x000B, +RDI_SectionKind_SourceLineMaps = 0x000C, +RDI_SectionKind_SourceLineMapNumbers = 0x000D, +RDI_SectionKind_SourceLineMapRanges = 0x000E, +RDI_SectionKind_SourceLineMapVOffs = 0x000F, +RDI_SectionKind_Units = 0x0010, +RDI_SectionKind_UnitVMap = 0x0011, +RDI_SectionKind_TypeNodes = 0x0012, +RDI_SectionKind_UDTs = 0x0013, +RDI_SectionKind_Members = 0x0014, +RDI_SectionKind_EnumMembers = 0x0015, +RDI_SectionKind_GlobalVariables = 0x0016, +RDI_SectionKind_GlobalVMap = 0x0017, +RDI_SectionKind_ThreadVariables = 0x0018, +RDI_SectionKind_Procedures = 0x0019, +RDI_SectionKind_Scopes = 0x001A, +RDI_SectionKind_ScopeVOffData = 0x001B, +RDI_SectionKind_ScopeVMap = 0x001C, +RDI_SectionKind_InlineSites = 0x001D, +RDI_SectionKind_Locals = 0x001E, +RDI_SectionKind_LocationBlocks = 0x001F, +RDI_SectionKind_LocationData = 0x0020, +RDI_SectionKind_NameMaps = 0x0021, +RDI_SectionKind_NameMapBuckets = 0x0022, +RDI_SectionKind_NameMapNodes = 0x0023, +RDI_SectionKind_COUNT = 0x0024, +} RDI_SectionKindEnum; -typedef RDI_U32 RDI_DataSectionEncoding; -typedef enum RDI_DataSectionEncodingEnum +typedef RDI_U32 RDI_SectionEncoding; +typedef enum RDI_SectionEncodingEnum { -RDI_DataSectionEncoding_Unpacked = 0, -RDI_DataSectionEncoding_LZB = 1, -} RDI_DataSectionEncodingEnum; +RDI_SectionEncoding_Unpacked = 0, +RDI_SectionEncoding_LZB = 1, +} RDI_SectionEncodingEnum; typedef RDI_U32 RDI_Arch; typedef enum RDI_ArchEnum @@ -485,56 +494,133 @@ RDI_NameMapKind_NormalSourcePaths = 6, RDI_NameMapKind_COUNT = 7, } RDI_NameMapKindEnum; -#define RDI_DataSectionTag_XList \ -X(NULL)\ -X(TopLevelInfo)\ -X(StringData)\ -X(StringTable)\ -X(IndexRuns)\ -X(BinarySections)\ -X(FilePathNodes)\ -X(SourceFiles)\ -X(Units)\ -X(UnitVmap)\ -X(TypeNodes)\ -X(UDTs)\ -X(Members)\ -X(EnumMembers)\ -X(GlobalVariables)\ -X(GlobalVmap)\ -X(ThreadVariables)\ -X(Procedures)\ -X(Scopes)\ -X(ScopeVoffData)\ -X(ScopeVmap)\ -X(Locals)\ -X(LocationBlocks)\ -X(LocationData)\ -X(NameMaps)\ -X(PRIMARY_COUNT)\ -X(SECONDARY)\ -X(LineInfoVoffs)\ -X(LineInfoData)\ -X(LineInfoColumns)\ -X(LineMapNumbers)\ -X(LineMapRanges)\ -X(LineMapVoffs)\ -X(NameMapBuckets)\ -X(NameMapNodes)\ +#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_DataSectionEncoding_XList \ +#define RDI_SectionKind_XList \ +X(NULL, null, RDI_U8)\ +X(TopLevelInfo, top_level_info, RDI_TopLevelInfo)\ +X(StringData, string_data, RDI_U8)\ +X(StringTable, string_table, RDI_U32)\ +X(IndexRuns, index_runs, RDI_U32)\ +X(BinarySections, binary_sections, RDI_BinarySection)\ +X(FilePathNodes, file_path_nodes, RDI_FilePathNode)\ +X(SourceFiles, source_files, RDI_SourceFile)\ +X(LineTables, line_tables, RDI_LineTable)\ +X(LineInfoVOffs, line_info_voffs, RDI_U64)\ +X(LineInfoLines, line_info_lines, RDI_Line)\ +X(LineInfoColumns, line_info_columns, RDI_Column)\ +X(SourceLineMaps, source_line_maps, RDI_SourceLineMap)\ +X(SourceLineMapNumbers, source_line_map_numbers, RDI_U32)\ +X(SourceLineMapRanges, source_line_map_ranges, RDI_U32)\ +X(SourceLineMapVOffs, source_line_map_voffs, RDI_U64)\ +X(Units, units, RDI_Unit)\ +X(UnitVMap, unit_vmap, RDI_VMapEntry)\ +X(TypeNodes, type_nodes, RDI_TypeNode)\ +X(UDTs, udts, RDI_UDT)\ +X(Members, members, RDI_Member)\ +X(EnumMembers, enum_members, RDI_EnumMember)\ +X(GlobalVariables, global_variables, RDI_GlobalVariable)\ +X(GlobalVMap, global_vmap, RDI_VMapEntry)\ +X(ThreadVariables, thread_variables, RDI_ThreadVariable)\ +X(Procedures, procedures, RDI_Procedure)\ +X(Scopes, scopes, RDI_Scope)\ +X(ScopeVOffData, scope_voff_data, RDI_U64)\ +X(ScopeVMap, scope_vmap, RDI_VMapEntry)\ +X(InlineSites, inline_sites, RDI_InlineSite)\ +X(Locals, locals, RDI_Local)\ +X(LocationBlocks, location_blocks, RDI_LocationBlock)\ +X(LocationData, location_data, RDI_U8)\ +X(NameMaps, name_maps, RDI_NameMap)\ +X(NameMapBuckets, name_map_buckets, RDI_NameMapBucket)\ +X(NameMapNodes, name_map_nodes, RDI_NameMapNode)\ + +#define RDI_SectionEncoding_XList \ X(Unpacked)\ X(LZB)\ +#define RDI_Section_XList \ +X(RDI_SectionEncoding, encoding)\ +X(RDI_U32, pad)\ +X(RDI_U64, off)\ +X(RDI_U64, encoded_size)\ +X(RDI_U64, unpacked_size)\ + +#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)\ +X(RDI_U32, producer_name_string_idx)\ + #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, source_line_map_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_SourceLineMapMemberTable \ +X(RDI_U32, line_count)\ +X(RDI_U32, voff_count)\ +X(RDI_U32, line_map_nums_base_idx)\ +X(RDI_U32, line_map_range_base_idx)\ +X(RDI_U32, line_map_voff_base_idx)\ #define RDI_Language_XList \ X(NULL)\ @@ -602,9 +688,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 +717,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 +747,72 @@ 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)\ +X(RDI_U32, inline_site_idx)\ + +#define RDI_InlineSite_XList \ +X(RDI_U32, name_string_idx)\ +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 +886,87 @@ X(LinkNameProcedures)\ X(NormalSourcePaths)\ X(COUNT)\ +#define RDI_NameMap_XList \ +X(RDI_U32, bucket_base_idx)\ +X(RDI_U32, node_base_idx)\ +X(RDI_U32, bucket_count)\ +X(RDI_U32, node_count)\ + +#define RDI_NameMapBucket_XList \ +X(RDI_U32, first_node)\ +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)\ + +#if !RDI_DISABLE_TABLE_INDEX_TYPECHECKING +typedef struct RDI_U32_StringTable { RDI_U32 v; } RDI_U32_StringTable; +typedef struct RDI_U32_IndexRuns { RDI_U32 v; } RDI_U32_IndexRuns; +typedef struct RDI_U32_BinarySections { RDI_U32 v; } RDI_U32_BinarySections; +typedef struct RDI_U32_FilePathNodes { RDI_U32 v; } RDI_U32_FilePathNodes; +typedef struct RDI_U32_SourceFiles { RDI_U32 v; } RDI_U32_SourceFiles; +typedef struct RDI_U32_LineTables { RDI_U32 v; } RDI_U32_LineTables; +typedef struct RDI_U32_LineInfoVOffs { RDI_U32 v; } RDI_U32_LineInfoVOffs; +typedef struct RDI_U32_LineInfoLines { RDI_U32 v; } RDI_U32_LineInfoLines; +typedef struct RDI_U32_LineInfoColumns { RDI_U32 v; } RDI_U32_LineInfoColumns; +typedef struct RDI_U32_SourceLineMaps { RDI_U32 v; } RDI_U32_SourceLineMaps; +typedef struct RDI_U32_SourceLineMapNumbers { RDI_U32 v; } RDI_U32_SourceLineMapNumbers; +typedef struct RDI_U32_SourceLineMapRanges { RDI_U32 v; } RDI_U32_SourceLineMapRanges; +typedef struct RDI_U32_SourceLineMapVOffs { RDI_U32 v; } RDI_U32_SourceLineMapVOffs; +typedef struct RDI_U32_Units { RDI_U32 v; } RDI_U32_Units; +typedef struct RDI_U32_TypeNodes { RDI_U32 v; } RDI_U32_TypeNodes; +typedef struct RDI_U32_UDTs { RDI_U32 v; } RDI_U32_UDTs; +typedef struct RDI_U32_Members { RDI_U32 v; } RDI_U32_Members; +typedef struct RDI_U32_EnumMembers { RDI_U32 v; } RDI_U32_EnumMembers; +typedef struct RDI_U32_GlobalVariables { RDI_U32 v; } RDI_U32_GlobalVariables; +typedef struct RDI_U32_ThreadVariables { RDI_U32 v; } RDI_U32_ThreadVariables; +typedef struct RDI_U32_Procedures { RDI_U32 v; } RDI_U32_Procedures; +typedef struct RDI_U32_Scopes { RDI_U32 v; } RDI_U32_Scopes; +typedef struct RDI_U32_ScopeVOffData { RDI_U32 v; } RDI_U32_ScopeVOffData; +typedef struct RDI_U32_InlineSites { RDI_U32 v; } RDI_U32_InlineSites; +typedef struct RDI_U32_Locals { RDI_U32 v; } RDI_U32_Locals; +typedef struct RDI_U32_LocationBlocks { RDI_U32 v; } RDI_U32_LocationBlocks; +typedef struct RDI_U32_LocationData { RDI_U32 v; } RDI_U32_LocationData; +typedef struct RDI_U32_NameMaps { RDI_U32 v; } RDI_U32_NameMaps; +typedef struct RDI_U32_NameMapBuckets { RDI_U32 v; } RDI_U32_NameMapBuckets; +typedef struct RDI_U32_NameMapNodes { RDI_U32 v; } RDI_U32_NameMapNodes; +#else +typedef struct RDI_U32_Table { RDI_U32 v; } RDI_U32_Table; +typedef struct RDI_U64_Table { RDI_U64 v; } RDI_U64_Table; +typedef RDI_U32_Table RDI_U32_StringTable; +typedef RDI_U32_Table RDI_U32_IndexRuns; +typedef RDI_U32_Table RDI_U32_BinarySections; +typedef RDI_U32_Table RDI_U32_FilePathNodes; +typedef RDI_U32_Table RDI_U32_SourceFiles; +typedef RDI_U32_Table RDI_U32_LineTables; +typedef RDI_U32_Table RDI_U32_LineInfoVOffs; +typedef RDI_U32_Table RDI_U32_LineInfoLines; +typedef RDI_U32_Table RDI_U32_LineInfoColumns; +typedef RDI_U32_Table RDI_U32_SourceLineMaps; +typedef RDI_U32_Table RDI_U32_SourceLineMapNumbers; +typedef RDI_U32_Table RDI_U32_SourceLineMapRanges; +typedef RDI_U32_Table RDI_U32_SourceLineMapVOffs; +typedef RDI_U32_Table RDI_U32_Units; +typedef RDI_U32_Table RDI_U32_TypeNodes; +typedef RDI_U32_Table RDI_U32_UDTs; +typedef RDI_U32_Table RDI_U32_Members; +typedef RDI_U32_Table RDI_U32_EnumMembers; +typedef RDI_U32_Table RDI_U32_GlobalVariables; +typedef RDI_U32_Table RDI_U32_ThreadVariables; +typedef RDI_U32_Table RDI_U32_Procedures; +typedef RDI_U32_Table RDI_U32_Scopes; +typedef RDI_U32_Table RDI_U32_ScopeVOffData; +typedef RDI_U32_Table RDI_U32_InlineSites; +typedef RDI_U32_Table RDI_U32_Locals; +typedef RDI_U32_Table RDI_U32_LocationBlocks; +typedef RDI_U32_Table RDI_U32_LocationData; +typedef RDI_U32_Table RDI_U32_NameMaps; +typedef RDI_U32_Table RDI_U32_NameMapBuckets; +typedef RDI_U32_Table RDI_U32_NameMapNodes; +#endif + #define RDI_EVAL_CTRLBITS(decodeN,popN,pushN) ((decodeN) | ((popN) << 4) | ((pushN) << 6)) #define RDI_DECODEN_FROM_CTRLBITS(ctrlbits) ((ctrlbits) & 0xf) #define RDI_POPN_FROM_CTRLBITS(ctrlbits) (((ctrlbits) >> 4) & 0x3) @@ -723,11 +982,11 @@ RDI_U32 data_section_off; RDI_U32 data_section_count; }; -typedef struct RDI_DataSection RDI_DataSection; -struct RDI_DataSection +typedef struct RDI_Section RDI_Section; +struct RDI_Section { -RDI_DataSectionTag tag; -RDI_DataSectionEncoding encoding; +RDI_SectionEncoding encoding; +RDI_U32 pad; RDI_U64 off; RDI_U64 encoded_size; RDI_U64 unpacked_size; @@ -747,6 +1006,7 @@ RDI_Arch arch; RDI_U32 exe_name_string_idx; RDI_U64 exe_hash; RDI_U64 voff_max; +RDI_U32 producer_name_string_idx; }; typedef struct RDI_BinarySection RDI_BinarySection; @@ -775,10 +1035,7 @@ struct RDI_SourceFile { RDI_U32 file_path_node_idx; RDI_U32 normal_full_path_string_idx; -RDI_U32 line_map_count; -RDI_U32 line_map_nums_data_idx; -RDI_U32 line_map_range_data_idx; -RDI_U32 line_map_voff_data_idx; +RDI_U32 source_line_map_idx; }; typedef struct RDI_Unit RDI_Unit; @@ -791,10 +1048,17 @@ 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; +struct RDI_LineTable +{ +RDI_U32 voffs_base_idx; +RDI_U32 lines_base_idx; +RDI_U32 cols_base_idx; +RDI_U32 lines_count; +RDI_U32 cols_count; }; typedef struct RDI_Line RDI_Line; @@ -811,6 +1075,16 @@ RDI_U16 col_first; RDI_U16 col_opl; }; +typedef struct RDI_SourceLineMap RDI_SourceLineMap; +struct RDI_SourceLineMap +{ +RDI_U32 line_count; +RDI_U32 voff_count; +RDI_U32 line_map_nums_base_idx; +RDI_U32 line_map_range_base_idx; +RDI_U32 line_map_voff_base_idx; +}; + typedef struct RDI_TypeNode RDI_TypeNode; struct RDI_TypeNode { @@ -831,13 +1105,15 @@ RDI_U32 byte_size; { RDI_U32 direct_type_idx; RDI_U32 count; - union{ + union + { // when kind is 'Function' or 'Method' RDI_U32 param_idx_run_first; // when kind is 'MemberPtr' RDI_U32 owner_type_idx; }; - } constructed; + } + constructed; // kind is 'user defined' struct @@ -845,7 +1121,8 @@ RDI_U32 byte_size; RDI_U32 name_string_idx; RDI_U32 direct_type_idx; RDI_U32 udt_idx; - } user_defined; + } + user_defined; // (kind = Bitfield) struct @@ -853,7 +1130,8 @@ RDI_U32 byte_size; RDI_U32 direct_type_idx; RDI_U32 off; RDI_U32 size; - } bitfield; + } + bitfield; } ; }; @@ -932,6 +1210,16 @@ RDI_U32 local_first; RDI_U32 local_count; RDI_U32 static_local_idx_run_first; RDI_U32 static_local_count; +RDI_U32 inline_site_idx; +}; + +typedef struct RDI_InlineSite RDI_InlineSite; +struct RDI_InlineSite +{ +RDI_U32 name_string_idx; +RDI_U32 type_idx; +RDI_U32 owner_type_idx; +RDI_U32 line_table_idx; }; typedef struct RDI_Local RDI_Local; @@ -977,9 +1265,10 @@ RDI_RegCode reg_code; typedef struct RDI_NameMap RDI_NameMap; struct RDI_NameMap { -RDI_NameMapKind kind; -RDI_U32 bucket_data_idx; -RDI_U32 node_data_idx; +RDI_U32 bucket_base_idx; +RDI_U32 node_base_idx; +RDI_U32 bucket_count; +RDI_U32 node_count; }; typedef struct RDI_NameMapBucket RDI_NameMapBucket; @@ -997,6 +1286,42 @@ RDI_U32 match_count; RDI_U32 match_idx_or_idx_run_first; }; +typedef RDI_TopLevelInfo RDI_SectionElementType_TopLevelInfo; +typedef RDI_U8 RDI_SectionElementType_StringData; +typedef RDI_U32 RDI_SectionElementType_StringTable; +typedef RDI_U32 RDI_SectionElementType_IndexRuns; +typedef RDI_BinarySection RDI_SectionElementType_BinarySections; +typedef RDI_FilePathNode RDI_SectionElementType_FilePathNodes; +typedef RDI_SourceFile RDI_SectionElementType_SourceFiles; +typedef RDI_LineTable RDI_SectionElementType_LineTables; +typedef RDI_U64 RDI_SectionElementType_LineInfoVOffs; +typedef RDI_Line RDI_SectionElementType_LineInfoLines; +typedef RDI_Column RDI_SectionElementType_LineInfoColumns; +typedef RDI_SourceLineMap RDI_SectionElementType_SourceLineMaps; +typedef RDI_U32 RDI_SectionElementType_SourceLineMapNumbers; +typedef RDI_U32 RDI_SectionElementType_SourceLineMapRanges; +typedef RDI_U64 RDI_SectionElementType_SourceLineMapVOffs; +typedef RDI_Unit RDI_SectionElementType_Units; +typedef RDI_VMapEntry RDI_SectionElementType_UnitVMap; +typedef RDI_TypeNode RDI_SectionElementType_TypeNodes; +typedef RDI_UDT RDI_SectionElementType_UDTs; +typedef RDI_Member RDI_SectionElementType_Members; +typedef RDI_EnumMember RDI_SectionElementType_EnumMembers; +typedef RDI_GlobalVariable RDI_SectionElementType_GlobalVariables; +typedef RDI_VMapEntry RDI_SectionElementType_GlobalVMap; +typedef RDI_ThreadVariable RDI_SectionElementType_ThreadVariables; +typedef RDI_Procedure RDI_SectionElementType_Procedures; +typedef RDI_Scope RDI_SectionElementType_Scopes; +typedef RDI_U64 RDI_SectionElementType_ScopeVOffData; +typedef RDI_VMapEntry RDI_SectionElementType_ScopeVMap; +typedef RDI_InlineSite RDI_SectionElementType_InlineSites; +typedef RDI_Local RDI_SectionElementType_Locals; +typedef RDI_LocationBlock RDI_SectionElementType_LocationBlocks; +typedef RDI_U8 RDI_SectionElementType_LocationData; +typedef RDI_NameMap RDI_SectionElementType_NameMaps; +typedef RDI_NameMapBucket RDI_SectionElementType_NameMapBuckets; +typedef RDI_NameMapNode RDI_SectionElementType_NameMapNodes; + RDI_PROC RDI_U64 rdi_hash(RDI_U8 *ptr, RDI_U64 size); RDI_PROC RDI_U32 rdi_size_from_basic_type_kind(RDI_TypeKind kind); RDI_PROC RDI_U32 rdi_addr_size_from_arch(RDI_Arch arch); @@ -1004,6 +1329,8 @@ RDI_PROC RDI_EvalConversionKind rdi_eval_conversion_kind_from_typegroups(RDI_Eva RDI_PROC RDI_S32 rdi_eval_op_typegroup_are_compatible(RDI_EvalOp op, RDI_EvalTypeGroup group); RDI_PROC RDI_U8 *rdi_explanation_string_from_eval_conversion_kind(RDI_EvalConversionKind kind, RDI_U64 *size_out); +extern RDI_U16 rdi_section_element_size_table[37]; +extern RDI_U8 rdi_section_is_required_table[37]; extern RDI_U8 rdi_eval_op_ctrlbits_table[45]; #endif // RDI_FORMAT_H diff --git a/src/lib_rdi_format/rdi_format_parse.c b/src/lib_rdi_format/rdi_format_parse.c index dafce68b..a2a3fd2f 100644 --- a/src/lib_rdi_format/rdi_format_parse.c +++ b/src/lib_rdi_format/rdi_format_parse.c @@ -2,388 +2,372 @@ // 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 - RDI_DataSection *dsecs = 0; + ////////////////////////////// + //- rjf: extract data sections + // + RDI_Section *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){ - dsecs = (RDI_DataSection*)(data + hdr->data_section_off); + if(opl <= size) + { + dsecs = (RDI_Section*)(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 - RDI_U32 dsec_idx[RDI_DataSectionTag_PRIMARY_COUNT] = {0}; - if (result == RDI_ParseStatus_Good){ - RDI_DataSection *sec_ptr = dsecs; - for (RDI_U32 i = 0; i < dsec_count; i += 1, sec_ptr += 1){ - if (sec_ptr->tag < RDI_DataSectionTag_PRIMARY_COUNT){ - dsec_idx[sec_ptr->tag] = i; - } - } - } - - // fill out data block (part 1) - if (result == RDI_ParseStatus_Good){ + ////////////////////////////// + //- rjf: fill result + // + if(result == RDI_ParseStatus_Good) + { out->raw_data = data; out->raw_data_size = size; - out->dsecs = dsecs; - out->dsec_count = dsec_count; - for (RDI_U32 i = 0; i < RDI_DataSectionTag_PRIMARY_COUNT; i += 1){ - out->dsec_idx[i] = dsec_idx[i]; - } + out->sections = dsecs; + out->sections_count = dsec_count; } - // out string table - 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); - - RDI_U64 table_entry_count = 0; - rdi_parse__extract_primary(out, string_offs, &table_entry_count, - RDI_DataSectionTag_StringTable); - if (table_entry_count > 0){ - string_count = table_entry_count - 1; - } - - // (errors) - if (string_data == 0){ - result = RDI_ParseStatus_MissingStringDataSection; - } - else if (string_offs == 0){ - result = RDI_ParseStatus_MissingStringTableSection; - } - } - - // out index runs - 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){ - result = RDI_ParseStatus_MissingIndexRunSection; - } - } - - if (result == RDI_ParseStatus_Good){ - // fill out primary data structures (part 2) - 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; - + ////////////////////////////// + //- rjf: validate results + // + if(result == RDI_ParseStatus_Good) + { + for(RDI_SectionKind k = (RDI_SectionKind)(RDI_SectionKind_NULL+1); k < RDI_SectionKind_COUNT; k = (RDI_SectionKind)(k+1)) { - RDI_TopLevelInfo *tli = 0; - RDI_U64 dummy = 0; - rdi_parse__extract_primary(out, tli, &dummy, RDI_DataSectionTag_TopLevelInfo); - if (dummy != 1){ - tli = 0; - } - out->top_level_info = tli; - } - - rdi_parse__extract_primary(out, out->binary_sections, &out->binary_sections_count, - RDI_DataSectionTag_BinarySections); - - rdi_parse__extract_primary(out, out->file_paths, &out->file_paths_count, - RDI_DataSectionTag_FilePathNodes); - - rdi_parse__extract_primary(out, out->source_files, &out->source_files_count, - RDI_DataSectionTag_SourceFiles); - - rdi_parse__extract_primary(out, out->units, &out->units_count, - RDI_DataSectionTag_Units); - - rdi_parse__extract_primary(out, out->unit_vmap, &out->unit_vmap_count, - RDI_DataSectionTag_UnitVmap); - - rdi_parse__extract_primary(out, out->unit_vmap, &out->unit_vmap_count, - RDI_DataSectionTag_UnitVmap); - - rdi_parse__extract_primary(out, out->type_nodes, &out->type_nodes_count, - RDI_DataSectionTag_TypeNodes); - - rdi_parse__extract_primary(out, out->udts, &out->udts_count, - RDI_DataSectionTag_UDTs); - - rdi_parse__extract_primary(out, out->members, &out->members_count, - RDI_DataSectionTag_Members); - - rdi_parse__extract_primary(out, out->enum_members, &out->enum_members_count, - RDI_DataSectionTag_EnumMembers); - - rdi_parse__extract_primary(out, out->global_variables, &out->global_variables_count, - RDI_DataSectionTag_GlobalVariables); - - rdi_parse__extract_primary(out, out->global_vmap, &out->global_vmap_count, - RDI_DataSectionTag_GlobalVmap); - - rdi_parse__extract_primary(out, out->thread_variables, &out->thread_variables_count, - RDI_DataSectionTag_ThreadVariables); - - rdi_parse__extract_primary(out, out->procedures, &out->procedures_count, - RDI_DataSectionTag_Procedures); - - rdi_parse__extract_primary(out, out->scopes, &out->scopes_count, - RDI_DataSectionTag_Scopes); - - rdi_parse__extract_primary(out, out->scope_voffs, &out->scope_voffs_count, - RDI_DataSectionTag_ScopeVoffData); - - rdi_parse__extract_primary(out, out->scope_vmap, &out->scope_vmap_count, - RDI_DataSectionTag_ScopeVmap); - - rdi_parse__extract_primary(out, out->locals, &out->locals_count, - RDI_DataSectionTag_Locals); - - rdi_parse__extract_primary(out, out->location_blocks, &out->location_blocks_count, - RDI_DataSectionTag_LocationBlocks); - - rdi_parse__extract_primary(out, out->location_data, &out->location_data_size, - RDI_DataSectionTag_LocationData); - - { - rdi_parse__extract_primary(out, out->name_maps, &out->name_maps_count, - RDI_DataSectionTag_NameMaps); - - RDI_NameMap *name_map_ptr = out->name_maps; - RDI_NameMap *name_map_opl = out->name_maps + out->name_maps_count; - for (; name_map_ptr < name_map_opl; name_map_ptr += 1){ - if (out->name_maps_by_kind[name_map_ptr->kind] == 0){ - out->name_maps_by_kind[name_map_ptr->kind] = name_map_ptr; + if(rdi_section_is_required_table[k]) + { + RDI_U64 data_size = 0; + RDI_SectionEncoding encoding = 0; + void *data = rdi_section_raw_data_from_kind(out, k, &encoding, &data_size); + if(data == 0 || data == &rdi_nil_element_union || data_size == 0) + { + result = RDI_ParseStatus_MissingRequiredSection; + break; } } } } -#if !defined(RDI_DISABLE_NILS) - if(out->top_level_info == 0) { out->top_level_info = &rdi_top_level_info_nil; } - if(out->binary_sections == 0) { out->binary_sections = &rdi_binary_section_nil; out->binary_sections_count = 1; } - if(out->file_paths == 0) { out->file_paths = &rdi_file_path_node_nil; out->file_paths_count = 1; } - if(out->source_files == 0) { out->source_files = &rdi_source_file_nil; out->source_files_count = 1; } - if(out->units == 0) { out->units = &rdi_unit_nil; out->units_count = 1; } - if(out->unit_vmap == 0) { out->unit_vmap = &rdi_vmap_entry_nil; out->unit_vmap_count = 1; } - if(out->type_nodes == 0) { out->type_nodes = &rdi_type_node_nil; out->type_nodes_count = 1; } - if(out->udts == 0) { out->udts = &rdi_udt_nil; out->udts_count = 1; } - if(out->members == 0) { out->members = &rdi_member_nil; out->members_count = 1; } - if(out->enum_members == 0) { out->enum_members = &rdi_enum_member_nil; out->enum_members_count = 1; } - if(out->global_variables == 0) { out->global_variables = &rdi_global_variable_nil; out->global_variables_count = 1; } - if(out->global_vmap == 0) { out->global_vmap = &rdi_vmap_entry_nil; out->global_vmap_count = 1; } - if(out->thread_variables == 0) { out->thread_variables = &rdi_thread_variable_nil; out->thread_variables_count = 1; } - if(out->procedures == 0) { out->procedures = &rdi_procedure_nil; out->procedures_count = 1; } - if(out->scopes == 0) { out->scopes = &rdi_scope_nil; out->scopes_count = 1; } - if(out->scope_voffs == 0) { out->scope_voffs = &rdi_voff_nil; out->scope_voffs_count = 1; } - if(out->scope_vmap == 0) { out->scope_vmap = &rdi_vmap_entry_nil; out->scope_vmap_count = 1; } - if(out->locals == 0) { out->locals = &rdi_local_nil; out->locals_count = 1; } - if(out->location_blocks == 0) { out->location_blocks = &rdi_location_block_nil; out->location_blocks_count = 1; } -#endif - - return(result); + return result; } +//////////////////////////////// +//~ Base Parsed Info Extraction Helpers + +//- section table/element raw data extraction + +RDI_PROC void * +rdi_section_raw_data_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_SectionEncoding *encoding_out, RDI_U64 *size_out) +{ + void *result = 0; +#if !defined(RDI_DISABLE_NILS) + result = &rdi_nil_element_union; + *size_out = rdi_section_element_size_table[kind]; +#endif + if(0 <= kind && kind < rdi->sections_count) + { + result = rdi->raw_data+rdi->sections[kind].off; + *size_out = rdi->sections[kind].encoded_size; + *encoding_out = rdi->sections[kind].encoding; + } + return result; +} + +RDI_PROC void * +rdi_section_raw_table_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 *count_out) +{ + void *result = 0; + RDI_U64 all_elements_size = 0; + RDI_SectionEncoding all_elements_encoding = 0; + void *all_elements = rdi_section_raw_data_from_kind(rdi, kind, &all_elements_encoding, &all_elements_size); + if(all_elements_encoding == RDI_SectionEncoding_Unpacked) + { + RDI_U64 element_size = (RDI_U64)rdi_section_element_size_table[kind]; + RDI_U64 all_elements_count = all_elements_size/element_size; + result = all_elements; + *count_out = all_elements_count; + } + return result; +} + +RDI_PROC void * +rdi_section_raw_element_from_kind_idx(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 idx) +{ + RDI_U64 count = 0; + void *table = rdi_section_raw_table_from_kind(rdi, kind, &count); + void *result = table; + if(idx < count) + { + RDI_U64 element_size = (RDI_U64)rdi_section_element_size_table[kind]; + result = (RDI_U8 *)table + element_size*idx; + } + return result; +} + +//- info about whole parse + RDI_PROC RDI_U64 rdi_decompressed_size_from_parsed(RDI_Parsed *rdi) { RDI_U64 decompressed_size = rdi->raw_data_size; - for(RDI_U64 dsec_idx = 0; dsec_idx < rdi->dsec_count; dsec_idx += 1) + for(RDI_U64 section_idx = 0; section_idx < rdi->sections_count; section_idx += 1) { - decompressed_size += (rdi->dsecs[dsec_idx].unpacked_size - rdi->dsecs[dsec_idx].encoded_size); + decompressed_size += (rdi->sections[section_idx].unpacked_size - rdi->sections[section_idx].encoded_size); } return decompressed_size; } -RDI_PROC RDI_U8* -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){ - RDI_U32 off_raw = parsed->string_offs[idx]; - RDI_U32 opl_raw = parsed->string_offs[idx + 1]; - RDI_U32 opl = rdi_parse__min(opl_raw, parsed->string_data_size); - RDI_U32 off = rdi_parse__min(off_raw, opl); - result = parsed->string_data + off; - len_result = opl - off; +//- strings + +RDI_PROC RDI_U8 * +rdi_string_from_idx(RDI_Parsed *rdi, RDI_U32 idx, RDI_U64 *len_out) +{ + RDI_U8 *result_base = 0; + RDI_U64 result_size = 0; + { + RDI_U64 string_offs_count = 0; + RDI_U32 *string_offs = rdi_table_from_name(rdi, StringTable, &string_offs_count); + if(idx < string_offs_count) + { + RDI_U64 string_data_size = 0; + RDI_U8 *string_data = rdi_table_from_name(rdi, StringData, &string_data_size); + RDI_U32 off_raw = string_offs[idx]; + RDI_U32 opl_raw = string_offs[idx + 1]; + RDI_U32 opl = rdi_parse__min(opl_raw, string_data_size); + RDI_U32 off = rdi_parse__min(off_raw, opl); + result_base = string_data + off; + result_size = opl - off; + } } - *len_out = len_result; - return(result); + *len_out = result_size; + return result_base; } +//- index runs + RDI_PROC RDI_U32* -rdi_idx_run_from_first_count(RDI_Parsed *parsed, - RDI_U32 raw_first, RDI_U32 raw_count, - RDI_U32 *n_out){ +rdi_idx_run_from_first_count(RDI_Parsed *rdi, RDI_U32 raw_first, RDI_U32 raw_count, RDI_U32 *n_out) +{ + RDI_U64 idx_run_count = 0; + RDI_U32 *idx_run_data = rdi_table_from_name(rdi, IndexRuns, &idx_run_count); RDI_U32 raw_opl = raw_first + raw_count; - RDI_U32 opl = rdi_parse__min(raw_opl, parsed->idx_run_count); + RDI_U32 opl = rdi_parse__min(raw_opl, idx_run_count); RDI_U32 first = rdi_parse__min(raw_first, opl); - RDI_U32 *result = 0; - if (first < parsed->idx_run_count){ - result = parsed->idx_run_data + first; + if(first < idx_run_count) + { + result = 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 *rdi, RDI_LineTable *line_table, RDI_ParsedLineTable *out) +{ + //- rjf: extract top-level line info tables + RDI_U64 all_voffs_count = 0; + RDI_U64 *all_voffs = rdi_table_from_name(rdi, LineInfoVOffs, &all_voffs_count); + RDI_U64 *all_voffs_opl = all_voffs + all_voffs_count; + RDI_U64 all_lines_count = 0; + RDI_Line *all_lines = rdi_table_from_name(rdi, LineInfoLines, &all_lines_count); + RDI_Line *all_lines_opl = all_lines + all_lines_count; + RDI_U64 all_cols_count = 0; + RDI_Column *all_cols = rdi_table_from_name(rdi, 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_range_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff, RDI_U64 *n_out) { RDI_U64 result = 0; - if (line_info->count > 0 && line_info->voffs[0] <= voff && voff < line_info->voffs[line_info->count - 1]){ + RDI_U64 n = 0; + if(line_info->count > 0 && line_info->voffs[0] <= voff && voff < line_info->voffs[line_info->count - 1]) + { + //- rjf: find i such that: (vmap[i].voff <= voff) && (voff < vmap[i + 1].voff) // 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; + + //- rjf: scan leftward, to find shallowest line info matching this voff + for(;result != 0;) + { + if(line_info->voffs[result-1] == voff) + { + result -= 1; + } + else + { + break; + } + } + + //- rjf: scan rightward, to count # of line info with this voff + for(RDI_U64 idx = result; idx < line_info->count; idx += 1) + { + if(line_info->voffs[idx] == voff) + { + n += 1; + } + else + { + break; + } + } } - return(result); + if(n_out) + { + *n_out = n; + } + return result; +} + +RDI_PROC RDI_U64 +rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff) +{ + RDI_U64 count = 0; + RDI_U64 result = rdi_line_info_idx_range_from_voff(line_info, voff, &count); + return result; } RDI_PROC void -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_parsed_from_source_line_map(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_ParsedSourceLineMap *out) +{ + //- rjf: extract top-level line info tables + RDI_U64 all_nums_count = 0; + RDI_U32 *all_nums = rdi_table_from_name(rdi, SourceLineMapNumbers, &all_nums_count); + RDI_U32 *all_nums_opl = all_nums + all_nums_count; + RDI_U64 all_rngs_count = 0; + RDI_U32 *all_rngs = rdi_table_from_name(rdi, SourceLineMapRanges, &all_rngs_count); + RDI_U32 *all_rngs_opl = all_rngs + all_rngs_count; + RDI_U64 all_voffs_count = 0; + RDI_U64 *all_voffs = rdi_table_from_name(rdi, SourceLineMapVOffs, &all_voffs_count); + RDI_U64 *all_voffs_opl = all_voffs + all_voffs_count; - RDI_U64 range_count = 0; - RDI_U32 *ranges = (RDI_U32*) - rdi_data_from_dsec(p, srcfile->line_map_range_data_idx, sizeof(RDI_U32), - RDI_DataSectionTag_LineMapRanges, - &range_count); + //- rjf: extract ranges of top-level tables belonging to this line map + RDI_U32 *map_nums = all_nums + map->line_map_nums_base_idx; + RDI_U32 *map_rngs = all_rngs + map->line_map_range_base_idx; + RDI_U64 *map_voffs= all_voffs+ map->line_map_voff_base_idx; + RDI_U64 lines_count = (RDI_U64)map->line_count; + RDI_U64 voffs_count = (RDI_U64)map->voff_count; + if(map_nums >= all_nums_opl) {map_nums = all_nums; lines_count = 0;} + if(map_rngs >= all_rngs_opl) {map_rngs = all_rngs; lines_count = 0;} + if(map_voffs>= all_voffs_opl){map_voffs= all_voffs;voffs_count = 0;} - RDI_U64 voff_count = 0; - RDI_U64 *voffs = (RDI_U64*) - rdi_data_from_dsec(p, srcfile->line_map_voff_data_idx, sizeof(RDI_U64), - RDI_DataSectionTag_LineMapVoffs, - &voff_count); - - RDI_U32 count_a = (range_count > 0)?(range_count - 1):0; - RDI_U32 count_b = rdi_parse__min(count_a, num_count); - RDI_U32 count = rdi_parse__min(count_b, srcfile->line_map_count); - - out->nums = nums; - out->ranges = ranges; - out->voffs = voffs; - out->count = count; - out->voff_count = voff_count; + //- rjf: fill result + out->nums = map_nums; + out->ranges = map_rngs; + out->voffs = map_voffs; + out->count = lines_count; + out->voff_count = voffs_count; } -RDI_PROC RDI_U64* -rdi_line_voffs_from_num(RDI_ParsedLineMap *map, RDI_U32 linenum, RDI_U32 *n_out){ +RDI_PROC RDI_U64 * +rdi_line_voffs_from_num(RDI_ParsedSourceLineMap *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,102 +375,126 @@ 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_U64 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; +} + +RDI_PROC RDI_U64 +rdi_vmap_idx_from_section_kind_voff(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 voff) +{ + RDI_U64 vmaps_count = 0; + RDI_VMapEntry *vmaps = rdi_section_raw_table_from_kind(rdi, kind, &vmaps_count); + RDI_U64 result = rdi_vmap_idx_from_voff(vmaps, vmaps_count, voff); + return result; } //- name maps -RDI_PROC RDI_NameMap* -rdi_name_map_from_kind(RDI_Parsed *p, RDI_NameMapKind kind){ - RDI_NameMap *result = 0; - if (0 < kind && kind < RDI_NameMapKind_COUNT){ - result = p->name_maps_by_kind[kind]; - } - return(result); -} - RDI_PROC void -rdi_name_map_parse(RDI_Parsed *p, RDI_NameMap *mapptr, RDI_ParsedNameMap *out){ +rdi_parsed_from_name_map(RDI_Parsed *rdi, RDI_NameMap *mapptr, RDI_ParsedNameMap *out) +{ out->buckets = 0; out->bucket_count = 0; - if (mapptr != 0){ - out->buckets = (RDI_NameMapBucket*) - rdi_data_from_dsec(p, mapptr->bucket_data_idx, sizeof(RDI_NameMapBucket), - RDI_DataSectionTag_NameMapBuckets, &out->bucket_count); - out->nodes = (RDI_NameMapNode*) - rdi_data_from_dsec(p, mapptr->node_data_idx, sizeof(RDI_NameMapNode), - RDI_DataSectionTag_NameMapNodes, &out->node_count); + if(mapptr != 0) + { + RDI_U64 all_buckets_count = 0; + RDI_NameMapBucket *all_buckets = rdi_table_from_name(rdi, NameMapBuckets, &all_buckets_count); + RDI_U64 all_nodes_count = 0; + RDI_NameMapNode *all_nodes = rdi_table_from_name(rdi, NameMapNodes, &all_nodes_count); + out->buckets = all_buckets+mapptr->bucket_base_idx; + out->nodes = all_nodes+mapptr->node_base_idx; + out->bucket_count = mapptr->bucket_count; + out->node_count = mapptr->node_count; + if(mapptr->bucket_base_idx > all_buckets_count) + { + out->buckets = 0; + out->bucket_count = 0; + } + if(mapptr->node_base_idx > all_nodes_count) + { + out->nodes = 0; + out->node_count = 0; + } } } 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,76 +503,280 @@ 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); -} - -//- common helpers - -RDI_PROC RDI_U64 -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){ - RDI_Procedure *proc = p->procedures + proc_id; - RDI_U32 scope_id = proc->root_scope_idx; - if (0 < scope_id && scope_id < p->scopes_count){ - RDI_Scope *scope = p->scopes + scope_id; - if (scope->voff_range_first < scope->voff_range_opl && - scope->voff_range_first < p->scope_voffs_count){ - result = p->scope_voffs[scope->voff_range_first]; - } - } - } - return(result); + return result; } //////////////////////////////// -//~ RADDBG Parsing Helpers +//~ High-Level Composite Lookup Functions -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) +//- procedures + +RDI_PROC RDI_Procedure * +rdi_procedure_from_name(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size) { - void *result = 0; - RDI_U32 count_result = 0; - if(0 < idx && idx < parsed->dsec_count) + RDI_NameMap *map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures); + RDI_ParsedNameMap map_parsed = {0}; + rdi_parsed_from_name_map(rdi, map, &map_parsed); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map_parsed, name, name_size); + RDI_U32 id_count = 0; + RDI_U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); + RDI_U32 procedure_idx = 0; + if(id_count > 0) { - RDI_DataSection *ds = parsed->dsecs + idx; - if(ds->tag == expected_tag) - { - RDI_U64 encoded_opl = ds->off + ds->encoded_size; - if(encoded_opl <= parsed->raw_data_size) - { - count_result = ds->unpacked_size/item_size; - result = (parsed->raw_data + ds->off); - } - } + procedure_idx = ids[0]; } - *count_out = count_result; - return(result); + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, procedure_idx); + return procedure; +} + +RDI_PROC RDI_Procedure * +rdi_procedure_from_name_cstr(RDI_Parsed *rdi, char *cstr) +{ + RDI_Procedure *result = rdi_procedure_from_name(rdi, (RDI_U8 *)cstr, rdi_cstring_length(cstr)); + return result; +} + +RDI_PROC RDI_U8 * +rdi_name_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure, RDI_U64 *len_out) +{ + return rdi_string_from_idx(rdi, procedure->name_string_idx, len_out); +} + +RDI_PROC RDI_Scope * +rdi_root_scope_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure) +{ + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx); + return scope; +} + +RDI_PROC RDI_U64 +rdi_first_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure) +{ + RDI_Scope *scope = rdi_root_scope_from_procedure(rdi, procedure); + RDI_U64 result = rdi_first_voff_from_scope(rdi, scope); + return result; +} + +RDI_PROC RDI_U64 +rdi_opl_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure) +{ + RDI_Scope *scope = rdi_root_scope_from_procedure(rdi, procedure); + RDI_U64 result = rdi_opl_voff_from_scope(rdi, scope); + return result; +} + +RDI_PROC RDI_Procedure * +rdi_procedure_from_voff(RDI_Parsed *rdi, RDI_U64 voff) +{ + RDI_Scope *scope = rdi_scope_from_voff(rdi, voff); + RDI_Procedure *procedure = rdi_procedure_from_scope(rdi, scope); + return procedure; +} + +//- scopes + +RDI_PROC RDI_U64 +rdi_first_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope) +{ + RDI_U64 *voffs = rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_first); + RDI_U64 result = *voffs; + return result; +} + +RDI_PROC RDI_U64 +rdi_opl_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope) +{ + RDI_U64 *voffs = rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_opl); + RDI_U64 result = *voffs; + return result; +} + +RDI_PROC RDI_Scope * +rdi_scope_from_voff(RDI_Parsed *rdi, RDI_U64 voff) +{ + RDI_U32 idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, idx); + return scope; +} + +RDI_PROC RDI_Procedure * +rdi_procedure_from_scope(RDI_Parsed *rdi, RDI_Scope *scope) +{ + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, scope->proc_idx); + return procedure; +} + +//- units + +RDI_PROC RDI_Unit * +rdi_unit_from_voff(RDI_Parsed *rdi, RDI_U64 voff) +{ + RDI_U32 unit_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_UnitVMap, voff); + RDI_Unit *unit = rdi_element_from_name_idx(rdi, Units, unit_idx); + return unit; +} + +RDI_PROC RDI_LineTable * +rdi_line_table_from_unit(RDI_Parsed *rdi, RDI_Unit *unit) +{ + RDI_LineTable *line_table = rdi_element_from_name_idx(rdi, LineTables, unit->line_table_idx); + return line_table; +} + +//- line info + +RDI_PROC RDI_Line +rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff) +{ + RDI_Unit *unit = rdi_unit_from_voff(rdi, voff); + RDI_LineTable *line_table = rdi_line_table_from_unit(rdi, unit); + RDI_Line line = rdi_line_from_line_table_voff(rdi, line_table, voff); + return line; +} + +RDI_PROC RDI_Line +rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff) +{ + RDI_ParsedLineTable parsed = {0}; + rdi_parsed_from_line_table(rdi, line_table, &parsed); + RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&parsed, voff); + RDI_Line result = {0}; + if(line_info_idx < parsed.count) + { + result = parsed.lines[line_info_idx]; + } + return result; +} + +RDI_PROC RDI_SourceFile * +rdi_source_file_from_line(RDI_Parsed *rdi, RDI_Line *line) +{ + RDI_SourceFile *result = rdi_element_from_name_idx(rdi, SourceFiles, line->file_idx); + return result; +} + +//- source files + +RDI_PROC RDI_SourceFile * +rdi_source_file_from_normal_path(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size) +{ + RDI_NameMap *map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_NormalSourcePaths); + RDI_ParsedNameMap map_parsed = {0}; + rdi_parsed_from_name_map(rdi, map, &map_parsed); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &map_parsed, name, name_size); + RDI_U32 id_count = 0; + RDI_U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count); + RDI_U32 file_idx = 0; + if(id_count > 0) + { + file_idx = ids[0]; + } + RDI_SourceFile *file = rdi_element_from_name_idx(rdi, SourceFiles, file_idx); + return file; +} + +RDI_PROC RDI_SourceFile * +rdi_source_file_from_normal_path_cstr(RDI_Parsed *rdi, char *cstr) +{ + RDI_SourceFile *result = rdi_source_file_from_normal_path(rdi, (RDI_U8 *)cstr, rdi_cstring_length(cstr)); + return result; +} + +RDI_PROC RDI_U8 * +rdi_normal_path_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U64 *len_out) +{ + return rdi_string_from_idx(rdi, src_file->normal_full_path_string_idx, len_out); +} + +RDI_PROC RDI_FilePathNode * +rdi_file_path_node_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file) +{ + RDI_FilePathNode *result = rdi_element_from_name_idx(rdi, FilePathNodes, src_file->file_path_node_idx); + return result; +} + +RDI_PROC RDI_SourceLineMap * +rdi_source_line_map_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file) +{ + RDI_SourceLineMap *result = rdi_element_from_name_idx(rdi, SourceLineMaps, src_file->source_line_map_idx); + return result; +} + +RDI_PROC RDI_U64 +rdi_first_voff_from_source_file_line_num(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U32 line_num) +{ + RDI_SourceLineMap *source_line_map = rdi_source_line_map_from_source_file(rdi, src_file); + RDI_U64 voff = rdi_first_voff_from_source_line_map_num(rdi, source_line_map, line_num); + return voff; +} + +//- source line maps + +RDI_PROC RDI_U64 +rdi_first_voff_from_source_line_map_num(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_U32 line_num) +{ + RDI_ParsedSourceLineMap parsed = {0}; + rdi_parsed_from_source_line_map(rdi, map, &parsed); + RDI_U32 all_voffs_count = 0; + RDI_U64 *all_voffs = rdi_line_voffs_from_num(&parsed, line_num, &all_voffs_count); + RDI_U64 voff = 0; + if(all_voffs_count != 0) + { + voff = all_voffs[0]; + } + return voff; +} + +//- file path nodes + +RDI_PROC RDI_FilePathNode * +rdi_parent_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node) +{ + RDI_FilePathNode *result = rdi_element_from_name_idx(rdi, FilePathNodes, node->parent_path_node); + return result; +} + +RDI_PROC RDI_U8 * +rdi_name_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node, RDI_U64 *len_out) +{ + return rdi_string_from_idx(rdi, node->name_string_idx, len_out); +} + +//////////////////////////////// +//~ Parser Helpers + +RDI_PROC RDI_U64 +rdi_cstring_length(char *cstr) +{ + RDI_U64 result = 0; + for(;cstr[result] != 0; result += 1){} + return result; } diff --git a/src/lib_rdi_format/rdi_format_parse.h b/src/lib_rdi_format/rdi_format_parse.h index 66b29019..66a20cdc 100644 --- a/src/lib_rdi_format/rdi_format_parse.h +++ b/src/lib_rdi_format/rdi_format_parse.h @@ -1,105 +1,85 @@ // 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 +//////////////////////////////////////////////////////////////// +//~ Usage Samples +// +#if 0 +// Procedure Name -> Line +{ + RDI_Parsed *rdi = ...; + char *name = "mule_main"; + RDI_Procedure *procedure = rdi_procedure_from_name_cstr(rdi, name); // 1. name -> procedure + RDI_U64 procedure_first_voff = rdi_first_voff_from_procedure(rdi, procedure); // 2. procedure -> virtual offset + RDI_Line line = rdi_line_from_voff(rdi, procedure_first_voff); // 3. virtual offset -> line + RDI_SourceFile *file = rdi_source_file_from_line(rdi, &line); // 4. line -> source file + RDI_U64 file_path_size = 0; // 5. source file -> path + RDI_U8 *file_path = rdi_normal_path_from_source_file(rdi, file, &file_path_size); + printf("%s is at %.*s:%u\n", name, (int)file_path_size, file_path, line.line_num); +} -typedef struct RDI_Parsed{ - // raw data & data sections (part 1) - 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 - RDI_U8* string_data; - RDI_U64 string_data_size; - RDI_U32* string_offs; - RDI_U64 string_count; - RDI_U32* idx_run_data; - RDI_U32 idx_run_count; - - // directly readable by users - // (any of these may be empty and null even in 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_Unit* units; - RDI_U64 units_count; - RDI_VMapEntry* unit_vmap; - RDI_U64 unit_vmap_count; - RDI_TypeNode* type_nodes; - RDI_U64 type_nodes_count; - RDI_UDT* udts; - RDI_U64 udts_count; - RDI_Member* members; - RDI_U64 members_count; - RDI_EnumMember* enum_members; - RDI_U64 enum_members_count; - RDI_GlobalVariable* global_variables; - RDI_U64 global_variables_count; - RDI_VMapEntry* global_vmap; - RDI_U64 global_vmap_count; - RDI_ThreadVariable* thread_variables; - RDI_U64 thread_variables_count; - RDI_Procedure* procedures; - RDI_U64 procedures_count; - RDI_Scope* scopes; - RDI_U64 scopes_count; - RDI_U64* scope_voffs; - RDI_U64 scope_voffs_count; - RDI_VMapEntry* scope_vmap; - RDI_U64 scope_vmap_count; - RDI_Local* locals; - RDI_U64 locals_count; - RDI_LocationBlock* location_blocks; - RDI_U64 location_blocks_count; - RDI_U8* location_data; - RDI_U64 location_data_size; - RDI_NameMap* name_maps; - RDI_U64 name_maps_count; - - // other helpers - - RDI_NameMap* name_maps_by_kind[RDI_NameMapKind_COUNT]; - -} RDI_Parsed; +// Line -> Procedure Name +{ + RDI_Parsed *rdi = ...; + char *path = "c:/devel/raddebugger/src/mule/mule_main.cpp"; + RDI_U32 line_num = 2557; + RDI_SourceFile *file = rdi_source_file_from_normal_path_cstr(rdi, path); // 1. path -> source file + RDI_U64 voff = rdi_first_voff_from_source_file_line_num(rdi, file, line_num); // 2. (source file, line) -> virtual offset + RDI_Procedure *procedure = rdi_procedure_from_voff(rdi, voff); // 3. virtual offset -> procedure + RDI_U64 name_size = 0; // 4. procedure -> name + RDI_U8 *name = rdi_name_from_procedure(rdi, procedure, &name_size); + printf("%s:%u is inside %.*s\n", path, line_num, (int)name_size, name); +} +#endif -typedef enum{ +#ifndef RDI_FORMAT_PARSE_H +#define RDI_FORMAT_PARSE_H + +//////////////////////////////////////////////////////////////// +//~ 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; + RDI_ParseStatus_MissingRequiredSection = 4, +} +RDI_ParseStatus; -typedef struct RDI_ParsedLineInfo{ +typedef struct RDI_Parsed RDI_Parsed; +struct RDI_Parsed +{ + RDI_U8 *raw_data; + RDI_U64 raw_data_size; + RDI_Section *sections; + RDI_U64 sections_count; +}; + +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_ParsedSourceLineMap RDI_ParsedSourceLineMap; +struct RDI_ParsedSourceLineMap +{ // NOTE: Mapping LINE_NUMBER -> VOFFs // // * nums[i] gives a line number @@ -108,116 +88,137 @@ 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 -#if !defined(RDI_DISABLE_NILS) -static RDI_TopLevelInfo rdi_top_level_info_nil = {0}; -static RDI_BinarySection rdi_binary_section_nil = {0}; -static RDI_FilePathNode rdi_file_path_node_nil = {0}; -static RDI_SourceFile rdi_source_file_nil = {0}; -static RDI_Unit rdi_unit_nil = {0}; -static RDI_VMapEntry rdi_vmap_entry_nil = {0}; -static RDI_TypeNode rdi_type_node_nil = {0}; -static RDI_UDT rdi_udt_nil = {0}; -static RDI_Member rdi_member_nil = {0}; -static RDI_EnumMember rdi_enum_member_nil = {0}; -static RDI_GlobalVariable rdi_global_variable_nil = {0}; -static RDI_ThreadVariable rdi_thread_variable_nil = {0}; -static RDI_Procedure rdi_procedure_nil = {0}; -static RDI_Scope rdi_scope_nil = {0}; -static RDI_U64 rdi_voff_nil = 0; -static RDI_LocationBlock rdi_location_block_nil = {0}; -static RDI_Local rdi_local_nil = {0}; -#endif +static union +{ + RDI_TopLevelInfo top_level_info; + RDI_BinarySection binary_section; + RDI_FilePathNode file_path_node; + RDI_SourceFile source_file; + RDI_LineTable line_table; + RDI_SourceLineMap source_line_map; + RDI_Line line; + RDI_Column column; + RDI_Unit unit; + RDI_VMapEntry vmap_entry; + RDI_TypeNode type_node; + RDI_UDT udt; + RDI_Member member; + RDI_EnumMember enum_member; + RDI_GlobalVariable global_variable; + RDI_ThreadVariable thread_variable; + RDI_Procedure procedure; + RDI_Scope scope; + RDI_U64 voff; + RDI_LocationBlock location_block; + RDI_Local local; +} +rdi_nil_element_union = {0}; //////////////////////////////// -//~ RADDBG Parse API +//~ Top-Level Parsing API -RDI_PROC RDI_ParseStatus -rdi_parse(RDI_U8 *data, RDI_U64 size, RDI_Parsed *out); +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); +//////////////////////////////// +//~ Base Parsed Info Extraction Helpers -RDI_PROC RDI_U8* -rdi_string_from_idx(RDI_Parsed *parsed, RDI_U32 idx, RDI_U64 *len_out); +//- section table/element raw data extraction +RDI_PROC void *rdi_section_raw_data_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_SectionEncoding *encoding_out, RDI_U64 *size_out); +RDI_PROC void *rdi_section_raw_table_from_kind(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 *count_out); +RDI_PROC void *rdi_section_raw_element_from_kind_idx(RDI_Parsed *rdi, RDI_SectionKind kind, RDI_U64 idx); +#define rdi_table_from_name(rdi, name, count_out) (RDI_SectionElementType_##name *)rdi_section_raw_table_from_kind((rdi), RDI_SectionKind_##name, (count_out)) +#define rdi_element_from_name_idx(rdi, name, idx) (RDI_SectionElementType_##name *)rdi_section_raw_element_from_kind_idx((rdi), RDI_SectionKind_##name, (idx)) -RDI_PROC RDI_U32* -rdi_idx_run_from_first_count(RDI_Parsed *parsed, RDI_U32 first, RDI_U32 raw_count, - RDI_U32 *n_out); +//- info about whole parse +RDI_PROC RDI_U64 rdi_decompressed_size_from_parsed(RDI_Parsed *rdi); -//- 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) +//- strings +RDI_PROC RDI_U8 *rdi_string_from_idx(RDI_Parsed *rdi, RDI_U32 idx, RDI_U64 *len_out); + +//- index runs +RDI_PROC RDI_U32 *rdi_idx_run_from_first_count(RDI_Parsed *rdi, RDI_U32 raw_first, RDI_U32 raw_count, RDI_U32 *n_out); //- 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); +RDI_PROC void rdi_parsed_from_line_table(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_ParsedLineTable *out); +RDI_PROC RDI_U64 rdi_line_info_idx_range_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff, RDI_U64 *n_out); +RDI_PROC RDI_U64 rdi_line_info_idx_from_voff(RDI_ParsedLineTable *line_info, RDI_U64 voff); +RDI_PROC void rdi_parsed_from_source_line_map(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_ParsedSourceLineMap *out); +RDI_PROC RDI_U64 *rdi_line_voffs_from_num(RDI_ParsedSourceLineMap *map, RDI_U32 linenum, RDI_U32 *n_out); +//- vmap lookups +RDI_PROC RDI_U64 rdi_vmap_idx_from_voff(RDI_VMapEntry *vmap, RDI_U64 vmap_count, RDI_U64 voff); //- name maps -RDI_PROC RDI_NameMap* -rdi_name_map_from_kind(RDI_Parsed *p, RDI_NameMapKind kind); - -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); - - +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); //////////////////////////////// -//~ RADDBG Parsing Helpers +//~ High-Level Composite Lookup Functions -#define rdi_parse__extract_primary(p,outptr,outn,pritag) \ -( (*(void**)&(outptr)) = \ -rdi_data_from_dsec((p),(p)->dsec_idx[pritag],sizeof(*(outptr)),(pritag),(outn)) ) +//- procedures +RDI_PROC RDI_Procedure *rdi_procedure_from_name(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size); +RDI_PROC RDI_Procedure *rdi_procedure_from_name_cstr(RDI_Parsed *rdi, char *cstr); +RDI_PROC RDI_U8 *rdi_name_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure, RDI_U64 *len_out); +RDI_PROC RDI_Scope *rdi_root_scope_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure); +RDI_PROC RDI_U64 rdi_first_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure); +RDI_PROC RDI_U64 rdi_opl_voff_from_procedure(RDI_Parsed *rdi, RDI_Procedure *procedure); +RDI_PROC RDI_Procedure *rdi_procedure_from_voff(RDI_Parsed *rdi, RDI_U64 voff); -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); +//- scopes +RDI_PROC RDI_U64 rdi_first_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope); +RDI_PROC RDI_U64 rdi_opl_voff_from_scope(RDI_Parsed *rdi, RDI_Scope *scope); +RDI_PROC RDI_Scope *rdi_scope_from_voff(RDI_Parsed *rdi, RDI_U64 voff); +RDI_PROC RDI_Procedure *rdi_procedure_from_scope(RDI_Parsed *rdi, RDI_Scope *scope); + +//- units +RDI_PROC RDI_Unit *rdi_unit_from_voff(RDI_Parsed *rdi, RDI_U64 voff); +RDI_PROC RDI_LineTable *rdi_line_table_from_unit(RDI_Parsed *rdi, RDI_Unit *unit); + +//- line tables +RDI_PROC RDI_Line rdi_line_from_voff(RDI_Parsed *rdi, RDI_U64 voff); +RDI_PROC RDI_Line rdi_line_from_line_table_voff(RDI_Parsed *rdi, RDI_LineTable *line_table, RDI_U64 voff); +RDI_PROC RDI_SourceFile *rdi_source_file_from_line(RDI_Parsed *rdi, RDI_Line *line); + +//- source files +RDI_PROC RDI_SourceFile *rdi_source_file_from_normal_path(RDI_Parsed *rdi, RDI_U8 *name, RDI_U64 name_size); +RDI_PROC RDI_SourceFile *rdi_source_file_from_normal_path_cstr(RDI_Parsed *rdi, char *cstr); +RDI_PROC RDI_U8 *rdi_normal_path_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U64 *len_out); +RDI_PROC RDI_FilePathNode *rdi_file_path_node_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file); +RDI_PROC RDI_SourceLineMap *rdi_source_line_map_from_source_file(RDI_Parsed *rdi, RDI_SourceFile *src_file); +RDI_PROC RDI_U64 rdi_first_voff_from_source_file_line_num(RDI_Parsed *rdi, RDI_SourceFile *src_file, RDI_U32 line_num); + +//- source line maps +RDI_PROC RDI_U64 rdi_first_voff_from_source_line_map_num(RDI_Parsed *rdi, RDI_SourceLineMap *map, RDI_U32 line_num); + +//- file path nodes +RDI_PROC RDI_FilePathNode *rdi_parent_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node); +RDI_PROC RDI_U8 *rdi_name_from_file_path_node(RDI_Parsed *rdi, RDI_FilePathNode *node, RDI_U64 *len_out); + +//////////////////////////////// +//~ Parser Helpers #define rdi_parse__min(a,b) (((a)<(b))?(a):(b)) +RDI_PROC RDI_U64 rdi_cstring_length(char *cstr); -#endif // RDI_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..f491dd31 100644 --- a/src/lib_rdi_make/rdi_make.c +++ b/src/lib_rdi_make/rdi_make.c @@ -90,7 +90,7 @@ rdim_scratch_begin_fallback(RDIM_Arena **conflicts, RDI_U64 conflicts_count) rdim_thread_scratches[1] = rdim_arena_alloc(); } RDIM_Arena *arena = 0; - for(RDI_U64 scratch_idx = 0; + for(RDI_U64 scratch_idx = 0; scratch_idx < sizeof(rdim_thread_scratches)/sizeof(rdim_thread_scratches[0]); scratch_idx += 1) { @@ -480,7 +480,7 @@ rdim_idx_from_src_file(RDIM_SrcFile *src_file) RDI_U64 idx = 0; if(src_file != 0 && src_file->chunk != 0) { - idx = src_file->chunk->base_idx + (src_file - src_file->chunk->v) + 1; + idx = (src_file->chunk->base_idx + (src_file - src_file->chunk->v) + 1); } return idx; } @@ -509,9 +509,89 @@ rdim_src_file_chunk_list_concat_in_place(RDIM_SrcFileChunkList *dst, RDIM_SrcFil RDI_PROC void rdim_src_file_push_line_sequence(RDIM_Arena *arena, RDIM_SrcFileChunkList *src_files, RDIM_SrcFile *src_file, RDIM_LineSequence *seq) { + if(src_file->first_line_map_fragment == 0) + { + src_files->source_line_map_count += 1; + } RDIM_SrcFileLineMapFragment *fragment = rdim_push_array(arena, RDIM_SrcFileLineMapFragment, 1); fragment->seq = seq; RDIM_SLLQueuePush(src_file->first_line_map_fragment, src_file->last_line_map_fragment, fragment); + src_files->total_line_count += seq->line_count; +} + +//////////////////////////////// +//~ 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; } //////////////////////////////// @@ -569,15 +649,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 @@ -762,6 +833,61 @@ rdim_symbol_chunk_list_concat_in_place(RDIM_SymbolChunkList *dst, RDIM_SymbolChu rdim_memzero_struct(to_push); } +//////////////////////////////// +//~ rjf: [Building] Inline Site Info Building + +RDI_PROC RDIM_InlineSite * +rdim_inline_site_chunk_list_push(RDIM_Arena *arena, RDIM_InlineSiteChunkList *list, RDI_U64 cap) +{ + RDIM_InlineSiteChunkNode *n = list->last; + if(n == 0 || n->count >= n->cap) + { + n = rdim_push_array(arena, RDIM_InlineSiteChunkNode, 1); + n->cap = cap; + n->base_idx = list->total_count; + n->v = rdim_push_array(arena, RDIM_InlineSite, n->cap); + RDIM_SLLQueuePush(list->first, list->last, n); + list->chunk_count += 1; + } + RDIM_InlineSite *result = &n->v[n->count]; + result->chunk = n; + n->count += 1; + list->total_count += 1; + return result; +} + +RDI_PROC RDI_U64 +rdim_idx_from_inline_site(RDIM_InlineSite *inline_site) +{ + RDI_U64 idx = 0; + if(inline_site != 0 && inline_site->chunk != 0) + { + idx = inline_site->chunk->base_idx + (inline_site - inline_site->chunk->v) + 1; + } + return idx; +} + +RDI_PROC void +rdim_inline_site_chunk_list_concat_in_place(RDIM_InlineSiteChunkList *dst, RDIM_InlineSiteChunkList *to_push) +{ + for(RDIM_InlineSiteChunkNode *n = to_push->first; n != 0; n = n->next) + { + n->base_idx += dst->total_count; + } + if(dst->last != 0 && to_push->first != 0) + { + dst->last->next = to_push->first; + dst->last = to_push->last; + dst->chunk_count += to_push->chunk_count; + dst->total_count += to_push->total_count; + } + else if(dst->first == 0) + { + rdim_memcpy_struct(dst, to_push); + } + rdim_memzero_struct(to_push); +} + //////////////////////////////// //~ rjf: [Building] Scope Info Building @@ -983,88 +1109,6 @@ rdim_location_set_push_case(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM scopes->location_count +=1; } -//////////////////////////////// -//~ rjf: [Baking Helpers] Baked File Layout Calculations - -RDI_PROC RDI_U64 -rdim_bake_section_count_from_params(RDIM_BakeParams *params) -{ - RDI_U64 section_count = 0; - { - section_count += RDI_DataSectionTag_PRIMARY_COUNT; - section_count += 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 - section_count += RDI_NameMapKind_COUNT-1; // PER-NAME-MAP buckets section - section_count += RDI_NameMapKind_COUNT-1; // PER-NAME-MAP nodes section - } - return section_count; -} - -RDI_PROC RDI_U64 -rdim_bake_section_idx_from_params_tag_idx(RDIM_BakeParams *params, RDI_DataSectionTag tag, RDI_U64 idx) -{ - RDI_U64 result = 0; - if(tag < RDI_DataSectionTag_PRIMARY_COUNT) - { - result = (RDI_U64)tag; - } - else switch(tag) - { - default:{}break; - - //- rjf: per-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; - }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; - }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; - }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); - }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); - }break; - } - return result; -} - //////////////////////////////// //~ rjf: [Baking Helpers] Baked VMap Building @@ -1434,20 +1478,23 @@ rdim_bake_string_map_tight_from_loose(RDIM_Arena *arena, RDIM_BakeStringMapTopol return m; } -RDI_PROC RDI_U64 +RDI_PROC RDI_U32 rdim_bake_idx_from_string(RDIM_BakeStringMapTight *map, RDIM_String8 string) { - RDI_U64 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) + RDI_U32 idx = 0; + 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; + } } } } @@ -1607,7 +1654,12 @@ RDI_PROC RDI_U32 rdim_bake_path_node_idx_from_string(RDIM_BakePathTree *tree, RDIM_String8 string) { RDIM_BakePathNode *path_node = rdim_bake_path_node_from_string(tree, string); - return path_node ? path_node->idx : 0; + RDI_U32 result = 0; + if(path_node != 0) + { + result = path_node->idx; + } + return result; } RDI_PROC RDIM_BakePathNode * @@ -1744,11 +1796,11 @@ rdim_bake_section_list_push(RDIM_Arena *arena, RDIM_BakeSectionList *list) } RDI_PROC RDIM_BakeSection * -rdim_bake_section_list_push_new_unpacked(RDIM_Arena *arena, RDIM_BakeSectionList *list, void *data, RDI_U64 size, RDI_DataSectionTag tag, RDI_U64 tag_idx) +rdim_bake_section_list_push_new_unpacked(RDIM_Arena *arena, RDIM_BakeSectionList *list, void *data, RDI_U64 size, RDI_SectionKind tag, RDI_U64 tag_idx) { RDIM_BakeSection *section = rdim_bake_section_list_push(arena, list); section->data = data; - section->encoding = RDI_DataSectionEncoding_Unpacked; + section->encoding = RDI_SectionEncoding_Unpacked; section->encoded_size = size; section->unpacked_size = size; section->tag = tag; @@ -1781,6 +1833,7 @@ RDI_PROC void rdim_bake_string_map_loose_push_top_level_info(RDIM_Arena *arena, RDIM_BakeStringMapTopology *top, RDIM_BakeStringMapLoose *map, RDIM_TopLevelInfo *tli) { rdim_bake_string_map_loose_insert(arena, top, map, 1, tli->exe_name); + rdim_bake_string_map_loose_insert(arena, top, map, 1, tli->producer_name); } RDI_PROC void @@ -2012,8 +2065,8 @@ rdim_bake_name_map_from_kind_params(RDIM_Arena *arena, RDI_NameMapKind kind, RDI { for(RDI_U64 idx = 0; idx < n->count; idx += 1) { - RDI_U32 src_file_idx = (RDI_U32)rdim_idx_from_src_file(&n->v[idx]); // TODO(rjf): @u64_to_u32 - rdim_bake_name_map_push(arena, map, n->v[idx].normal_full_path, src_file_idx); + RDI_U64 src_file_idx = rdim_idx_from_src_file(&n->v[idx]); + rdim_bake_name_map_push(arena, map, n->v[idx].normal_full_path, (RDI_U32)src_file_idx); // TODO(rjf): @u64_to_u32 } } }break; @@ -2130,325 +2183,226 @@ rdim_bake_path_tree_from_params(RDIM_Arena *arena, RDIM_BakeParams *params) } //////////////////////////////// -//~ rjf: [Baking] Build Artifacts -> Data Section Lists +//~ rjf: [Baking] Build Artifacts -> Baked Versions -//- rjf: top-level info +//- rjf: partial/joinable baking functions -RDI_PROC RDIM_BakeSectionList -rdim_bake_top_level_info_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params) +RDI_PROC RDIM_NameMapBakeResult +rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *src) { - RDIM_BakeSectionList sections = {0}; - RDI_TopLevelInfo *dst_tli = rdim_push_array(arena, RDI_TopLevelInfo, 1); - RDIM_TopLevelInfo *src_tli = ¶ms->top_level_info; - dst_tli->arch = src_tli->arch; - dst_tli->exe_name_string_idx = rdim_bake_idx_from_string(strings, src_tli->exe_name); - dst_tli->exe_hash = src_tli->exe_hash; - dst_tli->voff_max = src_tli->voff_max; - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_tli, sizeof(*dst_tli), RDI_DataSectionTag_TopLevelInfo, 0); - return sections; -} - -//- rjf: binary sections - -RDI_PROC RDIM_BakeSectionList -rdim_bake_binary_section_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params) -{ - RDIM_BakeSectionList sections = {0}; - RDIM_BinarySectionList *src_list = ¶ms->binary_sections; - RDI_BinarySection *dst_base = rdim_push_array(arena, RDI_BinarySection, src_list->count+1); - U64 dst_idx = 1; - for(RDIM_BinarySectionNode *src_n = src_list->first; src_n != 0; src_n = src_n->next, dst_idx += 1) + RDIM_NameMapBakeResult result = {0}; + if(src->name_count != 0) { - RDIM_BinarySection *src = &src_n->v; - RDI_BinarySection *dst = &dst_base[dst_idx]; - dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->flags = src->flags; - dst->voff_first = src->voff_first; - dst->voff_opl = src->voff_opl; - dst->foff_first = src->foff_first; - dst->foff_opl = src->foff_opl; - } - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_base, sizeof(*dst_base)*dst_idx, RDI_DataSectionTag_BinarySections, 0); - return sections; -} - -//- rjf: units - -RDI_PROC RDIM_BakeSectionList -rdim_bake_section_list_from_unit(RDIM_Arena *arena, RDIM_Unit *unit) -{ - RDIM_BakeSectionList sections = {0}; - - //////////////////////// - //- rjf: produce combined unit line info - // - RDI_U64 *unit_voffs = 0; - RDI_Line *unit_lines = 0; - RDI_U16 *unit_cols = 0; - RDI_U32 unit_line_count = 0; - RDIM_ProfScope("produce combined unit line info") - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - //- rjf: gather up all line info into two arrays: - // - // [1] keys: sortable array; pairs voffs with line info records; null records are sequence enders - // [2] recs: contains all the source coordinates for a range of voffs - // - typedef struct RDIM_LineRec RDIM_LineRec; - struct RDIM_LineRec + RDI_U32 baked_buckets_count = src->name_count; + RDI_U32 baked_nodes_count = src->name_count; + RDI_NameMapBucket *baked_buckets = rdim_push_array(arena, RDI_NameMapBucket, baked_buckets_count); + RDI_NameMapNode *baked_nodes = rdim_push_array_no_zero(arena, RDI_NameMapNode, baked_nodes_count); { - RDI_U32 file_id; - RDI_U32 line_num; - RDI_U16 col_first; - RDI_U16 col_opl; - }; - RDI_U64 line_count = 0; - RDI_U64 seq_count = 0; - for(RDIM_LineSequenceNode *seq_n = unit->line_sequences.first; seq_n != 0; seq_n = seq_n->next) - { - seq_count += 1; - line_count += seq_n->v.line_count; - } - RDI_U64 key_count = line_count + seq_count; - RDIM_SortKey *line_keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, key_count); - RDIM_LineRec *line_recs = rdim_push_array_no_zero(scratch.arena, RDIM_LineRec, line_count); - { - RDIM_SortKey *key_ptr = line_keys; - RDIM_LineRec *rec_ptr = line_recs; - for(RDIM_LineSequenceNode *seq_n = unit->line_sequences.first; seq_n != 0; seq_n = seq_n->next) - { - RDIM_LineSequence *seq = &seq_n->v; - for(RDI_U64 line_idx = 0; line_idx < seq->line_count; line_idx += 1) - { - key_ptr->key = seq->voffs[line_idx]; - key_ptr->val = rec_ptr; - key_ptr += 1; - rec_ptr->file_id = (RDI_U32)rdim_idx_from_src_file(seq->src_file); // TODO(rjf): @u64_to_u32 - rec_ptr->line_num = seq->line_nums[line_idx]; - if(seq->col_nums != 0) - { - rec_ptr->col_first = seq->col_nums[line_idx*2]; - rec_ptr->col_opl = seq->col_nums[line_idx*2 + 1]; - } - rec_ptr += 1; - } - key_ptr->key = seq->voffs[seq->line_count]; - key_ptr->val = 0; - key_ptr += 1; - } - } - - //- rjf: sort - RDIM_SortKey *sorted_line_keys = 0; - RDIM_ProfScope("sort") - { - sorted_line_keys = rdim_sort_key_array(scratch.arena, line_keys, key_count); - } - - // TODO(rjf): do a pass over sorted keys to make sure duplicate keys - // are sorted with null record first, and no more than one null - // record and one non-null record - - //- rjf: arrange output - RDI_U64 *arranged_voffs = rdim_push_array_no_zero(arena, RDI_U64, key_count + 1); - RDI_Line *arranged_lines = rdim_push_array_no_zero(arena, RDI_Line, key_count); - RDIM_ProfScope("arrange output") - { - for(RDI_U64 i = 0; i < key_count; i += 1) - { - arranged_voffs[i] = sorted_line_keys[i].key; - } - arranged_voffs[key_count] = ~0ull; - for(RDI_U64 i = 0; i < key_count; i += 1) - { - RDIM_LineRec *rec = (RDIM_LineRec*)sorted_line_keys[i].val; - if(rec != 0) - { - arranged_lines[i].file_idx = rec->file_id; - arranged_lines[i].line_num = rec->line_num; - } - else - { - arranged_lines[i].file_idx = 0; - arranged_lines[i].line_num = 0; - } - } - } - - //- rjf: fill output - unit_voffs = arranged_voffs; - unit_lines = arranged_lines; - unit_cols = 0; - unit_line_count = key_count; - rdim_scratch_end(scratch); - } - - //////////////////////// - //- rjf: build line info sections - // - U64 unit_idx = rdim_idx_from_unit(unit); - rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_voffs, sizeof(RDI_U64)*(unit_line_count+1), RDI_DataSectionTag_LineInfoVoffs, unit_idx); - rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_lines, sizeof(RDI_Line)*unit_line_count, RDI_DataSectionTag_LineInfoData, unit_idx); - if(unit_cols != 0) - { - rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_cols, sizeof(RDI_Column)*unit_line_count, RDI_DataSectionTag_LineInfoColumns, unit_idx); - } - - return sections; -} - -RDI_PROC RDIM_BakeSectionList -rdim_bake_unit_top_level_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params) -{ - RDIM_BakeSectionList sections = {0}; - RDI_Unit *dst_base = rdim_push_array(arena, RDI_Unit, params->units.total_count+1); - RDI_U64 dst_idx = 1; - for(RDIM_UnitChunkNode *src_n = params->units.first; src_n != 0; src_n = src_n->next) - { - for(RDI_U64 src_chunk_idx = 0; src_chunk_idx < src_n->count; src_chunk_idx += 1, dst_idx += 1) - { - RDIM_Unit *src = &src_n->v[src_chunk_idx]; - RDI_Unit *dst = &dst_base[dst_idx]; + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - //////////////////////// - //- rjf: produce combined unit line info - // - RDI_U64 *unit_voffs = 0; - RDI_Line *unit_lines = 0; - RDI_U16 *unit_cols = 0; - RDI_U32 unit_line_count = 0; - RDIM_ProfScope("produce combined unit line info") + // rjf: setup the final bucket layouts + typedef struct RDIM_NameMapSemiNode RDIM_NameMapSemiNode; + struct RDIM_NameMapSemiNode { - 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 + RDIM_NameMapSemiNode *next; + RDIM_BakeNameMapNode *node; + }; + typedef struct RDIM_NameMapSemiBucket RDIM_NameMapSemiBucket; + struct RDIM_NameMapSemiBucket + { + RDIM_NameMapSemiNode *first; + RDIM_NameMapSemiNode *last; + RDI_U64 count; + }; + RDIM_NameMapSemiBucket *sbuckets = rdim_push_array(scratch.arena, RDIM_NameMapSemiBucket, baked_buckets_count); + for(RDIM_BakeNameMapNode *node = src->first; + node != 0; + node = node->order_next) + { + RDI_U64 hash = rdi_hash(node->string.str, node->string.size); + RDI_U64 bi = hash%baked_buckets_count; + RDIM_NameMapSemiNode *snode = rdim_push_array(scratch.arena, RDIM_NameMapSemiNode, 1); + SLLQueuePush(sbuckets[bi].first, sbuckets[bi].last, snode); + snode->node = node; + sbuckets[bi].count += 1; + } + + // rjf: convert to serialized buckets & nodes + { + RDI_NameMapBucket *bucket_ptr = baked_buckets; + RDI_NameMapNode *node_ptr = baked_nodes; + for(RDI_U32 i = 0; i < baked_buckets_count; i += 1, bucket_ptr += 1) { - RDI_U32 file_id; - RDI_U32 line_num; - RDI_U16 col_first; - RDI_U16 col_opl; - }; - RDI_U64 line_count = 0; - RDI_U64 seq_count = 0; - for(RDIM_LineSequenceNode *seq_n = src->line_sequences.first; seq_n != 0; seq_n = seq_n->next) - { - seq_count += 1; - line_count += seq_n->v.line_count; - } - RDI_U64 key_count = line_count + seq_count; - RDIM_SortKey *line_keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, key_count); - RDIM_LineRec *line_recs = rdim_push_array_no_zero(scratch.arena, RDIM_LineRec, line_count); - { - RDIM_SortKey *key_ptr = line_keys; - RDIM_LineRec *rec_ptr = line_recs; - for(RDIM_LineSequenceNode *seq_n = src->line_sequences.first; seq_n != 0; seq_n = seq_n->next) + bucket_ptr->first_node = (RDI_U32)((RDI_U64)(node_ptr - baked_nodes)); + bucket_ptr->node_count = sbuckets[i].count; + for(RDIM_NameMapSemiNode *snode = sbuckets[i].first; + snode != 0; + snode = snode->next) { - RDIM_LineSequence *seq = &seq_n->v; - for(RDI_U64 line_idx = 0; line_idx < seq->line_count; line_idx += 1) + RDIM_BakeNameMapNode *node = snode->node; + + // rjf: cons name and index(es) + RDI_U32 string_idx = rdim_bake_idx_from_string(strings, node->string); + RDI_U32 match_count = node->val_count; + RDI_U32 idx = 0; + if(match_count == 1) { - key_ptr->key = seq->voffs[line_idx]; - key_ptr->val = rec_ptr; - key_ptr += 1; - rec_ptr->file_id = (RDI_U32)rdim_idx_from_src_file(seq->src_file); // TODO(rjf): @u64_to_u32 - rec_ptr->line_num = seq->line_nums[line_idx]; - if(seq->col_nums != 0) - { - rec_ptr->col_first = seq->col_nums[line_idx*2]; - rec_ptr->col_opl = seq->col_nums[line_idx*2 + 1]; - } - rec_ptr += 1; - } - key_ptr->key = seq->voffs[seq->line_count]; - key_ptr->val = 0; - key_ptr += 1; - } - } - - //- rjf: sort - RDIM_SortKey *sorted_line_keys = 0; - RDIM_ProfScope("sort") - { - sorted_line_keys = rdim_sort_key_array(scratch.arena, line_keys, key_count); - } - - // TODO(rjf): do a pass over sorted keys to make sure duplicate keys - // are sorted with null record first, and no more than one null - // record and one non-null record - - //- rjf: arrange output - RDI_U64 *arranged_voffs = rdim_push_array_no_zero(arena, RDI_U64, key_count + 1); - RDI_Line *arranged_lines = rdim_push_array_no_zero(arena, RDI_Line, key_count); - RDIM_ProfScope("arrange output") - { - for(RDI_U64 i = 0; i < key_count; i += 1) - { - arranged_voffs[i] = sorted_line_keys[i].key; - } - arranged_voffs[key_count] = ~0ull; - for(RDI_U64 i = 0; i < key_count; i += 1) - { - RDIM_LineRec *rec = (RDIM_LineRec*)sorted_line_keys[i].val; - if(rec != 0) - { - arranged_lines[i].file_idx = rec->file_id; - arranged_lines[i].line_num = rec->line_num; + idx = node->val_first->val[0]; } else { - arranged_lines[i].file_idx = 0; - arranged_lines[i].line_num = 0; + RDI_U64 temp_pos = rdim_arena_pos(scratch.arena); + RDI_U32 *idx_run = rdim_push_array_no_zero(scratch.arena, RDI_U32, match_count); + RDI_U32 *idx_ptr = idx_run; + for(RDIM_BakeNameMapValNode *idxnode = node->val_first; + idxnode != 0; + idxnode = idxnode->next) + { + for(RDI_U32 i = 0; i < sizeof(idxnode->val)/sizeof(idxnode->val[0]); i += 1) + { + if(idxnode->val[i] == 0) + { + goto dblbreak; + } + *idx_ptr = idxnode->val[i]; + idx_ptr += 1; + } + } + dblbreak:; + idx = rdim_bake_idx_from_idx_run(idx_runs, idx_run, match_count); + rdim_arena_pop_to(scratch.arena, temp_pos); } + + // rjf: write to node + node_ptr->string_idx = string_idx; + node_ptr->match_count = match_count; + node_ptr->match_idx_or_idx_run_first = idx; + node_ptr += 1; } } - - //- rjf: fill output - unit_voffs = arranged_voffs; - unit_lines = arranged_lines; - unit_cols = 0; - unit_line_count = key_count; - rdim_scratch_end(scratch); } - - //////////////////////// - //- rjf: build line info sections - // - rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_voffs, sizeof(RDI_U64)*(unit_line_count+1), RDI_DataSectionTag_LineInfoVoffs, dst_idx); - rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_lines, sizeof(RDI_Line)*unit_line_count, RDI_DataSectionTag_LineInfoData, dst_idx); - if(unit_cols != 0) - { - rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_cols, sizeof(RDI_Column)*unit_line_count, RDI_DataSectionTag_LineInfoColumns, dst_idx); - } - - //////////////////////// - //- rjf: fill output - // - dst->unit_name_string_idx = rdim_bake_idx_from_string(strings, src->unit_name); - dst->compiler_name_string_idx = rdim_bake_idx_from_string(strings, src->compiler_name); - dst->source_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->source_file); - dst->object_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->object_file); - dst->archive_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->archive_file); - dst->build_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->build_path); - dst->language = src->language; - dst->line_info_voffs_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_LineInfoVoffs, dst_idx); // TODO(rjf): @u64_to_u32 - dst->line_info_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_LineInfoData, dst_idx); // TODO(rjf): @u64_to_u32 - dst->line_info_col_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_LineInfoColumns, dst_idx); // TODO(rjf): @u64_to_u32 + rdim_scratch_end(scratch); } + + // rjf: sections for buckets/nodes + result.buckets = baked_buckets; + result.buckets_count = baked_buckets_count; + result.nodes = baked_nodes; + result.nodes_count = baked_nodes_count; } - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_base, sizeof(*dst_base)*dst_idx, RDI_DataSectionTag_Units, 0); - return sections; + return result; } -//- rjf: unit vmap +//- rjf: partial bakes -> final bake functions -RDI_PROC RDIM_BakeSectionList -rdim_bake_unit_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params) +RDI_PROC RDIM_NameMapBakeResult +rdim_name_map_bake_results_combine(RDIM_Arena *arena, RDIM_NameMapBakeResult *results, RDI_U64 results_count) +{ + RDIM_NameMapBakeResult result = {0}; + { + //- rjf: count needed # of buckets/nodes + RDI_U64 all_buckets_count = 0; + RDI_U64 all_nodes_count = 0; + for(RDI_U64 idx = 0; idx < results_count; idx += 1) + { + all_buckets_count += results[idx].buckets_count; + all_nodes_count += results[idx].nodes_count; + } + + //- rjf: allocate outputs + result.buckets_count = all_buckets_count; + result.buckets = rdim_push_array_no_zero(arena, RDI_NameMapBucket, result.buckets_count); + result.nodes_count = all_nodes_count; + result.nodes = rdim_push_array_no_zero(arena, RDI_NameMapNode, result.nodes_count); + + //- rjf: fill outputs + { + RDI_U64 buckets_off = 0; + RDI_U64 nodes_off = 0; + for(RDI_U64 idx = 0; idx < results_count; idx += 1) + { + rdim_memcpy(result.buckets + buckets_off, results[idx].buckets, sizeof(result.buckets[0])*results[idx].buckets_count); + rdim_memcpy(result.nodes + nodes_off, results[idx].nodes, sizeof(result.nodes[0])*results[idx].nodes_count); + buckets_off += results[idx].buckets_count; + nodes_off += results[idx].nodes_count; + } + } + } + return result; +} + +//- rjf: independent (top-level, global) baking functions + +RDI_PROC RDIM_TopLevelInfoBakeResult +rdim_bake_top_level_info(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_TopLevelInfo *src) +{ + RDIM_TopLevelInfoBakeResult result = {0}; + { + result.top_level_info = rdim_push_array(arena, RDI_TopLevelInfo, 1); + result.top_level_info->arch = src->arch; + result.top_level_info->exe_name_string_idx = rdim_bake_idx_from_string(strings, src->exe_name); + result.top_level_info->exe_hash = src->exe_hash; + result.top_level_info->voff_max = src->voff_max; + result.top_level_info->producer_name_string_idx = rdim_bake_idx_from_string(strings, src->producer_name); + } + return result; +} + +RDI_PROC RDIM_BinarySectionBakeResult +rdim_bake_binary_sections(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BinarySectionList *src) +{ + RDIM_BinarySectionBakeResult result = {0}; + { + RDI_BinarySection *dst_base = rdim_push_array(arena, RDI_BinarySection, src->count+1); + U64 dst_idx = 1; + for(RDIM_BinarySectionNode *src_n = src->first; src_n != 0; src_n = src_n->next, dst_idx += 1) + { + RDIM_BinarySection *src = &src_n->v; + RDI_BinarySection *dst = &dst_base[dst_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->flags = src->flags; + dst->voff_first = src->voff_first; + dst->voff_opl = src->voff_opl; + dst->foff_first = src->foff_first; + dst->foff_opl = src->foff_opl; + } + result.binary_sections = dst_base; + result.binary_sections_count = dst_idx; + } + return result; +} + +RDI_PROC RDIM_UnitBakeResult +rdim_bake_units(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_UnitChunkList *src) +{ + RDIM_UnitBakeResult result = {0}; + { + RDI_Unit *dst_base = rdim_push_array(arena, RDI_Unit, src->total_count+1); + RDI_U64 dst_idx = 1; + for(RDIM_UnitChunkNode *src_n = src->first; src_n != 0; src_n = src_n->next) + { + for(RDI_U64 src_chunk_idx = 0; src_chunk_idx < src_n->count; src_chunk_idx += 1, dst_idx += 1) + { + RDIM_Unit *src = &src_n->v[src_chunk_idx]; + RDI_Unit *dst = &dst_base[dst_idx]; + dst->unit_name_string_idx = rdim_bake_idx_from_string(strings, src->unit_name); + dst->compiler_name_string_idx = rdim_bake_idx_from_string(strings, src->compiler_name); + dst->source_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->source_file); + dst->object_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->object_file); + dst->archive_file_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->archive_file); + dst->build_path_node = rdim_bake_path_node_idx_from_string(path_tree, src->build_path); + dst->language = src->language; + dst->line_table_idx = (RDI_U32)rdim_idx_from_line_table(src->line_table); // TODO(rjf): @u64_to_u32 + } + } + result.units = dst_base; + result.units_count = dst_idx; + } + return result; +} + +RDI_PROC RDIM_UnitVMapBakeResult +rdim_bake_unit_vmap(RDIM_Arena *arena, RDIM_UnitChunkList *units) { //- rjf: build vmap from unit voff ranges RDIM_BakeVMap unit_vmap = {0}; @@ -2457,7 +2411,7 @@ rdim_bake_unit_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams // rjf: count voff ranges RDI_U64 voff_range_count = 0; - for(RDIM_UnitChunkNode *n = params->units.first; n != 0; n = n->next) + for(RDIM_UnitChunkNode *n = units->first; n != 0; n = n->next) { for(RDI_U64 idx = 0; idx < n->count; idx += 1) { @@ -2476,7 +2430,7 @@ rdim_bake_unit_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams RDIM_SortKey *key_ptr = keys; RDIM_VMapMarker *marker_ptr = markers; RDI_U32 unit_idx = 1; - for(RDIM_UnitChunkNode *unit_chunk_n = params->units.first; + for(RDIM_UnitChunkNode *unit_chunk_n = units->first; unit_chunk_n != 0; unit_chunk_n = unit_chunk_n->next) { @@ -2513,27 +2467,42 @@ rdim_bake_unit_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams rdim_scratch_end(scratch); } - //- rjf: build section - RDIM_BakeSectionList sections = {0}; - RDI_U64 unit_vmap_size = sizeof(unit_vmap.vmap[0])*(unit_vmap.count+1); - rdim_bake_section_list_push_new_unpacked(arena, §ions, unit_vmap.vmap, unit_vmap_size, RDI_DataSectionTag_UnitVmap, 0); - return sections; + //- rjf: fill result + RDIM_UnitVMapBakeResult result = {unit_vmap}; + return result; } -//- 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) +RDI_PROC RDIM_SrcFileBakeResult +rdim_bake_src_files(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_SrcFileChunkList *src) { - RDIM_BakeSectionList sections = {0}; + RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); //////////////////////////// - //- rjf: iterate all source files, fill serialized version, build sections for line info + //- rjf: iterate all source files, fill serialized version, fill line maps, fill line map tables // - RDI_U32 dst_files_count = params->src_files.total_count + 1; + typedef struct RDIM_DataNode RDIM_DataNode; + struct RDIM_DataNode + { + RDIM_DataNode *next; + void *data; + RDI_U64 size; + }; + RDI_U32 dst_files_count = src->total_count + 1; + RDI_U32 dst_maps_count = src->source_line_map_count + 1; RDI_SourceFile *dst_files = rdim_push_array(arena, RDI_SourceFile, dst_files_count); + RDI_SourceLineMap *dst_maps = rdim_push_array(arena, RDI_SourceLineMap, dst_maps_count); + RDIM_DataNode *first_dst_nums_node = 0; + RDIM_DataNode *last_dst_nums_node = 0; + RDIM_DataNode *first_dst_rngs_node = 0; + RDIM_DataNode *last_dst_rngs_node = 0; + RDIM_DataNode *first_dst_voffs_node = 0; + RDIM_DataNode *last_dst_voffs_node = 0; + RDI_U64 dst_nums_idx = 0; + RDI_U64 dst_rngs_idx = 0; + RDI_U64 dst_voffs_idx = 0; RDI_U32 dst_file_idx = 1; - for(RDIM_SrcFileChunkNode *chunk_n = params->src_files.first; + RDI_U32 dst_map_idx = 1; + for(RDIM_SrcFileChunkNode *chunk_n = src->first; chunk_n != 0; chunk_n = chunk_n->next) { @@ -2542,12 +2511,6 @@ rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMa RDIM_SrcFile *src_file = &chunk_n->v[idx]; RDI_SourceFile *dst_file = &dst_files[dst_file_idx]; - //////////////////////// - //- rjf: fill basics - // - dst_file->file_path_node_idx = rdim_bake_path_node_idx_from_string(path_tree, src_file->normal_full_path); - dst_file->normal_full_path_string_idx = rdim_bake_idx_from_string(strings, src_file->normal_full_path); - //////////////////////// //- rjf: produce combined source file line info // @@ -2557,8 +2520,6 @@ rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMa RDI_U32 src_file_line_count = 0; RDI_U32 src_file_voff_count = 0; { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - //- rjf: gather line number map typedef struct RDIM_SrcLineMapVoffBlock RDIM_SrcLineMapVoffBlock; struct RDIM_SrcLineMapVoffBlock @@ -2654,9 +2615,9 @@ rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMa RDIM_SortKey *sorted_keys = rdim_sort_key_array(scratch.arena, keys, line_count); //- rjf: bake result - RDI_U32 *line_nums = rdim_push_array_no_zero(arena, RDI_U32, line_count); - RDI_U32 *line_ranges = rdim_push_array_no_zero(arena, RDI_U32, line_count + 1); - RDI_U64 *voffs = rdim_push_array_no_zero(arena, RDI_U64, voff_count); + RDI_U32 *line_nums = rdim_push_array_no_zero(scratch.arena, RDI_U32, line_count); + RDI_U32 *line_ranges = rdim_push_array_no_zero(scratch.arena, RDI_U32, line_count + 1); + RDI_U64 *voffs = rdim_push_array_no_zero(scratch.arena, RDI_U64, voff_count); { RDI_U64 *voff_ptr = voffs; for(RDI_U32 i = 0; i < line_count; i += 1) @@ -2679,122 +2640,317 @@ rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMa src_file_line_count = line_count; src_file_voffs = voffs; src_file_voff_count = voff_count; - rdim_scratch_end(scratch); } - ////////////////////////// - //- rjf: produce data sections for this source file's line info tables + //////////////////////// + //- rjf: grab & fill the next line map, if this file has one // - if(src_file_line_count != 0) + RDI_SourceLineMap *dst_map = 0; + if(src_file->first_line_map_fragment != 0) { - dst_file->line_map_count = src_file_line_count; - dst_file->line_map_nums_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_LineMapNumbers, dst_file_idx); // TODO(rjf): @u64_to_u32 - dst_file->line_map_range_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_LineMapRanges, dst_file_idx); // TODO(rjf): @u64_to_u32 - dst_file->line_map_voff_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_LineMapVoffs, dst_file_idx); // TODO(rjf): @u64_to_u32 - rdim_bake_section_list_push_new_unpacked(arena, §ions, src_file_line_nums, sizeof(*src_file_line_nums)*src_file_line_count, RDI_DataSectionTag_LineMapNumbers, dst_file_idx); - rdim_bake_section_list_push_new_unpacked(arena, §ions, src_file_line_ranges, sizeof(*src_file_line_ranges)*(src_file_line_count + 1), RDI_DataSectionTag_LineMapRanges, dst_file_idx); - rdim_bake_section_list_push_new_unpacked(arena, §ions, src_file_voffs, sizeof(*src_file_voffs)*src_file_voff_count, RDI_DataSectionTag_LineMapVoffs, dst_file_idx); + dst_map = &dst_maps[dst_map_idx]; + dst_map_idx += 1; + dst_map->line_count = (RDI_U32)src_file_line_count; // TODO(rjf): @u64_to_u32 + dst_map->voff_count = (RDI_U32)src_file_voff_count; // TODO(rjf): @u64_to_u32 + dst_map->line_map_nums_base_idx = (RDI_U32)dst_nums_idx; // TODO(rjf): @u64_to_u32 + dst_map->line_map_range_base_idx = (RDI_U32)dst_rngs_idx; // TODO(rjf): @u64_to_u32 + dst_map->line_map_voff_base_idx = (RDI_U32)dst_voffs_idx; // TODO(rjf): @u64_to_u32 } + + //////////////////////// + //- rjf: gather line map data chunks for later collation & storage into their own top-level sections + // + { + RDIM_DataNode *dst_num_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); + RDIM_SLLQueuePush(first_dst_nums_node, last_dst_nums_node, dst_num_node); + dst_num_node->data = src_file_line_nums; + dst_num_node->size = sizeof(RDI_U32)*src_file_line_count; + RDIM_DataNode *dst_rng_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); + RDIM_SLLQueuePush(first_dst_rngs_node, last_dst_rngs_node, dst_rng_node); + dst_rng_node->data = src_file_line_ranges; + dst_rng_node->size = sizeof(RDI_U32)*(src_file_line_count+1); + RDIM_DataNode *dst_voff_node = rdim_push_array(scratch.arena, RDIM_DataNode, 1); + RDIM_SLLQueuePush(first_dst_voffs_node, last_dst_voffs_node, dst_voff_node); + dst_voff_node->data = src_file_voffs; + dst_voff_node->size = sizeof(RDI_U64)*(src_file_voff_count); + dst_nums_idx += src_file_line_count; + dst_rngs_idx += src_file_line_count+1; + dst_voffs_idx+= src_file_voff_count; + } + + //////////////////////// + //- rjf: fill file info + // + dst_file->file_path_node_idx = rdim_bake_path_node_idx_from_string(path_tree, src_file->normal_full_path); + dst_file->normal_full_path_string_idx = rdim_bake_idx_from_string(strings, src_file->normal_full_path); + dst_file->source_line_map_idx = (RDI_U32)(dst_map ? (dst_map - dst_maps) : 0); } } //////////////////////////// - //- rjf: build section for all source files + //- rjf: coalesce source line map data blobs // - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_files, sizeof(RDI_SourceFile)*dst_files_count, RDI_DataSectionTag_SourceFiles, 0); + RDI_U32 *source_line_map_nums = rdim_push_array_no_zero(arena, RDI_U32, dst_nums_idx); + RDI_U32 *source_line_map_rngs = rdim_push_array_no_zero(arena, RDI_U32, dst_rngs_idx); + RDI_U64 *source_line_map_voffs= rdim_push_array_no_zero(arena, RDI_U64, dst_voffs_idx); + { + RDI_U64 num_idx = 0; + RDI_U64 rng_idx = 0; + RDI_U64 voff_idx= 0; + for(RDIM_DataNode *num_n = first_dst_nums_node; num_n != 0; num_n = num_n->next) + { + rdim_memcpy(source_line_map_nums+num_idx, num_n->data, num_n->size); + num_idx += num_n->size/sizeof(RDI_U32); + } + for(RDIM_DataNode *rng_n = first_dst_rngs_node; rng_n != 0; rng_n = rng_n->next) + { + rdim_memcpy(source_line_map_rngs+rng_idx, rng_n->data, rng_n->size); + rng_idx += rng_n->size/sizeof(RDI_U32); + } + for(RDIM_DataNode *voff_n = first_dst_voffs_node; voff_n != 0; voff_n = voff_n->next) + { + rdim_memcpy(source_line_map_voffs+voff_idx, voff_n->data, voff_n->size); + voff_idx += voff_n->size/sizeof(RDI_U64); + } + } - return sections; + //////////////////////////// + //- rjf: fill result + // + RDIM_SrcFileBakeResult result = {0}; + result.source_files = dst_files; + result.source_files_count = dst_files_count; + result.source_line_maps = dst_maps; + result.source_line_maps_count = dst_maps_count; + result.source_line_map_nums = source_line_map_nums; + result.source_line_map_nums_count = dst_nums_idx; + result.source_line_map_rngs = source_line_map_rngs; + result.source_line_map_rngs_count = dst_rngs_idx; + result.source_line_map_voffs = source_line_map_voffs; + result.source_line_map_voffs_count= dst_voffs_idx; + + rdim_scratch_end(scratch); + return result; } -//- 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) +RDI_PROC RDIM_LineTableBakeResult +rdim_bake_line_tables(RDIM_Arena *arena, RDIM_LineTableChunkList *src) { - //- rjf: build all type nodes - RDI_TypeNode *type_nodes = push_array(arena, RDI_TypeNode, params->types.total_count+1); - RDIM_ProfScope("push all type nodes") + ////////////////////////////// + //- rjf: build all combined line info + // + RDI_LineTable *dst_line_tables = push_array(arena, RDI_LineTable, src->total_count+1); + RDI_U64 *dst_line_voffs = push_array(arena, RDI_U64, src->total_line_count + 2*src->total_seq_count); + RDI_Line *dst_lines = push_array(arena, RDI_Line, src->total_line_count + src->total_seq_count); + RDI_Column *dst_cols = push_array(arena, RDI_Column, 1); { - RDI_U32 dst_idx = 1; - for(RDIM_TypeChunkNode *n = params->types.first; n != 0; n = n->next) + RDI_U64 dst_table_idx = 1; + RDI_U64 dst_voff_idx = 0; + RDI_U64 dst_line_idx = 0; + RDI_U64 dst_col_idx = 0; + for(RDIM_LineTableChunkNode *src_n = src->first; src_n != 0; src_n = src_n->next) { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + for(RDI_U64 chunk_idx = 0; chunk_idx < src_n->count; chunk_idx += 1) { - RDIM_Type *src = &n->v[chunk_idx]; - RDI_TypeNode *dst = &type_nodes[dst_idx]; + RDIM_LineTable *src_line_table = &src_n->v[chunk_idx]; + RDI_LineTable *dst_line_table = &dst_line_tables[dst_table_idx]; - //- rjf: fill shared type node info - dst->kind = src->kind; - dst->flags = (RDI_U16)src->flags; // TODO(rjf): @u32_to_u16 - dst->byte_size = src->byte_size; - - //- rjf: fill built-in-only type node info - if(RDI_TypeKind_FirstBuiltIn <= dst->kind && dst->kind <= RDI_TypeKind_LastBuiltIn) + //- rjf: fill combined line table info { - dst->built_in.name_string_idx = rdim_bake_idx_from_string(strings, src->name); - } - - //- rjf: fill constructed type node info - else if(RDI_TypeKind_FirstConstructed <= dst->kind && dst->kind <= RDI_TypeKind_LastConstructed) - { - dst->constructed.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 - dst->constructed.count = src->count; - if(dst->kind == RDI_TypeKind_Function || dst->kind == RDI_TypeKind_Method) + 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 param_idx_run_count = src->count; - RDI_U32 *param_idx_run = rdim_push_array_no_zero(arena, RDI_U32, param_idx_run_count); - for(RDI_U32 idx = 0; idx < param_idx_run_count; idx += 1) + RDI_U32 file_id; + RDI_U32 line_num; + RDI_U16 col_first; + RDI_U16 col_opl; + }; + RDI_U64 line_count = src_line_table->line_count; + RDI_U64 seq_count = src_line_table->seq_count; + RDI_U64 key_count = line_count + seq_count; + RDIM_SortKey *line_keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, key_count); + RDIM_LineRec *line_recs = rdim_push_array_no_zero(scratch.arena, RDIM_LineRec, line_count); + { + RDIM_SortKey *key_ptr = line_keys; + RDIM_LineRec *rec_ptr = line_recs; + for(RDIM_LineSequenceNode *seq_n = src_line_table->first_seq; seq_n != 0; seq_n = seq_n->next) { - param_idx_run[idx] = (RDI_U32)rdim_idx_from_type(src->param_types[idx]); // TODO(rjf): @u64_to_u32 + 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; } - dst->constructed.param_idx_run_first = rdim_bake_idx_from_idx_run(idx_runs, param_idx_run, param_idx_run_count); } - else if(dst->kind == RDI_TypeKind_MemberPtr) + + //- rjf: sort + RDIM_SortKey *sorted_line_keys = 0; { - // TODO(rjf): member pointers not currently supported. + 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; + { + 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 user-defined-type info - else if(RDI_TypeKind_FirstUserDefined <= dst->kind && dst->kind <= RDI_TypeKind_LastUserDefined) - { - dst->user_defined.name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->user_defined.udt_idx = (RDI_U32)rdim_idx_from_udt(src->udt); // TODO(rjf): @u64_to_u32 - dst->user_defined.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 - } + //- rjf: fill destination table + dst_line_table->voffs_base_idx = (RDI_U32)dst_voff_idx; // TODO(rjf): @u64_to_u32 + dst_line_table->lines_base_idx = (RDI_U32)dst_line_idx; // TODO(rjf): @u64_to_u32 + dst_line_table->cols_base_idx = (RDI_U32)dst_col_idx; // TODO(rjf): @u64_to_u32 + dst_line_table->lines_count = (RDI_U32)src_line_table->line_count + src_line_table->seq_count; // TODO(rjf): @u64_to_u32 - //- rjf: fill bitfield info - else if(dst->kind == RDI_TypeKind_Bitfield) - { - dst->bitfield.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 - dst->bitfield.off = src->off; - dst->bitfield.size = src->count; - } + //- rjf: increment + dst_table_idx += 1; + dst_voff_idx += src_line_table->line_count + 2*src_line_table->seq_count; + dst_line_idx += src_line_table->line_count + src_line_table->seq_count; } } } - - //- rjf: build sections - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, type_nodes, sizeof(RDI_TypeNode)*(params->types.total_count+1), RDI_DataSectionTag_TypeNodes, 0); - return sections; + ////////////////////////////// + //- rjf: fill result + // + RDIM_LineTableBakeResult result = {0}; + { + result.line_tables = dst_line_tables; + result.line_tables_count = src->total_count; + result.line_table_voffs = dst_line_voffs; + result.line_table_voffs_count = (src->total_line_count + src->total_seq_count); + result.line_table_lines = dst_lines; + result.line_table_lines_count = (src->total_line_count + src->total_seq_count); + result.line_table_columns = dst_cols; + result.line_table_columns_count = src->total_col_count; + } + return result; } -//- rjf: UDTs +RDI_PROC RDIM_TypeNodeBakeResult +rdim_bake_types(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_TypeChunkList *src) +{ + RDI_TypeNode *type_nodes = push_array(arena, RDI_TypeNode, src->total_count+1); + RDI_U32 dst_idx = 1; + for(RDIM_TypeChunkNode *n = src->first; n != 0; n = n->next) + { + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + { + RDIM_Type *src = &n->v[chunk_idx]; + RDI_TypeNode *dst = &type_nodes[dst_idx]; + + //- rjf: fill shared type node info + dst->kind = src->kind; + dst->flags = (RDI_U16)src->flags; // TODO(rjf): @u32_to_u16 + dst->byte_size = src->byte_size; + + //- rjf: fill built-in-only type node info + if(RDI_TypeKind_FirstBuiltIn <= dst->kind && dst->kind <= RDI_TypeKind_LastBuiltIn) + { + dst->built_in.name_string_idx = rdim_bake_idx_from_string(strings, src->name); + } + + //- rjf: fill constructed type node info + else if(RDI_TypeKind_FirstConstructed <= dst->kind && dst->kind <= RDI_TypeKind_LastConstructed) + { + dst->constructed.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 + dst->constructed.count = src->count; + if(dst->kind == RDI_TypeKind_Function || dst->kind == RDI_TypeKind_Method) + { + RDI_U32 param_idx_run_count = src->count; + RDI_U32 *param_idx_run = rdim_push_array_no_zero(arena, RDI_U32, param_idx_run_count); + for(RDI_U32 idx = 0; idx < param_idx_run_count; idx += 1) + { + param_idx_run[idx] = (RDI_U32)rdim_idx_from_type(src->param_types[idx]); // TODO(rjf): @u64_to_u32 + } + dst->constructed.param_idx_run_first = rdim_bake_idx_from_idx_run(idx_runs, param_idx_run, param_idx_run_count); + } + else if(dst->kind == RDI_TypeKind_MemberPtr) + { + // TODO(rjf): member pointers not currently supported. + } + } + + //- rjf: fill user-defined-type info + else if(RDI_TypeKind_FirstUserDefined <= dst->kind && dst->kind <= RDI_TypeKind_LastUserDefined) + { + dst->user_defined.name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->user_defined.udt_idx = (RDI_U32)rdim_idx_from_udt(src->udt); // TODO(rjf): @u64_to_u32 + dst->user_defined.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 + } + + //- rjf: fill bitfield info + else if(dst->kind == RDI_TypeKind_Bitfield) + { + dst->bitfield.direct_type_idx = (RDI_U32)rdim_idx_from_type(src->direct_type); // TODO(rjf): @u64_to_u32 + dst->bitfield.off = src->off; + dst->bitfield.size = src->count; + } + } + } + RDIM_TypeNodeBakeResult result = {0}; + result.type_nodes = type_nodes; + result.type_nodes_count = (src->total_count+1); + return result; +} -RDI_PROC RDIM_BakeSectionList -rdim_bake_udt_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params) +RDI_PROC RDIM_UDTBakeResult +rdim_bake_udts(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_UDTChunkList *src) { //- rjf: build tables - RDI_UDT * udts = push_array(arena, RDI_UDT, params->udts.total_count+1); - RDI_Member * members = push_array(arena, RDI_Member, params->udts.total_member_count+1); - RDI_EnumMember *enum_members = push_array(arena, RDI_EnumMember, params->udts.total_enum_val_count+1); + RDI_UDT * udts = push_array(arena, RDI_UDT, src->total_count+1); + RDI_Member * members = push_array(arena, RDI_Member, src->total_member_count+1); + RDI_EnumMember *enum_members = push_array(arena, RDI_EnumMember, src->total_enum_val_count+1); { RDI_U32 dst_udt_idx = 1; RDI_U32 dst_member_idx = 1; RDI_U32 dst_enum_member_idx = 1; - for(RDIM_UDTChunkNode *n = params->udts.first; n != 0; n = n->next) + for(RDIM_UDTChunkNode *n = src->first; n != 0; n = n->next) { for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_udt_idx += 1) { @@ -2843,60 +2999,57 @@ rdim_bake_udt_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTigh } } - //- rjf: build sections - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, udts, sizeof(RDI_UDT) * (params->udts.total_count+1), RDI_DataSectionTag_UDTs, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, members , sizeof(RDI_Member) * (params->udts.total_member_count+1), RDI_DataSectionTag_Members, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, enum_members, sizeof(RDI_EnumMember) * (params->udts.total_enum_val_count+1), RDI_DataSectionTag_EnumMembers, 0); - return sections; + //- rjf: fill result + RDIM_UDTBakeResult result = {0}; + { + result.udts = udts; + result.udts_count = src->total_count+1; + result.members = members; + result.members_count = src->total_member_count+1; + result.enum_members = enum_members; + result.enum_members_count = src->total_enum_val_count+1; + } + return result; } -//- rjf: global variables - -RDI_PROC RDIM_BakeSectionList -rdim_bake_global_variable_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params) +RDI_PROC RDIM_GlobalVariableBakeResult +rdim_bake_global_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src) { - //- rjf: build all global variables - RDI_GlobalVariable *global_variables = push_array(arena, RDI_GlobalVariable, params->global_variables.total_count+1); + RDI_GlobalVariable *global_variables = push_array(arena, RDI_GlobalVariable, src->total_count+1); + RDI_U32 dst_idx = 1; + for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) { - RDI_U32 dst_idx = 1; - for(RDIM_SymbolChunkNode *n = params->global_variables.first; n != 0; n = n->next) + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + RDIM_Symbol *src = &n->v[chunk_idx]; + RDI_GlobalVariable *dst = &global_variables[dst_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->voff = src->offset; + dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 + if(src->is_extern) { - RDIM_Symbol *src = &n->v[chunk_idx]; - RDI_GlobalVariable *dst = &global_variables[dst_idx]; - dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->voff = src->offset; - dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 - if(src->is_extern) - { - dst->link_flags |= RDI_LinkFlag_External; - } - if(src->container_type != 0) - { - dst->link_flags |= RDI_LinkFlag_TypeScoped; - dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 - } - else if(src->container_symbol != 0) - { - dst->link_flags |= RDI_LinkFlag_ProcScoped; - dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 - } + dst->link_flags |= RDI_LinkFlag_External; + } + if(src->container_type != 0) + { + dst->link_flags |= RDI_LinkFlag_TypeScoped; + dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 + } + else if(src->container_symbol != 0) + { + dst->link_flags |= RDI_LinkFlag_ProcScoped; + dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 } } } - - //- rjf: build sections - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, global_variables, sizeof(RDI_GlobalVariable)*(params->global_variables.total_count+1), RDI_DataSectionTag_GlobalVariables, 0); - return sections; + RDIM_GlobalVariableBakeResult result = {0}; + result.global_variables = global_variables; + result.global_variables_count = (src->total_count+1); + return result; } -//- rjf: global vmap - -RDI_PROC RDIM_BakeSectionList -rdim_bake_global_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params) +RDI_PROC RDIM_GlobalVMapBakeResult +rdim_bake_global_vmap(RDIM_Arena *arena, RDIM_SymbolChunkList *src) { //- rjf: build global vmap RDIM_BakeVMap global_vmap = {0}; @@ -2904,7 +3057,7 @@ rdim_bake_global_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParam RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); //- rjf: allocate keys/markers - RDI_U64 marker_count = params->global_variables.total_count*2; + RDI_U64 marker_count = src->total_count*2; RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); @@ -2914,7 +3067,7 @@ rdim_bake_global_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParam RDIM_VMapMarker *marker_ptr = markers; // rjf: fill actual globals - for(RDIM_SymbolChunkNode *n = params->global_variables.first; n != 0; n = n->next) + for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) { for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1) { @@ -2967,111 +3120,96 @@ rdim_bake_global_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParam rdim_scratch_end(scratch); } - //- rjf: build sections - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, global_vmap.vmap, sizeof(RDI_VMapEntry)*(global_vmap.count+1), RDI_DataSectionTag_GlobalVmap, 0); - return sections; + //- rjf: fill result + RDIM_GlobalVMapBakeResult result = {global_vmap}; + return result; } -//- rjf: thread variables - -RDI_PROC RDIM_BakeSectionList -rdim_bake_thread_variable_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params) +RDI_PROC RDIM_ThreadVariableBakeResult +rdim_bake_thread_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src) { - //- rjf: build all thread variables - RDI_ThreadVariable *thread_variables = push_array(arena, RDI_ThreadVariable, params->thread_variables.total_count+1); + RDI_ThreadVariable *thread_variables = push_array(arena, RDI_ThreadVariable, src->total_count+1); + RDI_U32 dst_idx = 1; + for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) { - RDI_U32 dst_idx = 1; - for(RDIM_SymbolChunkNode *n = params->thread_variables.first; n != 0; n = n->next) + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + RDIM_Symbol *src = &n->v[chunk_idx]; + RDI_ThreadVariable *dst = &thread_variables[dst_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->tls_off = (RDI_U32)src->offset; // TODO(rjf): @u64_to_u32 + dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); + if(src->is_extern) { - RDIM_Symbol *src = &n->v[chunk_idx]; - RDI_ThreadVariable *dst = &thread_variables[dst_idx]; - dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->tls_off = (RDI_U32)src->offset; // TODO(rjf): @u64_to_u32 - dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); - if(src->is_extern) - { - dst->link_flags |= RDI_LinkFlag_External; - } - if(src->container_type != 0) - { - dst->link_flags |= RDI_LinkFlag_TypeScoped; - dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 - } - else if(src->container_symbol != 0) - { - dst->link_flags |= RDI_LinkFlag_ProcScoped; - dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 - } + dst->link_flags |= RDI_LinkFlag_External; + } + if(src->container_type != 0) + { + dst->link_flags |= RDI_LinkFlag_TypeScoped; + dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 + } + else if(src->container_symbol != 0) + { + dst->link_flags |= RDI_LinkFlag_ProcScoped; + dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 } } } - - //- rjf: build sections - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, thread_variables, sizeof(RDI_ThreadVariable)*(params->thread_variables.total_count+1), RDI_DataSectionTag_ThreadVariables, 0); - return sections; + RDIM_ThreadVariableBakeResult result = {0}; + result.thread_variables = thread_variables; + result.thread_variables_count = src->total_count+1; + return result; } -//- rjf: procedures - -RDI_PROC RDIM_BakeSectionList -rdim_bake_procedure_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params) +RDI_PROC RDIM_ProcedureBakeResult +rdim_bake_procedures(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src) { - //- rjf: build all procedures - RDI_Procedure *procedures = push_array(arena, RDI_Procedure, params->procedures.total_count+1); + RDI_Procedure *procedures = push_array(arena, RDI_Procedure, src->total_count+1); + RDI_U32 dst_idx = 1; + for(RDIM_SymbolChunkNode *n = src->first; n != 0; n = n->next) { - RDI_U32 dst_idx = 1; - for(RDIM_SymbolChunkNode *n = params->procedures.first; n != 0; n = n->next) + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) { - for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + RDIM_Symbol *src = &n->v[chunk_idx]; + RDI_Procedure *dst = &procedures[dst_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->link_name_string_idx = rdim_bake_idx_from_string(strings, src->link_name); + if(src->is_extern) { - RDIM_Symbol *src = &n->v[chunk_idx]; - RDI_Procedure *dst = &procedures[dst_idx]; - dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); - dst->link_name_string_idx = rdim_bake_idx_from_string(strings, src->link_name); - if(src->is_extern) - { - dst->link_flags |= RDI_LinkFlag_External; - } - if(src->container_type != 0) - { - dst->link_flags |= RDI_LinkFlag_TypeScoped; - dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 - } - else if(src->container_symbol != 0) - { - dst->link_flags |= RDI_LinkFlag_ProcScoped; - dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 - } - dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 - dst->root_scope_idx = (RDI_U32)rdim_idx_from_scope(src->root_scope); // TODO(rjf): @u64_to_u32 + dst->link_flags |= RDI_LinkFlag_External; } + if(src->container_type != 0) + { + dst->link_flags |= RDI_LinkFlag_TypeScoped; + dst->container_idx = src->container_type ? (RDI_U32)rdim_idx_from_udt(src->container_type->udt) : 0; // TODO(rjf): @u64_to_u32 + } + else if(src->container_symbol != 0) + { + dst->link_flags |= RDI_LinkFlag_ProcScoped; + dst->container_idx = (RDI_U32)rdim_idx_from_symbol(src->container_symbol); // TODO(rjf): @u64_to_u32 + } + dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 + dst->root_scope_idx = (RDI_U32)rdim_idx_from_scope(src->root_scope); // TODO(rjf): @u64_to_u32 } } - - //- rjf: build sections - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, procedures, sizeof(RDI_Procedure)*(params->procedures.total_count+1), RDI_DataSectionTag_Procedures, 0); - return sections; + RDIM_ProcedureBakeResult result = {0}; + result.procedures = procedures; + result.procedures_count = src->total_count+1; + return result; } -//- rjf: scopes - -RDI_PROC RDIM_BakeSectionList -rdim_bake_scope_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params) +RDI_PROC RDIM_ScopeBakeResult +rdim_bake_scopes(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_ScopeChunkList *src) { RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); //////////////////////////// //- rjf: build all scopes, scope voffs, locals, and location blocks // - RDI_Scope * scopes = rdim_push_array(arena, RDI_Scope, params->scopes.total_count+1); - RDI_U64 * scope_voffs = rdim_push_array(arena, RDI_U64, params->scopes.scope_voff_count+1); - RDI_Local * locals = rdim_push_array(arena, RDI_Local, params->scopes.local_count+1); - RDI_LocationBlock * location_blocks = rdim_push_array(arena, RDI_LocationBlock, params->scopes.location_count+1); + RDI_Scope * scopes = rdim_push_array(arena, RDI_Scope, src->total_count+1); + RDI_U64 * scope_voffs = rdim_push_array(arena, RDI_U64, src->scope_voff_count+1); + RDI_Local * locals = rdim_push_array(arena, RDI_Local, src->local_count+1); + RDI_LocationBlock * location_blocks = rdim_push_array(arena, RDI_LocationBlock, src->location_count+1); RDIM_String8List location_data_blobs = {0}; RDIM_ProfScope("build all scopes, scope voffs, locals, and location blocks") { @@ -3079,7 +3217,7 @@ rdim_bake_scope_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTi RDI_U64 dst_scope_voff_idx = 1; RDI_U64 dst_local_idx = 1; RDI_U64 dst_location_block_idx = 1; - for(RDIM_ScopeChunkNode *chunk_n = params->scopes.first; chunk_n != 0; chunk_n = chunk_n->next) + for(RDIM_ScopeChunkNode *chunk_n = src->first; chunk_n != 0; chunk_n = chunk_n->next) { for(RDI_U64 chunk_idx = 0; chunk_idx < chunk_n->count; chunk_idx += 1, dst_scope_idx += 1) { @@ -3202,6 +3340,7 @@ rdim_bake_scope_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTi dst_scope->voff_range_opl = (RDI_U32)voff_idx_opl; // TODO(rjf): @u64_to_u32 dst_scope->local_first = (RDI_U32)local_idx_first; // TODO(rjf): @u64_to_u32 dst_scope->local_count = (RDI_U32)(local_idx_opl - local_idx_first); // TODO(rjf): @u64_to_u32 + dst_scope->inline_site_idx = (RDI_U32)rdim_idx_from_inline_site(src_scope->inline_site); // TODO(rjf): @u64_to_u32 } } } @@ -3216,33 +3355,32 @@ rdim_bake_scope_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTi } //////////////////////////// - //- rjf: push all sections + //- rjf: fill result // - RDIM_BakeSectionList sections = {0}; - RDIM_ProfScope("push all symbol info sections") - { - rdim_bake_section_list_push_new_unpacked(arena, §ions, scopes, sizeof(RDI_Scope) * (params->scopes.total_count+1), RDI_DataSectionTag_Scopes, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, scope_voffs, sizeof(RDI_U64) * (params->scopes.scope_voff_count+1), RDI_DataSectionTag_ScopeVoffData, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, locals, sizeof(RDI_Local) * (params->scopes.local_count+1), RDI_DataSectionTag_Locals, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, location_blocks, sizeof(RDI_LocationBlock) * (params->scopes.location_count+1), RDI_DataSectionTag_LocationBlocks, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, location_data_blob.str, location_data_blob.size, RDI_DataSectionTag_LocationData, 0); - } + RDIM_ScopeBakeResult result = {0}; + result.scopes = scopes; + result.scopes_count = src->total_count+1; + result.scope_voffs = scope_voffs; + result.scope_voffs_count = src->scope_voff_count+1; + result.locals = locals; + result.locals_count = src->local_count+1; + result.location_blocks = location_blocks; + result.location_blocks_count = src->location_count+1; + result.location_data = location_data_blob.str; + result.location_data_size = location_data_blob.size; rdim_scratch_end(scratch); - return sections; + return result; } -//- rjf: scope vmap - -RDI_PROC RDIM_BakeSectionList -rdim_bake_scope_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params) +RDI_PROC RDIM_ScopeVMapBakeResult +rdim_bake_scope_vmap(RDIM_Arena *arena, RDIM_ScopeChunkList *src) { - //- rjf: build scope vmap RDIM_BakeVMap scope_vmap = {0}; { RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); // rjf: allocate keys/markers - RDI_U64 marker_count = params->scopes.scope_voff_count; + RDI_U64 marker_count = src->scope_voff_count; RDIM_SortKey *keys = rdim_push_array_no_zero(scratch.arena, RDIM_SortKey, marker_count); RDIM_VMapMarker *markers = rdim_push_array_no_zero(scratch.arena, RDIM_VMapMarker, marker_count); @@ -3250,7 +3388,7 @@ rdim_bake_scope_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams { RDIM_SortKey *key_ptr = keys; RDIM_VMapMarker *marker_ptr = markers; - for(RDIM_ScopeChunkNode *chunk_n = params->scopes.first; chunk_n != 0; chunk_n = chunk_n->next) + for(RDIM_ScopeChunkNode *chunk_n = src->first; chunk_n != 0; chunk_n = chunk_n->next) { for(RDI_U64 chunk_idx = 0; chunk_idx < chunk_n->count; chunk_idx += 1) { @@ -3280,163 +3418,63 @@ rdim_bake_scope_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams scope_vmap = rdim_bake_vmap_from_markers(arena, markers, keys, marker_count); rdim_scratch_end(scratch); } - - //- rjf: build sections - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, scope_vmap.vmap, sizeof(RDI_VMapEntry)*(scope_vmap.count+1), RDI_DataSectionTag_ScopeVmap, 0); - return sections; + RDIM_ScopeVMapBakeResult result = {scope_vmap}; + return result; } -//- rjf: name maps - -RDI_PROC RDIM_BakeSectionList -rdim_bake_top_level_name_map_section_list_from_params_maps(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeParams *params, RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT]) +RDI_PROC RDIM_InlineSiteBakeResult +rdim_bake_inline_sites(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_InlineSiteChunkList *src) { - RDIM_BakeSectionList sections = {0}; - - //- rjf: count the # of name maps we have with any content - RDI_U32 name_map_count = 0; - for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); - k < RDI_NameMapKind_COUNT; - k = (RDI_NameMapKind)(k+1)) + RDIM_InlineSiteBakeResult result = {0}; { - if(name_maps[k] != 0 && name_maps[k]->name_count != 0) + result.inline_sites_count = src->total_count; + result.inline_sites = rdim_push_array(arena, RDI_InlineSite, result.inline_sites_count+1); + RDI_U64 dst_idx = 1; + for(RDIM_InlineSiteChunkNode *n = src->first; n != 0; n = n->next) { - name_map_count += 1; + for(RDI_U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, dst_idx += 1) + { + RDI_InlineSite *dst = &result.inline_sites[dst_idx]; + RDIM_InlineSite *src = &n->v[chunk_idx]; + dst->name_string_idx = rdim_bake_idx_from_string(strings, src->name); + dst->type_idx = (RDI_U32)rdim_idx_from_type(src->type); // TODO(rjf): @u64_to_u32 + dst->owner_type_idx = (RDI_U32)rdim_idx_from_type(src->owner); // TODO(rjf): @u64_to_u32 + dst->line_table_idx = (RDI_U32)rdim_idx_from_line_table(src->line_table); // TODO(rjf): @u64_to_u32 + } } } - - //- rjf: allocate & fill baked name maps - RDI_NameMap *dst_maps = rdim_push_array(arena, RDI_NameMap, name_map_count); + return result; +} + +RDI_PROC RDIM_TopLevelNameMapBakeResult +rdim_bake_name_maps_top_level(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT]) +{ + RDI_NameMap *dst_maps = rdim_push_array(arena, RDI_NameMap, RDI_NameMapKind_COUNT); { - RDI_U64 dst_map_idx = 0; + RDI_U64 dst_map_bucket_idx = 0; + RDI_U64 dst_map_node_idx = 0; for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); k < RDI_NameMapKind_COUNT; k = (RDI_NameMapKind)(k+1)) { - RDI_NameMap *dst_map = &dst_maps[dst_map_idx]; + RDI_NameMap *dst_map = &dst_maps[k]; RDIM_BakeNameMap *src_map = name_maps[k]; - if(src_map == 0 || src_map->name_count == 0) { continue; } - dst_map->kind = k; - dst_map->bucket_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_NameMapBuckets, (RDI_U64)k); // TODO(rjf): @u64_to_u32 - dst_map->node_data_idx = (RDI_U32)rdim_bake_section_idx_from_params_tag_idx(params, RDI_DataSectionTag_NameMapNodes, (RDI_U64)k); // TODO(rjf): @u64_to_u32 - dst_map_idx += 1; + dst_map->bucket_base_idx = (RDI_U32)dst_map_bucket_idx; // TODO(rjf): @u64_to_u32 + dst_map->node_base_idx = (RDI_U32)dst_map_node_idx; // TODO(rjf): @u64_to_u32 + dst_map->bucket_count = (RDI_U32)src_map->name_count; // TODO(rjf): @u64_to_u32 + dst_map->node_count = (RDI_U32)src_map->name_count; // TODO(rjf): @u64_to_u32 + dst_map_bucket_idx += dst_map->bucket_count; + dst_map_node_idx += dst_map->node_count; } } - - // rjf: push section for all name maps - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_maps, sizeof(RDI_NameMap)*name_map_count, RDI_DataSectionTag_NameMaps, 0); - return sections; + RDIM_TopLevelNameMapBakeResult result = {0}; + result.name_maps = dst_maps; + result.name_maps_count = RDI_NameMapKind_COUNT; + return result; } -RDI_PROC RDIM_BakeSectionList -rdim_bake_name_map_section_list_from_params_kind_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeParams *params, RDI_NameMapKind k, RDIM_BakeNameMap *map) -{ - RDIM_BakeSectionList sections = {0}; - if(map != 0 && map->name_count != 0) - { - RDI_U32 baked_buckets_count = map->name_count; - RDI_U32 baked_nodes_count = map->name_count; - RDI_NameMapBucket *baked_buckets = rdim_push_array(arena, RDI_NameMapBucket, baked_buckets_count); - RDI_NameMapNode *baked_nodes = rdim_push_array_no_zero(arena, RDI_NameMapNode, baked_nodes_count); - { - RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - - // rjf: setup the final bucket layouts - typedef struct RDIM_NameMapSemiNode RDIM_NameMapSemiNode; - struct RDIM_NameMapSemiNode - { - RDIM_NameMapSemiNode *next; - RDIM_BakeNameMapNode *node; - }; - typedef struct RDIM_NameMapSemiBucket RDIM_NameMapSemiBucket; - struct RDIM_NameMapSemiBucket - { - RDIM_NameMapSemiNode *first; - RDIM_NameMapSemiNode *last; - RDI_U64 count; - }; - RDIM_NameMapSemiBucket *sbuckets = rdim_push_array(scratch.arena, RDIM_NameMapSemiBucket, baked_buckets_count); - for(RDIM_BakeNameMapNode *node = map->first; - node != 0; - node = node->order_next) - { - RDI_U64 hash = rdi_hash(node->string.str, node->string.size); - RDI_U64 bi = hash%baked_buckets_count; - RDIM_NameMapSemiNode *snode = rdim_push_array(scratch.arena, RDIM_NameMapSemiNode, 1); - SLLQueuePush(sbuckets[bi].first, sbuckets[bi].last, snode); - snode->node = node; - sbuckets[bi].count += 1; - } - - // rjf: convert to serialized buckets & nodes - { - RDI_NameMapBucket *bucket_ptr = baked_buckets; - RDI_NameMapNode *node_ptr = baked_nodes; - for(RDI_U32 i = 0; i < baked_buckets_count; i += 1, bucket_ptr += 1) - { - bucket_ptr->first_node = (RDI_U32)(node_ptr - baked_nodes); - bucket_ptr->node_count = sbuckets[i].count; - for(RDIM_NameMapSemiNode *snode = sbuckets[i].first; - snode != 0; - snode = snode->next) - { - RDIM_BakeNameMapNode *node = snode->node; - - // rjf: cons name and index(es) - RDI_U32 string_idx = rdim_bake_idx_from_string(strings, node->string); - RDI_U32 match_count = node->val_count; - RDI_U32 idx = 0; - if(match_count == 1) - { - idx = node->val_first->val[0]; - } - else - { - RDI_U64 temp_pos = rdim_arena_pos(scratch.arena); - RDI_U32 *idx_run = rdim_push_array_no_zero(scratch.arena, RDI_U32, match_count); - RDI_U32 *idx_ptr = idx_run; - for(RDIM_BakeNameMapValNode *idxnode = node->val_first; - idxnode != 0; - idxnode = idxnode->next) - { - for(RDI_U32 i = 0; i < sizeof(idxnode->val)/sizeof(idxnode->val[0]); i += 1) - { - if(idxnode->val[i] == 0) - { - goto dblbreak; - } - *idx_ptr = idxnode->val[i]; - idx_ptr += 1; - } - } - dblbreak:; - idx = rdim_bake_idx_from_idx_run(idx_runs, idx_run, match_count); - rdim_arena_pop_to(scratch.arena, temp_pos); - } - - // rjf: write to node - node_ptr->string_idx = string_idx; - node_ptr->match_count = match_count; - node_ptr->match_idx_or_idx_run_first = idx; - node_ptr += 1; - } - } - } - rdim_scratch_end(scratch); - } - - // rjf: sections for buckets/nodes - rdim_bake_section_list_push_new_unpacked(arena, §ions, baked_buckets, sizeof(RDI_NameMapBucket)* baked_buckets_count, RDI_DataSectionTag_NameMapBuckets, (RDI_U64)k); - rdim_bake_section_list_push_new_unpacked(arena, §ions, baked_nodes, sizeof(RDI_NameMapNode) * baked_nodes_count, RDI_DataSectionTag_NameMapNodes, (RDI_U64)k); - } - return sections; -} - -//- rjf: file paths - -RDI_PROC RDIM_BakeSectionList -rdim_bake_file_path_section_list_from_path_tree(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree) +RDI_PROC RDIM_FilePathBakeResult +rdim_bake_file_paths(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree) { RDI_U32 dst_nodes_count = path_tree->count; RDI_FilePathNode *dst_nodes = rdim_push_array(arena, RDI_FilePathNode, dst_nodes_count); @@ -3463,15 +3501,14 @@ rdim_bake_file_path_section_list_from_path_tree(RDIM_Arena *arena, RDIM_BakeStri } } } - RDIM_BakeSectionList sections = {0}; - rdim_bake_section_list_push_new_unpacked(arena, §ions, dst_nodes, sizeof(RDI_FilePathNode)*dst_nodes_count, RDI_DataSectionTag_FilePathNodes, 0); - return sections; + RDIM_FilePathBakeResult result = {0}; + result.nodes = dst_nodes; + result.nodes_count = dst_nodes_count; + return result; } -//- rjf: strings - -RDI_PROC RDIM_BakeSectionList -rdim_bake_string_section_list_from_string_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings) +RDI_PROC RDIM_StringBakeResult +rdim_bake_strings(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings) { RDIM_BakeSectionList sections = {0}; RDI_U32 *str_offs = rdim_push_array_no_zero(arena, RDI_U32, strings->total_count + 1); @@ -3487,8 +3524,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; } } @@ -3510,17 +3547,17 @@ rdim_bake_string_section_list_from_string_map(RDIM_Arena *arena, RDIM_BakeString } } } - rdim_bake_section_list_push_new_unpacked(arena, §ions, str_offs, sizeof(RDI_U32)*(strings->total_count+1), RDI_DataSectionTag_StringTable, 0); - rdim_bake_section_list_push_new_unpacked(arena, §ions, buf, off_cursor, RDI_DataSectionTag_StringData, 0); - return sections; + RDIM_StringBakeResult result = {0}; + result.string_offs = str_offs; + result.string_offs_count = strings->total_count+1; + result.string_data = buf; + result.string_data_size = off_cursor; + return result; } -//- rjf: index runs - -RDI_PROC RDIM_BakeSectionList -rdim_bake_idx_run_section_list_from_idx_run_map(RDIM_Arena *arena, RDIM_BakeIdxRunMap *idx_runs) +RDI_PROC RDIM_IndexRunBakeResult +rdim_bake_index_runs(RDIM_Arena *arena, RDIM_BakeIdxRunMap *idx_runs) { - RDIM_BakeSectionList sections = {0}; RDI_U32 *idx_data = rdim_push_array_no_zero(arena, RDI_U32, idx_runs->idx_count); { RDI_U32 *out_ptr = idx_data; @@ -3533,78 +3570,108 @@ rdim_bake_idx_run_section_list_from_idx_run_map(RDIM_Arena *arena, RDIM_BakeIdxR out_ptr += node->count; } } - rdim_bake_section_list_push_new_unpacked(arena, §ions, idx_data, sizeof(RDI_U32)*idx_runs->idx_count, RDI_DataSectionTag_IndexRuns, 0); - return sections; + RDIM_IndexRunBakeResult result = {0}; + result.idx_runs = idx_data; + result.idx_count = idx_runs->idx_count; + return result; } //////////////////////////////// -//~ rjf: [Serializing] Baked Data Section List -> Serialized Binary Strings +//~ rjf: [Serializing] Bake Results -> String Blobs + +RDI_PROC RDIM_SerializedSection +rdim_serialized_section_make_unpacked(void *data, RDI_U64 size) +{ + RDIM_SerializedSection s; + rdim_memzero_struct(&s); + s.data = data; + s.encoded_size = s.unpacked_size = size; + s.encoding = RDI_SectionEncoding_Unpacked; + return s; +} + +RDI_PROC RDIM_SerializedSectionBundle +rdim_serialized_section_bundle_from_bake_results(RDIM_BakeResults *results) +{ + RDIM_SerializedSectionBundle bundle; + rdim_memzero_struct(&bundle); + bundle.sections[RDI_SectionKind_TopLevelInfo] = rdim_serialized_section_make_unpacked_struct(results->top_level_info.top_level_info); + bundle.sections[RDI_SectionKind_StringData] = rdim_serialized_section_make_unpacked_array(results->strings.string_data, results->strings.string_data_size); + bundle.sections[RDI_SectionKind_StringTable] = rdim_serialized_section_make_unpacked_array(results->strings.string_offs, results->strings.string_offs_count); + bundle.sections[RDI_SectionKind_IndexRuns] = rdim_serialized_section_make_unpacked_array(results->idx_runs.idx_runs, results->idx_runs.idx_count); + bundle.sections[RDI_SectionKind_BinarySections] = rdim_serialized_section_make_unpacked_array(results->binary_sections.binary_sections, results->binary_sections.binary_sections_count); + bundle.sections[RDI_SectionKind_FilePathNodes] = rdim_serialized_section_make_unpacked_array(results->file_paths.nodes, results->file_paths.nodes_count); + bundle.sections[RDI_SectionKind_SourceFiles] = rdim_serialized_section_make_unpacked_array(results->src_files.source_files, results->src_files.source_files_count); + bundle.sections[RDI_SectionKind_LineTables] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_tables, results->line_tables.line_tables_count); + bundle.sections[RDI_SectionKind_LineInfoVOffs] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_table_voffs, results->line_tables.line_table_voffs_count); + bundle.sections[RDI_SectionKind_LineInfoLines] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_table_lines, results->line_tables.line_table_lines_count); + bundle.sections[RDI_SectionKind_LineInfoColumns] = rdim_serialized_section_make_unpacked_array(results->line_tables.line_table_columns, results->line_tables.line_table_columns_count); + bundle.sections[RDI_SectionKind_SourceLineMaps] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_maps, results->src_files.source_line_maps_count); + bundle.sections[RDI_SectionKind_SourceLineMapNumbers] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_map_nums, results->src_files.source_line_map_nums_count); + bundle.sections[RDI_SectionKind_SourceLineMapRanges] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_map_rngs, results->src_files.source_line_map_rngs_count); + bundle.sections[RDI_SectionKind_SourceLineMapVOffs] = rdim_serialized_section_make_unpacked_array(results->src_files.source_line_map_voffs, results->src_files.source_line_map_voffs_count); + bundle.sections[RDI_SectionKind_Units] = rdim_serialized_section_make_unpacked_array(results->units.units, results->units.units_count); + bundle.sections[RDI_SectionKind_UnitVMap] = rdim_serialized_section_make_unpacked_array(results->unit_vmap.vmap.vmap, results->unit_vmap.vmap.count+1); + bundle.sections[RDI_SectionKind_TypeNodes] = rdim_serialized_section_make_unpacked_array(results->type_nodes.type_nodes, results->type_nodes.type_nodes_count); + bundle.sections[RDI_SectionKind_UDTs] = rdim_serialized_section_make_unpacked_array(results->udts.udts, results->udts.udts_count); + bundle.sections[RDI_SectionKind_Members] = rdim_serialized_section_make_unpacked_array(results->udts.members, results->udts.members_count); + bundle.sections[RDI_SectionKind_EnumMembers] = rdim_serialized_section_make_unpacked_array(results->udts.enum_members, results->udts.enum_members_count); + bundle.sections[RDI_SectionKind_GlobalVariables] = rdim_serialized_section_make_unpacked_array(results->global_variables.global_variables, results->global_variables.global_variables_count); + bundle.sections[RDI_SectionKind_GlobalVMap] = rdim_serialized_section_make_unpacked_array(results->global_vmap.vmap.vmap, results->global_vmap.vmap.count+1); + bundle.sections[RDI_SectionKind_ThreadVariables] = rdim_serialized_section_make_unpacked_array(results->thread_variables.thread_variables, results->thread_variables.thread_variables_count); + bundle.sections[RDI_SectionKind_Procedures] = rdim_serialized_section_make_unpacked_array(results->procedures.procedures, results->procedures.procedures_count); + bundle.sections[RDI_SectionKind_Scopes] = rdim_serialized_section_make_unpacked_array(results->scopes.scopes, results->scopes.scopes_count); + bundle.sections[RDI_SectionKind_ScopeVOffData] = rdim_serialized_section_make_unpacked_array(results->scopes.scope_voffs, results->scopes.scope_voffs_count); + bundle.sections[RDI_SectionKind_ScopeVMap] = rdim_serialized_section_make_unpacked_array(results->scope_vmap.vmap.vmap, results->scope_vmap.vmap.count+1); + bundle.sections[RDI_SectionKind_InlineSites] = rdim_serialized_section_make_unpacked_array(results->inline_sites.inline_sites, results->inline_sites.inline_sites_count); + bundle.sections[RDI_SectionKind_Locals] = rdim_serialized_section_make_unpacked_array(results->scopes.locals, results->scopes.locals_count); + bundle.sections[RDI_SectionKind_LocationBlocks] = rdim_serialized_section_make_unpacked_array(results->scopes.location_blocks, results->scopes.location_blocks_count); + bundle.sections[RDI_SectionKind_LocationData] = rdim_serialized_section_make_unpacked_array(results->scopes.location_data, results->scopes.location_data_size); + bundle.sections[RDI_SectionKind_NameMaps] = rdim_serialized_section_make_unpacked_array(results->top_level_name_maps.name_maps, results->top_level_name_maps.name_maps_count); + bundle.sections[RDI_SectionKind_NameMapBuckets] = rdim_serialized_section_make_unpacked_array(results->name_maps.buckets, results->name_maps.buckets_count); + bundle.sections[RDI_SectionKind_NameMapNodes] = rdim_serialized_section_make_unpacked_array(results->name_maps.nodes, results->name_maps.nodes_count); + return bundle; +} RDI_PROC RDIM_String8List -rdim_serialized_strings_from_params_bake_section_list(RDIM_Arena *arena, RDIM_BakeParams *params, RDIM_BakeSectionList *sections) +rdim_file_blobs_from_section_bundle(RDIM_Arena *arena, RDIM_SerializedSectionBundle *bundle) { RDIM_String8List strings; rdim_memzero_struct(&strings); { RDIM_Temp scratch = rdim_scratch_begin(&arena, 1); - //- rjf: calculate total possible section count, given these params - RDI_U64 section_count = rdim_bake_section_count_from_params(params); - - //- rjf: make table for actually laid out sections - RDIM_BakeSection **bake_sections = rdim_push_array(scratch.arena, RDIM_BakeSection *, section_count); - for(RDIM_BakeSectionNode *n = sections->first; n != 0; n = n->next) - { - RDIM_BakeSection *bake_section = &n->v; - RDI_U64 idx = rdim_bake_section_idx_from_params_tag_idx(params, bake_section->tag, bake_section->tag_idx); - if(0 <= idx && idx < section_count) - { - if(bake_sections[idx] != 0) - { - // TODO(rjf): error - malformed input! we have a duplicate section. - } - else - { - bake_sections[idx] = bake_section; - } - } - } - - //- rjf: push empty header & data section table + // rjf: push empty header & data section table RDI_Header *rdi_header = rdim_push_array(arena, RDI_Header, 1); - RDI_DataSection *rdi_sections = rdim_push_array(arena, RDI_DataSection, section_count); + RDI_Section *rdi_sections = rdim_push_array(arena, RDI_Section, RDI_SectionKind_COUNT); rdim_str8_list_push(arena, &strings, rdim_str8_struct(rdi_header)); rdim_str8_list_push_align(arena, &strings, 8); U32 data_section_off = (U32)strings.total_size; - rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)rdi_sections, sizeof(RDI_DataSection)*section_count)); + rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)rdi_sections, sizeof(RDI_Section)*RDI_SectionKind_COUNT)); // rjf: fill baked header { rdi_header->magic = RDI_MAGIC_CONSTANT; rdi_header->encoding_version = RDI_ENCODING_VERSION; rdi_header->data_section_off = data_section_off; - rdi_header->data_section_count = section_count; + rdi_header->data_section_count = RDI_SectionKind_COUNT; } // rjf: fill baked data section table - U64 dst_idx = 0; - for(RDI_U64 src_idx = 0; src_idx < section_count; src_idx += 1, dst_idx += 1) + for(RDI_SectionKind k = RDI_SectionKind_NULL; k < RDI_SectionKind_COUNT; k += 1) { - RDIM_BakeSection *src = bake_sections[src_idx]; - if(src == 0) { continue; } - RDI_DataSection *dst = rdi_sections+dst_idx; + RDI_Section *dst = rdi_sections+k; U64 data_section_off = 0; - if(src->encoded_size != 0) + if(bundle->sections[k].encoded_size != 0) { rdim_str8_list_push_align(arena, &strings, 8); data_section_off = strings.total_size; - rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)src->data, src->encoded_size)); + rdim_str8_list_push(arena, &strings, rdim_str8((RDI_U8 *)bundle->sections[k].data, bundle->sections[k].encoded_size)); } - dst->tag = src->tag; - dst->encoding = src->encoding; + dst->encoding = bundle->sections[k].encoding; dst->off = data_section_off; - dst->encoded_size = src->encoded_size; - dst->unpacked_size = src->unpacked_size; + dst->encoded_size = bundle->sections[k].encoded_size; + dst->unpacked_size = bundle->sections[k].unpacked_size; } rdim_scratch_end(scratch); diff --git a/src/lib_rdi_make/rdi_make.h b/src/lib_rdi_make/rdi_make.h index c12c2a0e..e2610ba0 100644 --- a/src/lib_rdi_make/rdi_make.h +++ b/src/lib_rdi_make/rdi_make.h @@ -417,6 +417,7 @@ struct RDIM_TopLevelInfo RDIM_String8 exe_name; RDI_U64 exe_hash; RDI_U64 voff_max; + RDIM_String8 producer_name; }; //////////////////////////////// @@ -484,10 +485,12 @@ struct RDIM_SrcFileChunkList RDIM_SrcFileChunkNode *last; RDI_U64 chunk_count; RDI_U64 total_count; + RDI_U64 source_line_map_count; + RDI_U64 total_line_count; }; //////////////////////////////// -//~ rjf: Per-Compilation-Unit Info Types +//~ rjf: Line Info Types typedef struct RDIM_LineSequence RDIM_LineSequence; struct RDIM_LineSequence @@ -506,14 +509,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 +556,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 +766,38 @@ 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_Type *type; + RDIM_Type *owner; + RDIM_LineTable *line_table; +}; + +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 @@ -761,6 +824,7 @@ struct RDIM_Scope RDIM_Local *first_local; RDIM_Local *last_local; RDI_U32 local_count; + RDIM_InlineSite *inline_site; }; typedef struct RDIM_ScopeChunkNode RDIM_ScopeChunkNode; @@ -799,10 +863,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 @@ -811,10 +877,10 @@ typedef struct RDIM_BakeSection RDIM_BakeSection; struct RDIM_BakeSection { void *data; - RDI_DataSectionEncoding encoding; + RDI_SectionEncoding encoding; RDI_U64 encoded_size; RDI_U64 unpacked_size; - RDI_DataSectionTag tag; + RDI_SectionKind tag; RDI_U64 tag_idx; }; @@ -991,6 +1057,217 @@ struct RDIM_VMapMarker RDI_U32 begin_range; }; +//- rjf: baking results + +typedef struct RDIM_TopLevelInfoBakeResult RDIM_TopLevelInfoBakeResult; +struct RDIM_TopLevelInfoBakeResult +{ + RDI_TopLevelInfo *top_level_info; +}; + +typedef struct RDIM_BinarySectionBakeResult RDIM_BinarySectionBakeResult; +struct RDIM_BinarySectionBakeResult +{ + RDI_BinarySection *binary_sections; + RDI_U64 binary_sections_count; +}; + +typedef struct RDIM_UnitBakeResult RDIM_UnitBakeResult; +struct RDIM_UnitBakeResult +{ + RDI_Unit *units; + RDI_U64 units_count; +}; + +typedef struct RDIM_UnitVMapBakeResult RDIM_UnitVMapBakeResult; +struct RDIM_UnitVMapBakeResult +{ + RDIM_BakeVMap vmap; +}; + +typedef struct RDIM_SrcFileBakeResult RDIM_SrcFileBakeResult; +struct RDIM_SrcFileBakeResult +{ + RDI_SourceFile *source_files; + RDI_U64 source_files_count; + RDI_SourceLineMap *source_line_maps; + RDI_U64 source_line_maps_count; + RDI_U32 *source_line_map_nums; + RDI_U32 *source_line_map_rngs; + RDI_U64 *source_line_map_voffs; + RDI_U64 source_line_map_nums_count; + RDI_U64 source_line_map_rngs_count; + RDI_U64 source_line_map_voffs_count; +}; + +typedef struct RDIM_LineTableBakeResult RDIM_LineTableBakeResult; +struct RDIM_LineTableBakeResult +{ + RDI_LineTable *line_tables; + RDI_U64 line_tables_count; + RDI_U64 *line_table_voffs; + RDI_U64 line_table_voffs_count; + RDI_Line *line_table_lines; + RDI_U64 line_table_lines_count; + RDI_Column *line_table_columns; + RDI_U64 line_table_columns_count; +}; + +typedef struct RDIM_TypeNodeBakeResult RDIM_TypeNodeBakeResult; +struct RDIM_TypeNodeBakeResult +{ + RDI_TypeNode *type_nodes; + RDI_U64 type_nodes_count; +}; + +typedef struct RDIM_UDTBakeResult RDIM_UDTBakeResult; +struct RDIM_UDTBakeResult +{ + RDI_UDT *udts; + RDI_U64 udts_count; + RDI_Member *members; + RDI_U64 members_count; + RDI_EnumMember *enum_members; + RDI_U64 enum_members_count; +}; + +typedef struct RDIM_GlobalVariableBakeResult RDIM_GlobalVariableBakeResult; +struct RDIM_GlobalVariableBakeResult +{ + RDI_GlobalVariable *global_variables; + RDI_U64 global_variables_count; +}; + +typedef struct RDIM_GlobalVMapBakeResult RDIM_GlobalVMapBakeResult; +struct RDIM_GlobalVMapBakeResult +{ + RDIM_BakeVMap vmap; +}; + +typedef struct RDIM_ThreadVariableBakeResult RDIM_ThreadVariableBakeResult; +struct RDIM_ThreadVariableBakeResult +{ + RDI_ThreadVariable *thread_variables; + RDI_U64 thread_variables_count; +}; + +typedef struct RDIM_ProcedureBakeResult RDIM_ProcedureBakeResult; +struct RDIM_ProcedureBakeResult +{ + RDI_Procedure *procedures; + RDI_U64 procedures_count; +}; + +typedef struct RDIM_ScopeBakeResult RDIM_ScopeBakeResult; +struct RDIM_ScopeBakeResult +{ + RDI_Scope *scopes; + RDI_U64 scopes_count; + RDI_U64 *scope_voffs; + RDI_U64 scope_voffs_count; + RDI_Local *locals; + RDI_U64 locals_count; + RDI_LocationBlock *location_blocks; + RDI_U64 location_blocks_count; + RDI_U8 *location_data; + RDI_U64 location_data_size; +}; + +typedef struct RDIM_ScopeVMapBakeResult RDIM_ScopeVMapBakeResult; +struct RDIM_ScopeVMapBakeResult +{ + RDIM_BakeVMap vmap; +}; + +typedef struct RDIM_InlineSiteBakeResult RDIM_InlineSiteBakeResult; +struct RDIM_InlineSiteBakeResult +{ + RDI_InlineSite *inline_sites; + RDI_U64 inline_sites_count; +}; + +typedef struct RDIM_TopLevelNameMapBakeResult RDIM_TopLevelNameMapBakeResult; +struct RDIM_TopLevelNameMapBakeResult +{ + RDI_NameMap *name_maps; + RDI_U64 name_maps_count; +}; + +typedef struct RDIM_NameMapBakeResult RDIM_NameMapBakeResult; +struct RDIM_NameMapBakeResult +{ + RDI_NameMapBucket *buckets; + RDI_U64 buckets_count; + RDI_NameMapNode *nodes; + RDI_U64 nodes_count; +}; + +typedef struct RDIM_FilePathBakeResult RDIM_FilePathBakeResult; +struct RDIM_FilePathBakeResult +{ + RDI_FilePathNode *nodes; + RDI_U64 nodes_count; +}; + +typedef struct RDIM_StringBakeResult RDIM_StringBakeResult; +struct RDIM_StringBakeResult +{ + RDI_U32 *string_offs; + RDI_U64 string_offs_count; + RDI_U8 *string_data; + RDI_U64 string_data_size; +}; + +typedef struct RDIM_IndexRunBakeResult RDIM_IndexRunBakeResult; +struct RDIM_IndexRunBakeResult +{ + RDI_U32 *idx_runs; + RDI_U64 idx_count; +}; + +typedef struct RDIM_BakeResults RDIM_BakeResults; +struct RDIM_BakeResults +{ + RDIM_TopLevelInfoBakeResult top_level_info; + RDIM_BinarySectionBakeResult binary_sections; + RDIM_UnitBakeResult units; + RDIM_UnitVMapBakeResult unit_vmap; + RDIM_SrcFileBakeResult src_files; + RDIM_LineTableBakeResult line_tables; + RDIM_TypeNodeBakeResult type_nodes; + RDIM_UDTBakeResult udts; + RDIM_GlobalVariableBakeResult global_variables; + RDIM_GlobalVMapBakeResult global_vmap; + RDIM_ThreadVariableBakeResult thread_variables; + RDIM_ProcedureBakeResult procedures; + RDIM_ScopeBakeResult scopes; + RDIM_InlineSiteBakeResult inline_sites; + RDIM_ScopeVMapBakeResult scope_vmap; + RDIM_TopLevelNameMapBakeResult top_level_name_maps; + RDIM_NameMapBakeResult name_maps; + RDIM_FilePathBakeResult file_paths; + RDIM_StringBakeResult strings; + RDIM_IndexRunBakeResult idx_runs; +}; + +//////////////////////////////// +//~ rjf: Serialization Types + +typedef struct RDIM_SerializedSection RDIM_SerializedSection; +struct RDIM_SerializedSection +{ + void *data; + RDI_U64 encoded_size; + RDI_U64 unpacked_size; + RDI_SectionEncoding encoding; +}; + +typedef struct RDIM_SerializedSectionBundle RDIM_SerializedSectionBundle; +struct RDIM_SerializedSectionBundle +{ + RDIM_SerializedSection sections[RDI_SectionKind_COUNT]; +}; + //////////////////////////////// //~ rjf: Basic Helpers @@ -1028,8 +1305,9 @@ RDI_PROC RDIM_String8 rdim_str8_copy(RDIM_Arena *arena, RDIM_String8 src); RDI_PROC RDIM_String8 rdim_str8f(RDIM_Arena *arena, char *fmt, ...); RDI_PROC RDIM_String8 rdim_str8fv(RDIM_Arena *arena, char *fmt, va_list args); RDI_PROC RDI_S32 rdim_str8_match(RDIM_String8 a, RDIM_String8 b, RDIM_StringMatchFlags flags); -#define rdim_str8_lit(S) rdim_str8((RDI_U8*)(S), sizeof(S) - 1) -#define rdim_str8_struct(S) rdim_str8((RDI_U8*)(S), sizeof(*(S))) +#define rdim_str8_lit(S) rdim_str8((RDI_U8*)(S), sizeof(S) - 1) +#define rdim_str8_struct(S) rdim_str8((RDI_U8*)(S), sizeof(*(S))) +#define rdim_str8_struct_array(S, C) rdim_str8((RDI_U8*)(S), sizeof(*(S)) * (C)) //- rjf: string lists RDI_PROC void rdim_str8_list_push(RDIM_Arena *arena, RDIM_String8List *list, RDIM_String8 string); @@ -1056,13 +1334,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 @@ -1083,6 +1368,13 @@ RDI_PROC RDIM_Symbol *rdim_symbol_chunk_list_push(RDIM_Arena *arena, RDIM_Symbol RDI_PROC RDI_U64 rdim_idx_from_symbol(RDIM_Symbol *symbol); RDI_PROC void rdim_symbol_chunk_list_concat_in_place(RDIM_SymbolChunkList *dst, RDIM_SymbolChunkList *to_push); +//////////////////////////////// +//~ rjf: [Building] Inline Site Info Building + +RDI_PROC RDIM_InlineSite *rdim_inline_site_chunk_list_push(RDIM_Arena *arena, RDIM_InlineSiteChunkList *list, RDI_U64 cap); +RDI_PROC RDI_U64 rdim_idx_from_inline_site(RDIM_InlineSite *inline_site); +RDI_PROC void rdim_inline_site_chunk_list_concat_in_place(RDIM_InlineSiteChunkList *dst, RDIM_InlineSiteChunkList *to_push); + //////////////////////////////// //~ rjf: [Building] Scope Info Building @@ -1109,12 +1401,6 @@ RDI_PROC RDIM_Location *rdim_push_location_val_reg(RDIM_Arena *arena, RDI_U8 reg //- rjf: location sets RDI_PROC void rdim_location_set_push_case(RDIM_Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_LocationSet *locset, RDIM_Rng1U64 voff_range, RDIM_Location *location); -//////////////////////////////// -//~ rjf: [Baking Helpers] Baked File Layout Calculations - -RDI_PROC RDI_U64 rdim_bake_section_count_from_params(RDIM_BakeParams *params); -RDI_PROC RDI_U64 rdim_bake_section_idx_from_params_tag_idx(RDIM_BakeParams *params, RDI_DataSectionTag tag, RDI_U64 idx); - //////////////////////////////// //~ rjf: [Baking Helpers] Baked VMap Building @@ -1136,7 +1422,7 @@ RDI_PROC RDIM_BakeStringMapBaseIndices rdim_bake_string_map_base_indices_from_ma //- rjf: finalized bake string map RDI_PROC RDIM_BakeStringMapTight rdim_bake_string_map_tight_from_loose(RDIM_Arena *arena, RDIM_BakeStringMapTopology *map_topology, RDIM_BakeStringMapBaseIndices *map_base_indices, RDIM_BakeStringMapLoose *map); -RDI_PROC RDI_U64 rdim_bake_idx_from_string(RDIM_BakeStringMapTight *map, RDIM_String8 string); +RDI_PROC RDI_U32 rdim_bake_idx_from_string(RDIM_BakeStringMapTight *map, RDIM_String8 string); //- rjf: bake idx run map reading/writing RDI_PROC RDI_U64 rdim_hash_from_idx_run(RDI_U32 *idx_run, RDI_U32 count); @@ -1155,7 +1441,7 @@ RDI_PROC void rdim_bake_name_map_push(RDIM_Arena *arena, RDIM_BakeNameMap *map, //~ rjf: [Baking Helpers] Data Section List Building Helpers RDI_PROC RDIM_BakeSection *rdim_bake_section_list_push(RDIM_Arena *arena, RDIM_BakeSectionList *list); -RDI_PROC RDIM_BakeSection *rdim_bake_section_list_push_new_unpacked(RDIM_Arena *arena, RDIM_BakeSectionList *list, void *data, RDI_U64 size, RDI_DataSectionTag tag, RDI_U64 tag_idx); +RDI_PROC RDIM_BakeSection *rdim_bake_section_list_push_new_unpacked(RDIM_Arena *arena, RDIM_BakeSectionList *list, void *data, RDI_U64 size, RDI_SectionKind tag, RDI_U64 tag_idx); RDI_PROC void rdim_bake_section_list_concat_in_place(RDIM_BakeSectionList *dst, RDIM_BakeSectionList *to_push); //////////////////////////////// @@ -1192,64 +1478,42 @@ RDI_PROC RDIM_BakeIdxRunMap *rdim_bake_idx_run_map_from_params(RDIM_Arena *arena RDI_PROC RDIM_BakePathTree *rdim_bake_path_tree_from_params(RDIM_Arena *arena, RDIM_BakeParams *params); //////////////////////////////// -//~ rjf: [Baking] Build Artifacts -> Data Section Lists +//~ rjf: [Baking] Build Artifacts -> Baked Versions -//- rjf: top-level info -RDI_PROC RDIM_BakeSectionList rdim_bake_top_level_info_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); +//- rjf: partial/joinable baking functions +RDI_PROC RDIM_NameMapBakeResult rdim_bake_name_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *src); -//- rjf: binary sections -RDI_PROC RDIM_BakeSectionList rdim_bake_binary_section_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); +//- rjf: partial bakes -> final bake functions +RDI_PROC RDIM_NameMapBakeResult rdim_name_map_bake_results_combine(RDIM_Arena *arena, RDIM_NameMapBakeResult *results, RDI_U64 results_count); -//- rjf: units -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); - -//- rjf: unit vmap -RDI_PROC RDIM_BakeSectionList rdim_bake_unit_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params); - -//- rjf: source files -RDI_PROC RDIM_BakeSectionList rdim_bake_src_file_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_BakeParams *params); - -//- rjf: type nodes -RDI_PROC RDIM_BakeSectionList rdim_bake_type_node_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeParams *params); - -//- rjf: UDTs -RDI_PROC RDIM_BakeSectionList rdim_bake_udt_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); - -//- rjf: global variables -RDI_PROC RDIM_BakeSectionList rdim_bake_global_variable_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); - -//- rjf: global vmap -RDI_PROC RDIM_BakeSectionList rdim_bake_global_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params); - -//- rjf: thread variables -RDI_PROC RDIM_BakeSectionList rdim_bake_thread_variable_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); - -//- rjf: procedures -RDI_PROC RDIM_BakeSectionList rdim_bake_procedure_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); - -//- rjf: scopes -RDI_PROC RDIM_BakeSectionList rdim_bake_scope_section_list_from_params(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeParams *params); - -//- rjf: scope vmap -RDI_PROC RDIM_BakeSectionList rdim_bake_scope_vmap_section_list_from_params(RDIM_Arena *arena, RDIM_BakeParams *params); - -//- rjf: name maps -RDI_PROC RDIM_BakeSectionList rdim_bake_top_level_name_map_section_list_from_params_maps(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeParams *params, RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT]); -RDI_PROC RDIM_BakeSectionList rdim_bake_name_map_section_list_from_params_kind_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeParams *params, RDI_NameMapKind k, RDIM_BakeNameMap *map); - -//- rjf: file paths -RDI_PROC RDIM_BakeSectionList rdim_bake_file_path_section_list_from_path_tree(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree); - -//- rjf: strings -RDI_PROC RDIM_BakeSectionList rdim_bake_string_section_list_from_string_map(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings); - -//- rjf: index runs -RDI_PROC RDIM_BakeSectionList rdim_bake_idx_run_section_list_from_idx_run_map(RDIM_Arena *arena, RDIM_BakeIdxRunMap *idx_runs); +//- rjf: independent (top-level, global) baking functions +RDI_PROC RDIM_TopLevelInfoBakeResult rdim_bake_top_level_info(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_TopLevelInfo *src); +RDI_PROC RDIM_BinarySectionBakeResult rdim_bake_binary_sections(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BinarySectionList *src); +RDI_PROC RDIM_UnitBakeResult rdim_bake_units(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_UnitChunkList *src); +RDI_PROC RDIM_UnitVMapBakeResult rdim_bake_unit_vmap(RDIM_Arena *arena, RDIM_UnitChunkList *units); +RDI_PROC RDIM_SrcFileBakeResult rdim_bake_src_files(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree, RDIM_SrcFileChunkList *src); +RDI_PROC RDIM_LineTableBakeResult rdim_bake_line_tables(RDIM_Arena *arena, RDIM_LineTableChunkList *src); +RDI_PROC RDIM_TypeNodeBakeResult rdim_bake_types(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_TypeChunkList *src); +RDI_PROC RDIM_UDTBakeResult rdim_bake_udts(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_UDTChunkList *src); +RDI_PROC RDIM_GlobalVariableBakeResult rdim_bake_global_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src); +RDI_PROC RDIM_GlobalVMapBakeResult rdim_bake_global_vmap(RDIM_Arena *arena, RDIM_SymbolChunkList *src); +RDI_PROC RDIM_ThreadVariableBakeResult rdim_bake_thread_variables(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src); +RDI_PROC RDIM_ProcedureBakeResult rdim_bake_procedures(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_SymbolChunkList *src); +RDI_PROC RDIM_ScopeBakeResult rdim_bake_scopes(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_ScopeChunkList *src); +RDI_PROC RDIM_ScopeVMapBakeResult rdim_bake_scope_vmap(RDIM_Arena *arena, RDIM_ScopeChunkList *src); +RDI_PROC RDIM_InlineSiteBakeResult rdim_bake_inline_sites(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_InlineSiteChunkList *src); +RDI_PROC RDIM_TopLevelNameMapBakeResult rdim_bake_name_maps_top_level(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakeIdxRunMap *idx_runs, RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT]); +RDI_PROC RDIM_FilePathBakeResult rdim_bake_file_paths(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings, RDIM_BakePathTree *path_tree); +RDI_PROC RDIM_StringBakeResult rdim_bake_strings(RDIM_Arena *arena, RDIM_BakeStringMapTight *strings); +RDI_PROC RDIM_IndexRunBakeResult rdim_bake_index_runs(RDIM_Arena *arena, RDIM_BakeIdxRunMap *idx_runs); //////////////////////////////// -//~ rjf: [Serializing] Baked Data Section List -> Serialized Binary Strings +//~ rjf: [Serializing] Bake Results -> String Blobs -RDI_PROC RDIM_String8List rdim_serialized_strings_from_params_bake_section_list(RDIM_Arena *arena, RDIM_BakeParams *params, RDIM_BakeSectionList *sections); +RDI_PROC RDIM_SerializedSection rdim_serialized_section_make_unpacked(void *data, RDI_U64 size); +#define rdim_serialized_section_make_unpacked_struct(ptr) rdim_serialized_section_make_unpacked((ptr), sizeof(*(ptr))) +#define rdim_serialized_section_make_unpacked_array(ptr, count) rdim_serialized_section_make_unpacked((ptr), sizeof(*(ptr))*(count)) +RDI_PROC RDIM_SerializedSectionBundle rdim_serialized_section_bundle_from_bake_results(RDIM_BakeResults *results); +RDI_PROC RDIM_String8List rdim_file_blobs_from_section_bundle(RDIM_Arena *arena, RDIM_SerializedSectionBundle *bundle); #endif // RDI_MAKE_H diff --git a/src/mule/mule_main.cpp b/src/mule/mule_main.cpp index a9647a31..d8791ca1 100644 --- a/src/mule/mule_main.cpp +++ b/src/mule/mule_main.cpp @@ -1514,6 +1514,34 @@ extern "C"{ #include "mule_c.h" } +//////////////////////////////// +//~ rjf: Basic Inline Line Info Tests + +#if defined(_MSC_VER) +# define FORCE_INLINE __forceinline +#elif defined(__clang__) +# define FORCE_INLINE __attribute__((always_inline)) +#else +# error need force inline for this compiler +#endif + +static FORCE_INLINE void +basic_inlinee(int inlinee_param_x, int inlinee_param_y, int inlinee_param_z) +{ + OutputDebugStringA("A\n"); + OutputDebugStringA("B\n"); + OutputDebugStringA("C\n"); + OutputDebugStringA("D\n"); +} + +static void +basic_inline_tests(void) +{ + OutputDebugStringA("{\n"); + basic_inlinee(12, 34, 56); + OutputDebugStringA("}\n"); +} + //////////////////////////////// //~ rjf: Fancy Visualization Eval Tests @@ -2269,6 +2297,14 @@ debug_string_tests(void) { OutputDebugStringA("Hello, World!\n"); } + char message[65409+1]; + memset(&message[0], '=', sizeof(message)); + for(int i = 1; i < sizeof(message); i += 128) + { + message[i] = '\n'; + } + message[sizeof(message) - 1] = 0; + OutputDebugStringA(message); #endif } @@ -2595,6 +2631,8 @@ mule_main(int argc, char** argv){ alloca_stepping_tests(); + basic_inline_tests(); + inline_stepping_tests(); overloaded_line_stepping_tests(); diff --git a/src/raddbg/raddbg.h b/src/raddbg/raddbg.h index 4c065424..cd01b5d0 100644 --- a/src/raddbg/raddbg.h +++ b/src/raddbg/raddbg.h @@ -4,6 +4,8 @@ //////////////////////////////// //~ rjf: Frontend/UI Pass Tasks // +// [ ] mouse-driven way to complete file/folder selection, or more generally +// query completion // [ ] display threads at their last exception address, rather than current // rip, if applicable // diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index d9892de7..9db07fce 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -515,21 +515,30 @@ entry_point(CmdLine *cmd_line) bake2srlz = p2r_bake(scratch.arena, convert2bake); } + //- rjf: serialize + P2R_Serialize2File *srlz2file = 0; + ProfScope("serialize") + { + srlz2file = push_array(scratch.arena, P2R_Serialize2File, 1); + srlz2file->bundle = rdim_serialized_section_bundle_from_bake_results(&bake2srlz->bake_results); + } + //- rjf: compress - P2R_Bake2Serialize *bake2srlz_compressed = bake2srlz; + P2R_Serialize2File *srlz2file_compressed = srlz2file; if(cmd_line_has_flag(cmd_line, str8_lit("compress"))) ProfScope("compress") { - bake2srlz_compressed = p2r_compress(scratch.arena, bake2srlz); + srlz2file_compressed = push_array(scratch.arena, P2R_Serialize2File, 1); + srlz2file_compressed = p2r_compress(scratch.arena, srlz2file); } //- rjf: serialize - String8List serialize_out = rdim_serialized_strings_from_params_bake_section_list(scratch.arena, &convert2bake->bake_params, &bake2srlz_compressed->sections); + String8List blobs = rdim_file_blobs_from_section_bundle(scratch.arena, &srlz2file_compressed->bundle); //- rjf: write if(out_file_is_good) { U64 off = 0; - for(String8Node *n = serialize_out.first; n != 0; n = n->next) + for(String8Node *n = blobs.first; n != 0; n = n->next) { os_file_write(out_file, r1u64(off, off+n->string.size), n->string.str); off += n->string.size; diff --git a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c index 26d043cd..9a32b06e 100644 --- a/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c +++ b/src/rdi_breakpad_from_pdb/rdi_breakpad_from_pdb_main.c @@ -26,7 +26,7 @@ #include "base/base_inc.h" #include "os/os_inc.h" #include "task_system/task_system.h" -#include "rdi_make_local/rdi_make_local.h" +#include "rdi_make/rdi_make_local.h" #include "coff/coff.h" #include "codeview/codeview.h" #include "codeview/codeview_stringize.h" @@ -39,7 +39,7 @@ #include "base/base_inc.c" #include "os/os_inc.c" #include "task_system/task_system.c" -#include "rdi_make_local/rdi_make_local.c" +#include "rdi_make/rdi_make_local.c" #include "coff/coff.c" #include "codeview/codeview.c" #include "codeview/codeview_stringize.c" @@ -56,76 +56,30 @@ typedef struct P2B_BakeUnitVMapIn P2B_BakeUnitVMapIn; struct P2B_BakeUnitVMapIn { - RDIM_BakeParams *params; -}; - -typedef struct P2B_BakeUnitVMapOut P2B_BakeUnitVMapOut; -struct P2B_BakeUnitVMapOut -{ - RDI_VMapEntry *vmap_entries; - RDI_U64 vmap_entries_count; + RDIM_UnitChunkList *units; }; internal TS_TASK_FUNCTION_DEF(p2b_bake_unit_vmap_task__entry_point) { P2B_BakeUnitVMapIn *in = (P2B_BakeUnitVMapIn *)p; - P2B_BakeUnitVMapOut *out = push_array(arena, P2B_BakeUnitVMapOut, 1); - RDIM_BakeSectionList sections = rdim_bake_unit_vmap_section_list_from_params(arena, in->params); - RDIM_BakeSection *vmap_section = 0; - for(RDIM_BakeSectionNode *n = sections.first; n != 0 && vmap_section == 0; n = n->next) - { - switch(n->v.tag) - { - default:{}break; - case RDI_DataSectionTag_UnitVmap:{vmap_section = &n->v;}break; - } - } - if(vmap_section != 0) - { - out->vmap_entries = (RDI_VMapEntry *)vmap_section->data; - out->vmap_entries_count = vmap_section->unpacked_size/sizeof(RDI_VMapEntry); - } + RDIM_UnitVMapBakeResult *out = push_array(arena, RDIM_UnitVMapBakeResult, 1); + *out = rdim_bake_unit_vmap(arena, in->units); return out; } -//- rjf: per-unit baking +//- rjf: line table baking -typedef struct P2B_BakeUnitIn P2B_BakeUnitIn; -struct P2B_BakeUnitIn +typedef struct P2B_BakeLineTablesIn P2B_BakeLineTablesIn; +struct P2B_BakeLineTablesIn { - RDIM_Unit *unit; + RDIM_LineTableChunkList *line_tables; }; -typedef struct P2B_BakeUnitOut P2B_BakeUnitOut; -struct P2B_BakeUnitOut +internal TS_TASK_FUNCTION_DEF(p2b_bake_line_table_task__entry_point) { - U64 unit_line_count; - U64 *unit_line_voffs; - RDI_Line *unit_lines; -}; - -internal TS_TASK_FUNCTION_DEF(p2b_bake_unit_task__entry_point) -{ - P2B_BakeUnitIn *in = (P2B_BakeUnitIn *)p; - P2B_BakeUnitOut *out = push_array(arena, P2B_BakeUnitOut, 1); - RDIM_BakeSectionList sections = rdim_bake_section_list_from_unit(arena, in->unit); - RDIM_BakeSection *voffs_section = 0; - RDIM_BakeSection *lines_section = 0; - for(RDIM_BakeSectionNode *n = sections.first; n != 0; n = n->next) - { - switch(n->v.tag) - { - default:{}break; - case RDI_DataSectionTag_LineInfoVoffs:{voffs_section = &n->v;}break; - case RDI_DataSectionTag_LineInfoData: {lines_section = &n->v;}break; - } - } - if(voffs_section != 0 && lines_section != 0) - { - out->unit_line_count = lines_section->unpacked_size/sizeof(RDI_Line); - out->unit_line_voffs = (U64 *)voffs_section->data; - out->unit_lines = (RDI_Line *)lines_section->data; - } + P2B_BakeLineTablesIn *in = (P2B_BakeLineTablesIn *)p; + RDIM_LineTableBakeResult *out = push_array(arena, RDIM_LineTableBakeResult, 1); + *out = rdim_bake_line_tables(arena, in->line_tables); return out; } @@ -136,8 +90,9 @@ struct P2B_DumpProcChunkIn { RDI_VMapEntry *unit_vmap; U32 unit_vmap_count; - P2B_BakeUnitOut **bake_units_out; - U64 bake_units_out_count; + U32 *unit_line_table_idxs; + U64 unit_count; + RDIM_LineTableBakeResult *line_tables_bake; RDIM_SymbolChunkNode *chunk; }; @@ -145,6 +100,12 @@ internal TS_TASK_FUNCTION_DEF(p2b_dump_proc_chunk_task__entry_point) { P2B_DumpProcChunkIn *in = (P2B_DumpProcChunkIn *)p; String8List *out = push_array(arena, String8List, 1); + RDI_LineTable *line_tables = in->line_tables_bake->line_tables; + RDI_U64 line_tables_count = in->line_tables_bake->line_tables_count; + RDI_U64 *line_table_voffs = in->line_tables_bake->line_table_voffs; + RDI_U64 line_table_voffs_count = in->line_tables_bake->line_table_voffs_count; + RDI_Line *line_table_lines = in->line_tables_bake->line_table_lines; + RDI_U64 line_table_lines_count = in->line_tables_bake->line_table_lines_count; for(U64 idx = 0; idx < in->chunk->count; idx += 1) { // NOTE(rjf): breakpad does not support multiple voff ranges per procedure. @@ -158,34 +119,45 @@ internal TS_TASK_FUNCTION_DEF(p2b_dump_proc_chunk_task__entry_point) // rjf: dump function lines U64 unit_idx = rdi_vmap_idx_from_voff(in->unit_vmap, in->unit_vmap_count, voff_range.min); - if(0 < unit_idx && unit_idx <= in->bake_units_out_count) + if(0 < unit_idx && unit_idx <= in->unit_count) { - // rjf: unpack unit line info - P2B_BakeUnitOut *bake_unit_out = in->bake_units_out[unit_idx]; - RDI_ParsedLineInfo line_info = {bake_unit_out->unit_line_voffs, bake_unit_out->unit_lines, 0, bake_unit_out->unit_line_count, 0}; - for(U64 voff = voff_range.min, last_voff = 0; - voff < voff_range.max && voff > last_voff;) + U32 line_table_idx = in->unit_line_table_idxs[unit_idx]; + if(0 < line_table_idx && line_table_idx <= line_tables_count) { - RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&line_info, voff); - if(line_info_idx < line_info.count) + // rjf: unpack unit line info + RDI_LineTable *line_table = &line_tables[line_table_idx]; + RDI_ParsedLineTable line_info = { - RDI_Line *line = &line_info.lines[line_info_idx]; - U64 line_voff_min = line_info.voffs[line_info_idx]; - U64 line_voff_opl = line_info.voffs[line_info_idx+1]; - if(line->file_idx != 0) + line_table_voffs + line_table->voffs_base_idx, + line_table_lines + line_table->lines_base_idx, + 0, + line_table->lines_count, + 0 + }; + for(U64 voff = voff_range.min, last_voff = 0; + voff < voff_range.max && voff > last_voff;) + { + RDI_U64 line_info_idx = rdi_line_info_idx_from_voff(&line_info, voff); + if(line_info_idx < line_info.count) { - str8_list_pushf(arena, out, "%I64x %I64x %I64u %I64u\n", - line_voff_min, - line_voff_opl-line_voff_min, - (U64)line->line_num, - (U64)line->file_idx); + RDI_Line *line = &line_info.lines[line_info_idx]; + U64 line_voff_min = line_info.voffs[line_info_idx]; + U64 line_voff_opl = line_info.voffs[line_info_idx+1]; + if(line->file_idx != 0) + { + str8_list_pushf(arena, out, "%I64x %I64x %I64u %I64u\n", + line_voff_min, + line_voff_opl-line_voff_min, + (U64)line->line_num, + (U64)line->file_idx); + } + last_voff = voff; + voff = line_voff_opl; + } + else + { + break; } - last_voff = voff; - voff = line_voff_opl; - } - else - { - break; } } } @@ -248,20 +220,23 @@ entry_point(CmdLine *cmdline) RDIM_BakeParams *params = &convert2bake->bake_params; //- rjf: kick off unit vmap baking - P2B_BakeUnitVMapIn bake_unit_vmap_in = {params}; + P2B_BakeUnitVMapIn bake_unit_vmap_in = {¶ms->units}; TS_Ticket bake_unit_vmap_ticket = ts_kickoff(p2b_bake_unit_vmap_task__entry_point, 0, &bake_unit_vmap_in); - //- rjf: kick off per-unit baking - P2B_BakeUnitIn *bake_units_in = push_array(arena, P2B_BakeUnitIn, params->units.total_count+1); - TS_Ticket *bake_units_tickets = push_array(arena, TS_Ticket, params->units.total_count+1); + //- rjf: kick off line-table baking + P2B_BakeLineTablesIn bake_line_tables_in = {¶ms->line_tables}; + TS_Ticket bake_line_tables_ticket = ts_kickoff(p2b_bake_line_table_task__entry_point, 0, &bake_line_tables_in); + + //- rjf: build unit -> line table idx array + U64 unit_count = params->units.total_count; + U32 *unit_line_table_idxs = push_array(arena, U32, unit_count+1); { - U64 idx = 1; + U64 dst_idx = 1; for(RDIM_UnitChunkNode *n = params->units.first; n != 0; n = n->next) { - for(U64 chunk_idx = 0; chunk_idx < n->count; chunk_idx += 1, idx += 1) + for(U64 n_idx = 0; n_idx < n->count; n_idx += 1, dst_idx += 1) { - bake_units_in[chunk_idx].unit = &n->v[chunk_idx]; - bake_units_tickets[idx] = ts_kickoff(p2b_bake_unit_task__entry_point, 0, &bake_units_in[chunk_idx]); + unit_line_table_idxs[dst_idx] = rdim_idx_from_line_table(n->v[n_idx].line_table); } } } @@ -285,20 +260,15 @@ entry_point(CmdLine *cmdline) //- rjf: join unit vmap ProfBegin("join unit vmap"); - P2B_BakeUnitVMapOut *bake_unit_vmap_out = ts_join_struct(bake_unit_vmap_ticket, max_U64, P2B_BakeUnitVMapOut); - RDI_VMapEntry *unit_vmap = bake_unit_vmap_out->vmap_entries; - U32 unit_vmap_count = (U32)(bake_unit_vmap_out->vmap_entries_count); + RDIM_UnitVMapBakeResult *bake_unit_vmap_out = ts_join_struct(bake_unit_vmap_ticket, max_U64, RDIM_UnitVMapBakeResult); + RDI_VMapEntry *unit_vmap = bake_unit_vmap_out->vmap.vmap; + U32 unit_vmap_count = bake_unit_vmap_out->vmap.count; ProfEnd(); - //- rjf: join units - P2B_BakeUnitOut **bake_units_out = push_array(arena, P2B_BakeUnitOut*, params->units.total_count+1); - ProfScope("join units") - { - for(U64 idx = 1; idx < params->units.total_count+1; idx += 1) - { - bake_units_out[idx] = ts_join_struct(bake_units_tickets[idx], max_U64, P2B_BakeUnitOut); - } - } + //- rjf: join line tables + ProfBegin("join line table"); + RDIM_LineTableBakeResult *bake_line_tables_out = ts_join_struct(bake_line_tables_ticket, max_U64, RDIM_LineTableBakeResult); + ProfEnd(); //- rjf: kick off FUNC & line record dump tasks P2B_DumpProcChunkIn *dump_proc_chunk_in = push_array(arena, P2B_DumpProcChunkIn, params->procedures.chunk_count); @@ -310,8 +280,9 @@ entry_point(CmdLine *cmdline) { dump_proc_chunk_in[task_idx].unit_vmap = unit_vmap; dump_proc_chunk_in[task_idx].unit_vmap_count = unit_vmap_count; - dump_proc_chunk_in[task_idx].bake_units_out = bake_units_out; - dump_proc_chunk_in[task_idx].bake_units_out_count = params->units.total_count+1; + dump_proc_chunk_in[task_idx].unit_line_table_idxs = unit_line_table_idxs; + dump_proc_chunk_in[task_idx].unit_count = unit_count; + dump_proc_chunk_in[task_idx].line_tables_bake = bake_line_tables_out; dump_proc_chunk_in[task_idx].chunk = n; dump_proc_chunk_tickets[task_idx] = ts_kickoff(p2b_dump_proc_chunk_task__entry_point, 0, &dump_proc_chunk_in[task_idx]); } diff --git a/src/rdi_dump/rdi_dump.c b/src/rdi_dump/rdi_dump.c index efa88363..25d57c73 100644 --- a/src/rdi_dump/rdi_dump.c +++ b/src/rdi_dump/rdi_dump.c @@ -5,14 +5,14 @@ //~ rjf: RDI Enum -> String Functions internal String8 -rdi_string_from_data_section_tag(RDI_DataSectionTag v) +rdi_string_from_data_section_kind(RDI_SectionKind v) { - String8 result = str8_lit(""); + String8 result = str8_lit(""); switch(v) { default:{}break; -#define X(name) case RDI_DataSectionTag_##name:{result = str8_lit(#name);}break; - RDI_DataSectionTag_XList +#define X(name, lower, type) case RDI_SectionKind_##name:{result = str8_lit(#name);}break; + RDI_SectionKind_XList #undef X } return result; @@ -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,77 +134,71 @@ 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){ - U64 data_section_count = parsed->dsec_count; - RDI_DataSection *ptr = parsed->dsecs; - for (U64 i = 0; i < data_section_count; i += 1, ptr += 1){ - String8 tag_str = rdi_string_from_data_section_tag(ptr->tag); - str8_list_pushf(arena, out, "%.*sdata_section[%5u] = {0x%08llx, %7u, %7u} %.*s\n", +rdi_stringize_data_sections(Arena *arena, String8List *out, RDI_Parsed *rdi, U32 indent_level) +{ + for(U64 idx = 0; idx < rdi->sections_count; idx += 1) + { + RDI_SectionKind kind = (RDI_SectionKind)idx; + RDI_Section *section = &rdi->sections[idx]; + String8 kind_str = rdi_string_from_data_section_kind(kind); + str8_list_pushf(arena, out, "%.*sdata_section[%5I64u] = {0x%08llx, %7u, %7u} %S\n", indent_level, rdi_stringize_spaces, - i, ptr->off, ptr->encoded_size, ptr->unpacked_size, str8_varg(tag_str)); + idx, section->off, section->encoded_size, section->unpacked_size, kind_str); } } internal void -rdi_stringize_top_level_info(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_TopLevelInfo *tli, U32 indent_level){ +rdi_stringize_top_level_info(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_TopLevelInfo *tli, U32 indent_level) +{ String8 arch_str = rdi_string_from_arch(tli->arch); String8 exe_name = {0}; - exe_name.str = rdi_string_from_idx(parsed, tli->exe_name_string_idx, &exe_name.size); - - 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); + exe_name.str = rdi_string_from_idx(rdi, tli->exe_name_string_idx, &exe_name.size); + String8 producer_name = {0}; + producer_name.str = rdi_string_from_idx(rdi, tli->producer_name_string_idx, &producer_name.size); + str8_list_pushf(arena, out, "%.*sarch=%S\n", indent_level, rdi_stringize_spaces, arch_str); + str8_list_pushf(arena, out, "%.*sexe_name='%S'\n", indent_level, rdi_stringize_spaces, 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, "%.*sproducer_name='%S'\n", indent_level, rdi_stringize_spaces, producer_name); } internal void -rdi_stringize_binary_section(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_BinarySection *bin_section, U32 indent_level){ +rdi_stringize_binary_section(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_BinarySection *bin_section, U32 indent_level) +{ String8 name = {0}; - name.str = rdi_string_from_idx(parsed, bin_section->name_string_idx, &name.size); - str8_list_pushf(arena, out, "%.*sname='%.*s'\n", - indent_level, rdi_stringize_spaces, str8_varg(name)); + name.str = rdi_string_from_idx(rdi, bin_section->name_string_idx, &name.size); + str8_list_pushf(arena, out, "%.*sname='%.*s'\n", indent_level, rdi_stringize_spaces, str8_varg(name)); str8_list_pushf(arena, out, "%.*sflags=", indent_level, rdi_stringize_spaces); 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 *rdi, RDI_FilePathBundle *bundle, RDI_FilePathNode *file_path, U32 indent_level) +{ String8 name = {0}; - name.str = rdi_string_from_idx(parsed, file_path->name_string_idx, &name.size); - + name.str = rdi_string_from_idx(rdi, file_path->name_string_idx, &name.size); U32 this_idx = (U32)(file_path - bundle->file_paths); - - if (file_path->source_file_idx == 0){ + 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){ @@ -236,7 +209,7 @@ rdi_stringize_file_path(Arena *arena, String8List *out, RDI_Parsed *parsed, } // stringize child - rdi_stringize_file_path(arena, out, parsed, bundle, child_node, indent_level + 1); + rdi_stringize_file_path(arena, out, rdi, bundle, child_node, indent_level + 1); // increment iterator child = child_node->next_sibling; @@ -244,104 +217,44 @@ 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){ - // extract line map data - RDI_ParsedLineMap line_map = {0}; - rdi_line_map_from_source_file(parsed, source_file, &line_map); - +rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_SourceFile *source_file, U32 indent_level) +{ // normal source path String8 path = {0}; - path.str = rdi_string_from_idx(parsed, source_file->normal_full_path_string_idx, &path.size); + path.str = rdi_string_from_idx(rdi, source_file->normal_full_path_string_idx, &path.size); str8_list_pushf(arena, out, "%.*spath: \"%S\"\n", indent_level, rdi_stringize_spaces, path); - // stringize line map data - str8_list_pushf(arena, out, "%.*slines:\n", indent_level, rdi_stringize_spaces); - - for (U32 i = 0; i < line_map.count; i += 1){ - U32 line_num = line_map.nums[i]; - - U32 digit_count = 1; - if (line_num > 0){ - U32 x = line_num; - for (;;){ - x /= 10; - if (x == 0){ - break; - } - digit_count += 1; - } - } - - str8_list_pushf(arena, out, "%.*s %u: ", - indent_level, rdi_stringize_spaces, line_num); - - U32 first = line_map.ranges[i]; - U32 opl_raw = line_map.ranges[i + 1]; - U32 opl = ClampTop(opl_raw, line_map.voff_count); - for (U32 j = first; j < opl; j += 1){ - if (j == first){ - str8_list_pushf(arena, out, "0x%08x\n", line_map.voffs[j]); - } - else{ - str8_list_pushf(arena, out, "%.*s0x%08x\n", - indent_level + digit_count + 3, rdi_stringize_spaces, - line_map.voffs[j]); - } - } - } + // rjf: source line map idx + str8_list_pushf(arena, out, "%.*ssource_line_map: %u\n", indent_level, rdi_stringize_spaces, source_file->source_line_map_idx); } internal void -rdi_stringize_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 *rdi, RDI_LineTable *line_table, U32 indent_level) +{ + // rjf: parse line table + RDI_ParsedLineTable parsed_line_table = {0}; + rdi_parsed_from_line_table(rdi, 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, @@ -351,7 +264,75 @@ rdi_stringize_unit(Arena *arena, String8List *out, RDI_Parsed *parsed, } internal void -rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, +rdi_stringize_source_line_map(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_SourceLineMap *map, U32 indent_level) +{ + RDI_ParsedSourceLineMap line_map = {0}; + rdi_parsed_from_source_line_map(rdi, map, &line_map); + str8_list_pushf(arena, out, "%.*slines:\n", indent_level, rdi_stringize_spaces); + + for(U32 i = 0; i < line_map.count; i += 1) + { + U32 line_num = line_map.nums[i]; + U32 digit_count = 1; + if(line_num > 0) + { + U32 x = line_num; + for(;;) + { + x /= 10; + if(x == 0) + { + break; + } + digit_count += 1; + } + } + + str8_list_pushf(arena, out, "%.*s %u: ", indent_level, rdi_stringize_spaces, line_num); + + U32 first = line_map.ranges[i]; + U32 opl_raw = line_map.ranges[i + 1]; + U32 opl = ClampTop(opl_raw, line_map.voff_count); + for(U32 j = first; j < opl; j += 1) + { + if(j == first) + { + str8_list_pushf(arena, out, "0x%08x\n", line_map.voffs[j]); + } + else + { + str8_list_pushf(arena, out, "%.*s0x%08x\n", + indent_level + digit_count + 3, rdi_stringize_spaces, + line_map.voffs[j]); + } + } + } +} + +internal void +rdi_stringize_unit(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_Unit *unit, U32 indent_level) +{ + String8 unit_name = {0}; + unit_name.str = rdi_string_from_idx(rdi, unit->unit_name_string_idx, &unit_name.size); + String8 compiler_name = {0}; + compiler_name.str = rdi_string_from_idx(rdi, unit->compiler_name_string_idx, &compiler_name.size); + + str8_list_pushf(arena, out, "%.*sunit_name='%.*s'\n", indent_level, rdi_stringize_spaces, str8_varg(unit_name)); + str8_list_pushf(arena, out, "%.*scompiler_name='%.*s'\n", indent_level, rdi_stringize_spaces, str8_varg(compiler_name)); + + 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 *rdi, RDI_TypeNode *type, U32 indent_level){ RDI_TypeKind kind = type->kind; String8 type_kind_str = rdi_string_from_type_kind(kind); @@ -382,7 +363,7 @@ rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, if (RDI_TypeKind_FirstBuiltIn <= kind && kind <= RDI_TypeKind_LastBuiltIn){ String8 name = {0}; - name.str = rdi_string_from_idx(parsed, type->built_in.name_string_idx, &name.size); + name.str = rdi_string_from_idx(rdi, type->built_in.name_string_idx, &name.size); str8_list_pushf(arena, out, "%.*sbuilt_in.name='%.*s'\n", indent_level, rdi_stringize_spaces, str8_varg(name)); } @@ -403,7 +384,7 @@ rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, U32 run_count_raw = type->constructed.count; U32 run_count = 0; - U32 *run = rdi_idx_run_from_first_count(parsed, run_first, run_count_raw, &run_count); + U32 *run = rdi_idx_run_from_first_count(rdi, run_first, run_count_raw, &run_count); U32 this_type_idx = 0; if (run_count > 0 && type->kind == RDI_TypeKind_Method){ @@ -435,7 +416,7 @@ rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, else if (RDI_TypeKind_FirstUserDefined <= kind && kind <= RDI_TypeKind_LastUserDefined){ String8 name = {0}; - name.str = rdi_string_from_idx(parsed, type->user_defined.name_string_idx, &name.size); + name.str = rdi_string_from_idx(rdi, type->user_defined.name_string_idx, &name.size); str8_list_pushf(arena, out, "%.*suser_defined.name='%.*s'\n", indent_level, rdi_stringize_spaces, str8_varg(name)); str8_list_pushf(arena, out, "%.*suser_defined.direct_type=%u\n", @@ -455,7 +436,7 @@ rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, } internal void -rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *parsed, +rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_UDTMemberBundle *member_bundle, RDI_UDT *udt, U32 indent_level){ str8_list_pushf(arena, out, "%.*sself_type=%u\n", @@ -483,7 +464,7 @@ rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_EnumMember *enum_member = member_bundle->enum_members + first; for (U32 i = first; i < opl; i += 1, enum_member += 1){ String8 name = {0}; - name.str = rdi_string_from_idx(parsed, enum_member->name_string_idx, &name.size); + name.str = rdi_string_from_idx(rdi, enum_member->name_string_idx, &name.size); str8_list_pushf(arena, out, "%.*s '%.*s' %llu\n", indent_level, rdi_stringize_spaces, str8_varg(name), enum_member->val); @@ -511,7 +492,7 @@ rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *parsed, if (member->name_string_idx != 0){ String8 name = {0}; - name.str = rdi_string_from_idx(parsed, member->name_string_idx, &name.size); + name.str = rdi_string_from_idx(rdi, member->name_string_idx, &name.size); str8_list_pushf(arena, out, "%.*s name='%.*s'\n", indent_level, rdi_stringize_spaces, str8_varg(name)); } @@ -529,10 +510,10 @@ rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *parsed, } internal void -rdi_stringize_global_variable(Arena *arena, String8List *out, RDI_Parsed *parsed, +rdi_stringize_global_variable(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_GlobalVariable *global_variable, U32 indent_level){ String8 name = {0}; - name.str = rdi_string_from_idx(parsed, global_variable->name_string_idx, &name.size); + name.str = rdi_string_from_idx(rdi, global_variable->name_string_idx, &name.size); str8_list_pushf(arena, out, "%.*sname='%.*s'\n", indent_level, rdi_stringize_spaces, str8_varg(name)); @@ -551,11 +532,11 @@ rdi_stringize_global_variable(Arena *arena, String8List *out, RDI_Parsed *parsed } internal void -rdi_stringize_thread_variable(Arena *arena, String8List *out, RDI_Parsed *parsed, +rdi_stringize_thread_variable(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_ThreadVariable *thread_var, U32 indent_level){ String8 name = {0}; - name.str = rdi_string_from_idx(parsed, thread_var->name_string_idx, &name.size); + name.str = rdi_string_from_idx(rdi, thread_var->name_string_idx, &name.size); str8_list_pushf(arena, out, "%.*sname='%.*s'\n", indent_level, rdi_stringize_spaces, str8_varg(name)); @@ -574,15 +555,15 @@ rdi_stringize_thread_variable(Arena *arena, String8List *out, RDI_Parsed *parsed } internal void -rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *parsed, +rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_Procedure *proc, U32 indent_level){ String8 name = {0}; - name.str = rdi_string_from_idx(parsed, proc->name_string_idx, &name.size); + name.str = rdi_string_from_idx(rdi, proc->name_string_idx, &name.size); str8_list_pushf(arena, out, "%.*sname='%.*s'\n", indent_level, rdi_stringize_spaces, str8_varg(name)); String8 link_name = {0}; - link_name.str = rdi_string_from_idx(parsed, proc->link_name_string_idx, &link_name.size); + link_name.str = rdi_string_from_idx(rdi, proc->link_name_string_idx, &link_name.size); str8_list_pushf(arena, out, "%.*slink_name='%.*s'\n", indent_level, rdi_stringize_spaces, str8_varg(link_name)); @@ -601,8 +582,9 @@ rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *parsed, } internal void -rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *parsed, - RDI_ScopeBundle *bundle, RDI_Scope *scope, U32 indent_level){ +rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *rdi, + RDI_ScopeBundle *bundle, RDI_Scope *scope, U32 indent_level) +{ U32 this_idx = (U32)(scope - bundle->scopes); @@ -612,6 +594,12 @@ rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *parsed, str8_list_pushf(arena, out, "%.*s proc_idx=%u\n", indent_level, rdi_stringize_spaces, scope->proc_idx); + if(scope->inline_site_idx != 0) + { + str8_list_pushf(arena, out, "%.*s inline_site_idx=%u\n", + indent_level, rdi_stringize_spaces, scope->inline_site_idx); + } + // voff ranges { U32 voff_range_first_raw = scope->voff_range_first; @@ -660,7 +648,7 @@ rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *parsed, indent_level, rdi_stringize_spaces, str8_varg(local_kind_str)); String8 name = {0}; - name.str = rdi_string_from_idx(parsed, local_ptr->name_string_idx, &name.size); + name.str = rdi_string_from_idx(rdi, local_ptr->name_string_idx, &name.size); str8_list_pushf(arena, out, "%.*s name='%.*s'\n", indent_level, rdi_stringize_spaces, str8_varg(name)); @@ -778,7 +766,7 @@ rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *parsed, } // stringize child - rdi_stringize_scope(arena, out, parsed, bundle, child_scope, indent_level + 1); + rdi_stringize_scope(arena, out, rdi, bundle, child_scope, indent_level + 1); // increment iterator child = child_scope->next_sibling_scope_idx; @@ -787,3 +775,14 @@ rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *parsed, str8_list_pushf(arena, out, "%.*s[/%u]\n", indent_level, rdi_stringize_spaces, this_idx); } + +internal void +rdi_stringize_inline_site(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_InlineSite *inline_site, U32 indent_level) +{ + String8 name = {0}; + name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size); + str8_list_pushf(arena, out, "%.*sname='%S'\n", indent_level, rdi_stringize_spaces, name); + str8_list_pushf(arena, out, "%.*stype_idx=%u\n", indent_level, rdi_stringize_spaces, inline_site->type_idx); + str8_list_pushf(arena, out, "%.*sowner_type_idx=%u\n", indent_level, rdi_stringize_spaces, inline_site->owner_type_idx); + str8_list_pushf(arena, out, "%.*sline_table_idx=%u\n", indent_level, rdi_stringize_spaces, inline_site->line_table_idx); +} diff --git a/src/rdi_dump/rdi_dump.h b/src/rdi_dump/rdi_dump.h index 69eb49d3..7a469d9d 100644 --- a/src/rdi_dump/rdi_dump.h +++ b/src/rdi_dump/rdi_dump.h @@ -11,7 +11,7 @@ typedef struct RDI_FilePathBundle RDI_FilePathBundle; struct RDI_FilePathBundle { RDI_FilePathNode *file_paths; - U32 file_path_count; + U64 file_path_count; }; typedef struct RDI_UDTMemberBundle RDI_UDTMemberBundle; @@ -41,7 +41,7 @@ struct RDI_ScopeBundle //////////////////////////////// //~ rjf: RDI Enum -> String Functions -internal String8 rdi_string_from_data_section_tag(RDI_DataSectionTag v); +internal String8 rdi_string_from_data_section_kind(RDI_SectionKind v); internal String8 rdi_string_from_arch(RDI_Arch v); internal String8 rdi_string_from_language(RDI_Language v); internal String8 rdi_string_from_type_kind(RDI_TypeKind v); @@ -59,17 +59,20 @@ internal void rdi_stringize_link_flags(Arena *arena, String8List *out, RDI_LinkF //////////////////////////////// //~ rjf: RDI Compound Stringize Functions -internal void rdi_stringize_data_sections(Arena *arena, String8List *out, RDI_Parsed *parsed, U32 indent_level); -internal void rdi_stringize_top_level_info(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_TopLevelInfo *tli, U32 indent_level); -internal void rdi_stringize_binary_section(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_BinarySection *bin_section, U32 indent_level); -internal void rdi_stringize_file_path(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_FilePathBundle *bundle, RDI_FilePathNode *file_path, U32 indent_level); -internal void rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_SourceFile *source_file, U32 indent_level); -internal void rdi_stringize_unit(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_Unit *unit, U32 indent_level); -internal void rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_TypeNode *type, U32 indent_level); -internal void rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_UDTMemberBundle *bundle, RDI_UDT *udt, U32 indent_level); -internal void rdi_stringize_global_variable(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_GlobalVariable *global_variable, U32 indent_level); -internal void rdi_stringize_thread_variable(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_ThreadVariable *thread_var, U32 indent_level); -internal void rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_Procedure *proc, U32 indent_level); -internal void rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_ScopeBundle *bundle, RDI_Scope *scope, U32 indent_level); +internal void rdi_stringize_data_sections(Arena *arena, String8List *out, RDI_Parsed *rdi, U32 indent_level); +internal void rdi_stringize_top_level_info(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_TopLevelInfo *tli, U32 indent_level); +internal void rdi_stringize_binary_section(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_BinarySection *bin_section, U32 indent_level); +internal void rdi_stringize_file_path(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_FilePathBundle *bundle, RDI_FilePathNode *file_path, U32 indent_level); +internal void rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_SourceFile *source_file, U32 indent_level); +internal void rdi_stringize_line_table(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_LineTable *line_table, U32 indent_level); +internal void rdi_stringize_source_line_map(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_SourceLineMap *map, U32 indent_level); +internal void rdi_stringize_unit(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_Unit *unit, U32 indent_level); +internal void rdi_stringize_type_node(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_TypeNode *type, U32 indent_level); +internal void rdi_stringize_udt(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_UDTMemberBundle *bundle, RDI_UDT *udt, U32 indent_level); +internal void rdi_stringize_global_variable(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_GlobalVariable *global_variable, U32 indent_level); +internal void rdi_stringize_thread_variable(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_ThreadVariable *thread_var, U32 indent_level); +internal void rdi_stringize_procedure(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_Procedure *proc, U32 indent_level); +internal void rdi_stringize_scope(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_ScopeBundle *bundle, RDI_Scope *scope, U32 indent_level); +internal void rdi_stringize_inline_site(Arena *arena, String8List *out, RDI_Parsed *rdi, RDI_InlineSite *inline_site, U32 indent_level); #endif // RDI_DUMP_H diff --git a/src/rdi_dump/rdi_dump_main.c b/src/rdi_dump/rdi_dump_main.c index 20f77361..bb4ae241 100644 --- a/src/rdi_dump/rdi_dump_main.c +++ b/src/rdi_dump/rdi_dump_main.c @@ -53,18 +53,21 @@ 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_SourceLineMaps = (1<<6), + DumpFlag_Units = (1<<7), + DumpFlag_UnitVMap = (1<<8), + DumpFlag_TypeNodes = (1<<9), + DumpFlag_UDTs = (1<<10), + DumpFlag_GlobalVariables = (1<<11), + DumpFlag_GlobalVMap = (1<<12), + DumpFlag_ThreadVariables = (1<<13), + DumpFlag_Procedures = (1<<14), + DumpFlag_Scopes = (1<<15), + DumpFlag_ScopeVMap = (1<<16), + DumpFlag_InlineSites = (1<<17), + DumpFlag_NameMaps = (1<<18), + DumpFlag_Strings = (1<<19), }; String8 input_name = {0}; DumpFlags dump_flags = (U32)0xffffffff; @@ -72,9 +75,9 @@ entry_point(CmdLine *cmd_line) // rjf: extract input file path input_name = str8_list_first(&cmd_line->inputs); - // rjf: extract dump options + // rjf: extract "only" options { - String8List dump_options = cmd_line_strings(cmd_line, str8_lit("dump")); + String8List dump_options = cmd_line_strings(cmd_line, str8_lit("only")); if(dump_options.first != 0) { dump_flags = 0; @@ -86,6 +89,8 @@ 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("source_line_maps"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_SourceLineMaps; } else if(str8_match(n->string, str8_lit("units"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_Units; } else if(str8_match(n->string, str8_lit("unit_vmap"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_UnitVMap; } else if(str8_match(n->string, str8_lit("type_nodes"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_TypeNodes; } @@ -96,7 +101,9 @@ entry_point(CmdLine *cmd_line) else if(str8_match(n->string, str8_lit("procedures"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_Procedures; } else if(str8_match(n->string, str8_lit("scopes"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_Scopes; } else if(str8_match(n->string, str8_lit("scope_vmap"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_ScopeVMap; } + else if(str8_match(n->string, str8_lit("inline_sites"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_InlineSites; } else if(str8_match(n->string, str8_lit("name_maps"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_NameMaps; } + else if(str8_match(n->string, str8_lit("strings"), StringMatchFlag_CaseInsensitive)) { dump_flags |= DumpFlag_Strings; } } } } @@ -170,7 +177,8 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_TopLevelInfo) { str8_list_pushf(arena, &dump, "# TOP LEVEL INFO:\n"); - rdi_stringize_top_level_info(arena, &dump, rdi, rdi->top_level_info, 1); + RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0); + rdi_stringize_top_level_info(arena, &dump, rdi, tli, 1); str8_list_push(arena, &dump, str8_lit("\n")); } @@ -178,12 +186,12 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_BinarySections) { str8_list_pushf(arena, &dump, "# BINARY SECTIONS:\n"); - RDI_BinarySection *ptr = rdi->binary_sections; - for(U32 i = 0; i < rdi->binary_sections_count; i += 1, ptr += 1) + U64 count = 0; + RDI_BinarySection *v = rdi_table_from_name(rdi, BinarySections, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " section[%u]:\n", i); - rdi_stringize_binary_section(arena, &dump, rdi, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); + str8_list_pushf(arena, &dump, " section[%I64u]:\n", idx); + rdi_stringize_binary_section(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -192,13 +200,10 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_FilePaths) { RDI_FilePathBundle file_path_bundle = {0}; - { - file_path_bundle.file_paths = rdi->file_paths; - file_path_bundle.file_path_count = rdi->file_paths_count; - } + file_path_bundle.file_paths = rdi_table_from_name(rdi, FilePathNodes, &file_path_bundle.file_path_count); str8_list_pushf(arena, &dump, "# FILE PATHS\n"); - RDI_FilePathNode *ptr = rdi->file_paths; - for(U32 i = 0; i < rdi->file_paths_count; i += 1, ptr += 1) + RDI_FilePathNode *ptr = file_path_bundle.file_paths; + for(U32 i = 0; i < file_path_bundle.file_path_count; i += 1, ptr += 1) { if(ptr->parent_path_node == 0) { @@ -212,12 +217,40 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_SourceFiles) { str8_list_pushf(arena, &dump, "# SOURCE FILES\n"); - RDI_SourceFile *ptr = rdi->source_files; - for(U32 i = 0; i < rdi->source_files_count; i += 1, ptr += 1) + U64 count = 0; + RDI_SourceFile *v = rdi_table_from_name(rdi, SourceFiles, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " source_file[%u]:\n", i); - rdi_stringize_source_file(arena, &dump, rdi, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); + str8_list_pushf(arena, &dump, " source_file[%I64u]:\n", idx); + rdi_stringize_source_file(arena, &dump, rdi, &v[idx], 2); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: LINE TABLES + if(dump_flags & DumpFlag_LineTables) + { + str8_list_pushf(arena, &dump, "# LINE TABLES\n"); + U64 count = 0; + RDI_LineTable *v = rdi_table_from_name(rdi, LineTables, &count); + for(U64 idx = 0; idx < count; idx += 1) + { + str8_list_pushf(arena, &dump, " line_table[%I64u]:\n", idx); + rdi_stringize_line_table(arena, &dump, rdi, &v[idx], 2); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: SOURCE LINE MAPS + if(dump_flags & DumpFlag_SourceLineMaps) + { + str8_list_pushf(arena, &dump, "# SOURCE LINE MAPS\n"); + U64 count = 0; + RDI_SourceLineMap *v = rdi_table_from_name(rdi, SourceLineMaps, &count); + for(U64 idx = 0; idx < count; idx += 1) + { + str8_list_pushf(arena, &dump, " source_line_map[%I64u]:\n", idx); + rdi_stringize_source_line_map(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -226,12 +259,12 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_Units) { str8_list_pushf(arena, &dump, "# UNITS\n"); - RDI_Unit *ptr = rdi->units; - for (U32 i = 0; i < rdi->units_count; i += 1, ptr += 1) + U64 count = 0; + RDI_Unit *v = rdi_table_from_name(rdi, Units, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " unit[%u]:\n", i); - rdi_stringize_unit(arena, &dump, rdi, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); + str8_list_pushf(arena, &dump, " unit[%I64u]:\n", idx); + rdi_stringize_unit(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -240,10 +273,11 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_UnitVMap) { str8_list_pushf(arena, &dump, "# UNIT VMAP\n"); - RDI_VMapEntry *ptr = rdi->unit_vmap; - for(U32 i = 0; i < rdi->unit_vmap_count; i += 1, ptr += 1) + U64 count = 0; + RDI_VMapEntry *v = rdi_table_from_name(rdi, UnitVMap, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", ptr->voff, ptr->idx); + str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", v[idx].voff, v[idx].idx); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -252,12 +286,12 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_TypeNodes) { str8_list_pushf(arena, &dump, "# TYPE NODES:\n"); - RDI_TypeNode *ptr = rdi->type_nodes; - for(U32 i = 0; i < rdi->type_nodes_count; i += 1, ptr += 1) + U64 count = 0; + RDI_TypeNode *v = rdi_table_from_name(rdi, TypeNodes, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " type[%u]:\n", i); - rdi_stringize_type_node(arena, &dump, rdi, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); + str8_list_pushf(arena, &dump, " type[%I64u]:\n", idx); + rdi_stringize_type_node(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -265,20 +299,24 @@ entry_point(CmdLine *cmd_line) //- rjf: UDT DATA if(dump_flags & DumpFlag_UDTs) { + U64 all_members_count = 0; + RDI_Member *all_members = rdi_table_from_name(rdi, Members, &all_members_count); + U64 all_enum_members_count = 0; + RDI_EnumMember *all_enum_members = rdi_table_from_name(rdi, EnumMembers, &all_enum_members_count); + U64 all_udts_count = 0; + RDI_UDT *all_udts = rdi_table_from_name(rdi, UDTs, &all_udts_count); RDI_UDTMemberBundle member_bundle = {0}; { - member_bundle.members = rdi->members; - member_bundle.enum_members = rdi->enum_members; - member_bundle.member_count = rdi->members_count; - member_bundle.enum_member_count = rdi->enum_members_count; + member_bundle.members = all_members; + member_bundle.enum_members = all_enum_members; + member_bundle.member_count = (RDI_U32)all_members_count; + member_bundle.enum_member_count = (RDI_U32)all_enum_members_count; } str8_list_pushf(arena, &dump, "# UDTS:\n"); - RDI_UDT *ptr = rdi->udts; - for(U32 i = 0; i < rdi->udts_count; i += 1, ptr += 1) + for(U64 idx = 0; idx < all_udts_count; idx += 1) { - str8_list_pushf(arena, &dump, " udt[%u]:\n", i); - rdi_stringize_udt(arena, &dump, rdi, &member_bundle, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); + str8_list_pushf(arena, &dump, " udt[%I64u]:\n", idx); + rdi_stringize_udt(arena, &dump, rdi, &member_bundle, &all_udts[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -287,12 +325,12 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_GlobalVariables) { str8_list_pushf(arena, &dump, "# GLOBAL VARIABLES:\n"); - RDI_GlobalVariable *ptr = rdi->global_variables; - for(U32 i = 0; i < rdi->global_variables_count; i += 1, ptr += 1) + RDI_U64 count = 0; + RDI_GlobalVariable *v = rdi_table_from_name(rdi, GlobalVariables, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " global_variable[%u]:\n", i); - rdi_stringize_global_variable(arena, &dump, rdi, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); + str8_list_pushf(arena, &dump, " global_variable[%I64u]:\n", idx); + rdi_stringize_global_variable(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -301,10 +339,11 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_GlobalVMap) { str8_list_pushf(arena, &dump, "# GLOBAL VMAP:\n"); - RDI_VMapEntry *ptr = rdi->global_vmap; - for(U32 i = 0; i < rdi->global_vmap_count; i += 1, ptr += 1) + U64 count = 0; + RDI_VMapEntry *v = rdi_table_from_name(rdi, GlobalVMap, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", ptr->voff, ptr->idx); + str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", v[idx].voff, v[idx].idx); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -313,12 +352,12 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_ThreadVariables) { str8_list_pushf(arena, &dump, "# THREAD VARIABLES:\n"); - RDI_ThreadVariable *ptr = rdi->thread_variables; - for(U32 i = 0; i < rdi->thread_variables_count; i += 1, ptr += 1) + U64 count = 0; + RDI_ThreadVariable *v = rdi_table_from_name(rdi, ThreadVariables, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " thread_variable[%u]:\n", i); - rdi_stringize_thread_variable(arena, &dump, rdi, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); + str8_list_pushf(arena, &dump, " thread_variable[%I64u]:\n", idx); + rdi_stringize_thread_variable(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -327,12 +366,12 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_Procedures) { str8_list_pushf(arena, &dump, "# PROCEDURES:\n"); - RDI_Procedure *ptr = rdi->procedures; - for(U32 i = 0; i < rdi->procedures_count; i += 1, ptr += 1) + U64 count = 0; + RDI_Procedure *v = rdi_table_from_name(rdi, Procedures, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " procedure[%u]:\n", i); - rdi_stringize_procedure(arena, &dump, rdi, ptr, 2); - str8_list_push(arena, &dump, str8_lit("\n")); + str8_list_pushf(arena, &dump, " procedure[%I64u]:\n", idx); + rdi_stringize_procedure(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -340,27 +379,35 @@ entry_point(CmdLine *cmd_line) //- rjf: SCOPES if(dump_flags & DumpFlag_Scopes) { + U64 scopes_count = 0; + RDI_Scope *scopes = rdi_table_from_name(rdi, Scopes, &scopes_count); + U64 scopes_voffs_count = 0; + U64 *scopes_voffs = rdi_table_from_name(rdi, ScopeVOffData, &scopes_voffs_count); + U64 locals_count = 0; + RDI_Local *locals = rdi_table_from_name(rdi, Locals, &locals_count); + U64 location_block_count = 0; + RDI_LocationBlock *location_blocks = rdi_table_from_name(rdi, LocationBlocks, &location_block_count); + U64 location_data_size = 0; + RDI_U8 *location_data = rdi_table_from_name(rdi, LocationData, &location_data_size); RDI_ScopeBundle scope_bundle = {0}; { - scope_bundle.scopes = rdi->scopes; - scope_bundle.scope_count = rdi->scopes_count; - scope_bundle.scope_voffs = rdi->scope_voffs; - scope_bundle.scope_voff_count = rdi->scope_voffs_count; - scope_bundle.locals = rdi->locals; - scope_bundle.local_count = rdi->locals_count; - scope_bundle.location_blocks = rdi->location_blocks; - scope_bundle.location_block_count = rdi->location_blocks_count; - scope_bundle.location_data = rdi->location_data; - scope_bundle.location_data_size = rdi->location_data_size; + scope_bundle.scopes = scopes; + scope_bundle.scope_count = scopes_count; + scope_bundle.scope_voffs = scopes_voffs; + scope_bundle.scope_voff_count = scopes_voffs_count; + scope_bundle.locals = locals; + scope_bundle.local_count = locals_count; + scope_bundle.location_blocks = location_blocks; + scope_bundle.location_block_count = location_block_count; + scope_bundle.location_data = location_data; + scope_bundle.location_data_size = location_data_size; } str8_list_pushf(arena, &dump, "# SCOPES:\n"); - RDI_Scope *ptr = rdi->scopes; - for(U32 i = 0; i < rdi->scopes_count; i += 1, ptr += 1) + for(U64 idx = 0; idx < scopes_count; idx += 1) { - if(ptr->parent_scope_idx == 0) + if(scopes[idx].parent_scope_idx == 0) { - rdi_stringize_scope(arena, &dump, rdi, &scope_bundle, ptr, 1); - str8_list_push(arena, &dump, str8_lit("\n")); + rdi_stringize_scope(arena, &dump, rdi, &scope_bundle, &scopes[idx], 1); } } str8_list_push(arena, &dump, str8_lit("\n")); @@ -370,10 +417,25 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_ScopeVMap) { str8_list_pushf(arena, &dump, "# SCOPE VMAP:\n"); - RDI_VMapEntry *ptr = rdi->scope_vmap; - for(U32 i = 0; i < rdi->scope_vmap_count; i += 1, ptr += 1) + U64 count = 0; + RDI_VMapEntry *v = rdi_table_from_name(rdi, ScopeVMap, &count); + for(U64 idx = 0; idx < count; idx += 1) { - str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", ptr->voff, ptr->idx); + str8_list_pushf(arena, &dump, " 0x%08x: %llu\n", v[idx].voff, v[idx].idx); + } + str8_list_push(arena, &dump, str8_lit("\n")); + } + + //- rjf: INLINE SITES + if(dump_flags & DumpFlag_InlineSites) + { + str8_list_pushf(arena, &dump, "# INLINE SITES:\n"); + U64 count = 0; + RDI_InlineSite *v = rdi_table_from_name(rdi, InlineSites, &count); + for(U64 idx = 0; idx < count; idx += 1) + { + str8_list_pushf(arena, &dump, " inline_site[%I64u]:\n", idx); + rdi_stringize_inline_site(arena, &dump, rdi, &v[idx], 2); } str8_list_push(arena, &dump, str8_lit("\n")); } @@ -382,12 +444,13 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_NameMaps) { str8_list_pushf(arena, &dump, "# NAME MAP:\n"); - RDI_NameMap *ptr = rdi->name_maps; - for(U32 i = 0; i < rdi->name_maps_count; i += 1, ptr += 1) + U64 count = 0; + RDI_NameMap *v = rdi_table_from_name(rdi, NameMaps, &count); + for(U64 idx = 0; idx < count; idx += 1) { RDI_ParsedNameMap name_map = {0}; - rdi_name_map_parse(rdi, ptr, &name_map); - str8_list_pushf(arena, &dump, " name_map[%u]:\n", i); + rdi_parsed_from_name_map(rdi, &v[idx], &name_map); + str8_list_pushf(arena, &dump, " name_map[%I64u]:\n", idx); RDI_NameMapBucket *bucket = name_map.buckets; for(U32 j = 0; j < name_map.bucket_count; j += 1, bucket += 1) { @@ -434,11 +497,13 @@ entry_point(CmdLine *cmd_line) if(dump_flags & DumpFlag_Strings) { str8_list_pushf(arena, &dump, "# STRINGS:\n"); - for(U64 string_idx = 0; string_idx < rdi->string_count; string_idx += 1) + U64 count = 0; + U32 *v = rdi_table_from_name(rdi, StringTable, &count); + for(U64 idx = 0; idx < count; idx += 1) { String8 string = {0}; - string.str = rdi_string_from_idx(rdi, string_idx, &string.size); - str8_list_pushf(arena, &dump, " string[%I64u]: \"%S\"\n", string_idx, string); + string.str = rdi_string_from_idx(rdi, (RDI_U32)idx, &string.size); + str8_list_pushf(arena, &dump, " string[%I64u]: \"%S\"\n", idx, string); } str8_list_push(arena, &dump, str8_lit("\n")); } diff --git a/src/rdi_format/rdi_format.mdesk b/src/rdi_format/rdi_format.mdesk index 89f284be..bb3931cd 100644 --- a/src/rdi_format/rdi_format.mdesk +++ b/src/rdi_format/rdi_format.mdesk @@ -51,11 +51,18 @@ "#endif"; ""; "////////////////////////////////////////////////////////////////"; + "//~ Overridable Enabling/Disabling Of Table Index Typechecking"; + ""; + "#if !defined(RDI_DISABLE_TABLE_INDEX_TYPECHECKING)"; + "# define RDI_DISABLE_TABLE_INDEX_TYPECHECKING 0"; + "#endif"; + ""; + "////////////////////////////////////////////////////////////////"; "//~ Format Constants"; ""; "// \"raddbg\0\0\""; "#define RDI_MAGIC_CONSTANT 0x0000676264646172"; - "#define RDI_ENCODING_VERSION 1"; + "#define RDI_ENCODING_VERSION 6"; ""; "////////////////////////////////////////////////////////////////"; "//~ Format Types & Functions"; @@ -97,96 +104,134 @@ 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)` } //////////////////////////////// -//~ rjf: Format Data Section Tables +//~ rjf: Format Section Tables -@constant RDI_DataSectionTag_SECONDARY: 0x80000000 - -@table(name value desc) -RDI_DataSectionTable: +@table(name name_lower element_type value is_required index_base_type desc) +RDI_SectionTable: { - {NULL 0x0000 ""} - {TopLevelInfo 0x0001 ""} - {StringData 0x0002 ""} - {StringTable 0x0003 ""} - {IndexRuns 0x0004 ""} - {BinarySections 0x0005 ""} - {FilePathNodes 0x0006 ""} - {SourceFiles 0x0007 ""} - {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 ""} - {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` ""} + {NULL null RDI_U8 0x0000 - - ""} + {TopLevelInfo top_level_info RDI_TopLevelInfo 0x0001 - - ""} + {StringData string_data RDI_U8 0x0002 x - ""} + {StringTable string_table RDI_U32 0x0003 x U32 ""} + {IndexRuns index_runs RDI_U32 0x0004 x U32 ""} + {BinarySections binary_sections RDI_BinarySection 0x0005 - U32 ""} + {FilePathNodes file_path_nodes RDI_FilePathNode 0x0006 - U32 ""} + {SourceFiles source_files RDI_SourceFile 0x0007 - U32 ""} + {LineTables line_tables RDI_LineTable 0x0008 - U32 ""} + {LineInfoVOffs line_info_voffs RDI_U64 0x0009 - U32 ""} + {LineInfoLines line_info_lines RDI_Line 0x000A - U32 ""} + {LineInfoColumns line_info_columns RDI_Column 0x000B - U32 ""} + {SourceLineMaps source_line_maps RDI_SourceLineMap 0x000C - U32 ""} + {SourceLineMapNumbers source_line_map_numbers RDI_U32 0x000D - U32 ""} + {SourceLineMapRanges source_line_map_ranges RDI_U32 0x000E - U32 ""} + {SourceLineMapVOffs source_line_map_voffs RDI_U64 0x000F - U32 ""} + {Units units RDI_Unit 0x0010 - U32 ""} + {UnitVMap unit_vmap RDI_VMapEntry 0x0011 - - ""} + {TypeNodes type_nodes RDI_TypeNode 0x0012 - U32 ""} + {UDTs udts RDI_UDT 0x0013 - U32 ""} + {Members members RDI_Member 0x0014 - U32 ""} + {EnumMembers enum_members RDI_EnumMember 0x0015 - U32 ""} + {GlobalVariables global_variables RDI_GlobalVariable 0x0016 - U32 ""} + {GlobalVMap global_vmap RDI_VMapEntry 0x0017 - - ""} + {ThreadVariables thread_variables RDI_ThreadVariable 0x0018 - U32 ""} + {Procedures procedures RDI_Procedure 0x0019 - U32 ""} + {Scopes scopes RDI_Scope 0x001A - U32 ""} + {ScopeVOffData scope_voff_data RDI_U64 0x001B - U32 ""} + {ScopeVMap scope_vmap RDI_VMapEntry 0x001C - - ""} + {InlineSites inline_sites RDI_InlineSite 0x001D - U32 ""} + {Locals locals RDI_Local 0x001E - U32 ""} + {LocationBlocks location_blocks RDI_LocationBlock 0x001F - U32 ""} + {LocationData location_data RDI_U8 0x0020 - U32 ""} + {NameMaps name_maps RDI_NameMap 0x0021 - U32 ""} + {NameMapBuckets name_map_buckets RDI_NameMapBucket 0x0022 - U32 ""} + {NameMapNodes name_map_nodes RDI_NameMapNode 0x0023 - U32 ""} + {COUNT count RDI_U8 0x0024 - - ""} } @table(name value) -RDI_DataSectionEncodingTable: +RDI_SectionEncodingTable: { {Unpacked 0} {LZB 1} } @table(name type desc) -RDI_DataSectionMemberTable: +RDI_SectionMemberTable: { - {tag RDI_DataSectionTag ""} - {encoding RDI_DataSectionEncoding ""} + {encoding RDI_SectionEncoding ""} + {pad RDI_U32 ""} {off RDI_U64 ""} {encoded_size RDI_U64 ""} {unpacked_size RDI_U64 ""} } -@enum(RDI_U32) RDI_DataSectionTag: +@enum(RDI_U32) RDI_SectionKind: { - @expand(RDI_DataSectionTable a) `$(a.name .. =>20) = $(a.value)`, + @expand(RDI_SectionTable a) `$(a.name .. =>20) = $(a.value)`, } -@enum(RDI_U32) RDI_DataSectionEncoding: +@enum(RDI_U32) RDI_SectionEncoding: { - @expand(RDI_DataSectionEncodingTable a) `$(a.name .. =>10) = $(a.value)`, + @expand(RDI_SectionEncodingTable a) `$(a.name .. =>10) = $(a.value)`, } -@xlist RDI_DataSectionTag_XList: +@xlist RDI_SectionKind_XList: { - @expand(RDI_DataSectionTable a) `$(a.name)`; + @expand(RDI_SectionTable a) `$(a.name != COUNT -> a.name .. ', ' .. a.name_lower .. ', ' .. a.element_type)`; } -@xlist RDI_DataSectionEncoding_XList: +@xlist RDI_SectionEncoding_XList: { - @expand(RDI_DataSectionEncodingTable a) `$(a.name)`; + @expand(RDI_SectionEncodingTable a) `$(a.name)`; } -@struct RDI_DataSection: +@xlist RDI_Section_XList: { - @expand(RDI_DataSectionMemberTable a) `$(a.type) $(a.name)` + @expand(RDI_SectionMemberTable a) `$(a.type), $(a.name)` +} + +@struct RDI_Section: +{ + @expand(RDI_SectionMemberTable a) `$(a.type) $(a.name)` +} + +@gen(enums) +{ + `#if !RDI_DISABLE_TABLE_INDEX_TYPECHECKING`; + @expand(RDI_SectionTable a) `$(a.index_base_type != '-' -> "typedef struct RDI_" .. a.index_base_type .. "_" .. a.name .. =>50 .. " { RDI_" .. a.index_base_type .. " v; }".. " RDI_" .. a.index_base_type .. "_" .. a.name .. ";")`; + `#else`; + `typedef struct RDI_U32_Table { RDI_U32 v; } RDI_U32_Table;`; + `typedef struct RDI_U64_Table { RDI_U64 v; } RDI_U64_Table;`; + @expand(RDI_SectionTable a) `$(a.index_base_type != '-' -> "typedef RDI_" .. a.index_base_type .. "_Table RDI_" .. a.index_base_type .. "_" .. a.name .. ";")`; + `#endif`; + ``; +} + +@gen(catchall) +{ + @expand(RDI_SectionTable a) `$(a.name != COUNT && a.name != NULL -> "typedef " .. a.element_type .. =>40 .. " RDI_SectionElementType_" .. a.name .. ";")`; + ``; +} + +@data(RDI_U16) rdi_section_element_size_table: +{ + @expand(RDI_SectionTable a) `sizeof($(a.element_type))`; +} + +@data(RDI_U8) rdi_section_is_required_table: +{ + @expand(RDI_SectionTable a) `$(a.is_required == 'x' -> 1)$(a.is_required != 'x' -> 0)`; } //////////////////////////////// @@ -199,6 +244,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)` @@ -391,10 +441,16 @@ RDI_RegCodeX64Table: @table(name type desc) RDI_TopLevelInfoMemberTable: { - {arch RDI_Arch ""} - {exe_name_string_idx RDI_U32 ""} - {exe_hash RDI_U64 ""} - {voff_max RDI_U64 ""} + {arch RDI_Arch ""} + {exe_name_string_idx RDI_U32 ""} + {exe_hash RDI_U64 ""} + {voff_max RDI_U64 ""} + {producer_name_string_idx RDI_U32 ""} +} + +@xlist RDI_TopLevelInfo_XList: +{ + @expand(RDI_TopLevelInfoMemberTable a) `$(a.type), $(a.name)` } @struct RDI_TopLevelInfo: @@ -431,7 +487,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: @@ -445,26 +506,33 @@ RDI_BinarySectionMemberTable: @table(name type desc) RDI_FilePathNodeMemberTable: { - {name_string_idx RDI_U32 ""} - {parent_path_node RDI_U32 ""} - {first_child RDI_U32 ""} - {next_sibling RDI_U32 ""} - {source_file_idx RDI_U32 ""} + {name_string_idx RDI_U32 ""} + {parent_path_node RDI_U32 ""} + {first_child RDI_U32 ""} + {next_sibling RDI_U32 ""} + {source_file_idx RDI_U32 ""} } @table(name type desc) RDI_SourceFileMemberTable: { - {file_path_node_idx RDI_U32 ""} - {normal_full_path_string_idx RDI_U32 ""} + {file_path_node_idx RDI_U32 ""} + {normal_full_path_string_idx RDI_U32 ""} // usage of line map to go from a line number to an array of voffs // (line_map_nums * line_number) -> (nil | index) // (line_map_data * index) -> (range) // (line_map_voff_data * range) -> (array(voff)) - {line_map_count RDI_U32 ""} - {line_map_nums_data_idx RDI_U32 ""} // U32[line_map_count] (sorted - not closed ranges) - {line_map_range_data_idx RDI_U32 ""} // U32[line_map_count + 1] (pairs form ranges) - {line_map_voff_data_idx RDI_U32 ""} // U64[...] (idx by line_map_range_data) + {source_line_map_idx RDI_U32 ""} +} + +@xlist RDI_FilePathNode_XList: +{ + @expand(RDI_FilePathNodeMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_SourceFile_XList: +{ + @expand(RDI_SourceFileMemberTable a) `$(a.type), $(a.name)` } @struct RDI_FilePathNode: @@ -483,20 +551,19 @@ RDI_SourceFileMemberTable: @table(name type desc) RDI_UnitMemberTable: { - {unit_name_string_idx RDI_U32 ""} - {compiler_name_string_idx RDI_U32 ""} - {source_file_path_node RDI_U32 ""} - {object_file_path_node RDI_U32 ""} - {archive_file_path_node RDI_U32 ""} - {build_path_node RDI_U32 ""} - {language RDI_Language ""} - // 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 ""} + {unit_name_string_idx RDI_U32 ""} + {compiler_name_string_idx RDI_U32 ""} + {source_file_path_node RDI_U32 ""} + {object_file_path_node RDI_U32 ""} + {archive_file_path_node RDI_U32 ""} + {build_path_node RDI_U32 ""} + {language RDI_Language ""} + {line_table_idx RDI_U32 ""} +} + +@xlist RDI_Unit_XList: +{ + @expand(RDI_UnitMemberTable a) `$(a.type), $(a.name)` } @struct RDI_Unit: @@ -507,11 +574,24 @@ RDI_UnitMemberTable: //////////////////////////////// //~ rjf: Line Info Type Tables +@table(name type desc) +RDI_LineTableMemberTable: +{ + // usage of line info to go from voff to file & line number: + // (line_info_voffs * voff) -> (nil + index) + // (line_info_data * index) -> (RDI_Line = (file_idx * line_number)) + {voffs_base_idx RDI_U32 ""} // U64[lines_count+1] (sorted ranges) + {lines_base_idx RDI_U32 ""} // RDI_Line[lines_count] + {cols_base_idx RDI_U32 ""} // RDI_Column[cols_count] + {lines_count RDI_U32 ""} + {cols_count RDI_U32 ""} +} + @table(name type desc) RDI_LineMemberTable: { - {file_idx RDI_U32 ""} - {line_num RDI_U32 ""} + {file_idx RDI_U32 ""} + {line_num RDI_U32 ""} } @table(name type desc) @@ -521,6 +601,45 @@ RDI_ColumnMemberTable: {col_opl RDI_U16 ""} } +@table(name type desc) +RDI_SourceLineMapMemberTable: +{ + // usage of line map to go from a line number to an array of voffs + // (line_map_nums * line_number) -> (nil | index) + // (line_map_data * index) -> (range) + // (line_map_voff_data * range) -> (array(voff)) + {line_count RDI_U32 ""} + {voff_count RDI_U32 ""} + {line_map_nums_base_idx RDI_U32 ""} // U32[line_count] (sorted - not closed ranges) + {line_map_range_base_idx RDI_U32 ""} // U32[line_count + 1] (pairs form ranges) + {line_map_voff_base_idx RDI_U32 ""} // U64[voff_count] (idx by line_map_range_data) +} + +@xlist RDI_LineTable_XList: +{ + @expand(RDI_LineTableMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_Line_XList: +{ + @expand(RDI_LineMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_Column_XList: +{ + @expand(RDI_ColumnMemberTable a) `$(a.type), $(a.name)` +} + +@xlist RDI_SourceLineMapMemberTable: +{ + @expand(RDI_SourceLineMapMemberTable a) `$(a.type), $(a.name)` +} + +@struct RDI_LineTable: +{ + @expand(RDI_LineTableMemberTable a) `$(a.type) $(a.name)` +} + @struct RDI_Line: { @expand(RDI_LineMemberTable a) `$(a.type) $(a.name)` @@ -531,6 +650,11 @@ RDI_ColumnMemberTable: @expand(RDI_ColumnMemberTable a) `$(a.type) $(a.name)` } +@struct RDI_SourceLineMap: +{ + @expand(RDI_SourceLineMapMemberTable a) `$(a.type) $(a.name)` +} + //////////////////////////////// //~ rjf: Language Info Tables @@ -643,13 +767,13 @@ RDI_UDTFlagTable: @table(name type desc) RDI_UDTMemberTable: { - {self_type_idx RDI_U32 ""} - {flags RDI_UDTFlags ""} - {member_first RDI_U32 ""} - {member_count RDI_U32 ""} - {file_idx RDI_U32 ""} - {line RDI_U32 ""} - {col RDI_U32 ""} + {self_type_idx RDI_U32 ""} + {flags RDI_UDTFlags ""} + {member_first RDI_U32 ""} + {member_count RDI_U32 ""} + {file_idx RDI_U32 ""} + {line RDI_U32 ""} + {col RDI_U32 ""} } @table(name value) @@ -670,19 +794,19 @@ RDI_MemberKindTable: @table(name type desc) RDI_MemberMemberTable: { - {kind RDI_MemberKind ""} - {pad RDI_U16 ""} - {name_string_idx RDI_U32 ""} - {type_idx RDI_U32 ""} - {off RDI_U32 ""} + {kind RDI_MemberKind ""} + {pad RDI_U16 ""} + {name_string_idx RDI_U32 ""} + {type_idx RDI_U32 ""} + {off RDI_U32 ""} } @table(name type desc) RDI_EnumMemberTable: { - {name_string_idx RDI_U32 ""} - {pad RDI_U32 ""} - {val RDI_U64 ""} + {name_string_idx RDI_U32 ""} + {pad RDI_U32 ""} + {val RDI_U64 ""} } @enum(RDI_U16) RDI_TypeKind: @@ -707,6 +831,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)` @@ -724,13 +853,15 @@ RDI_EnumMemberTable: { RDI_U32 direct_type_idx; RDI_U32 count; - union{ + union + { // when kind is 'Function' or 'Method' RDI_U32 param_idx_run_first; // when kind is 'MemberPtr' RDI_U32 owner_type_idx; }; - } constructed; + } + constructed; // kind is 'user defined' struct @@ -738,7 +869,8 @@ RDI_EnumMemberTable: RDI_U32 name_string_idx; RDI_U32 direct_type_idx; RDI_U32 udt_idx; - } user_defined; + } + user_defined; // (kind = Bitfield) struct @@ -746,7 +878,8 @@ RDI_EnumMemberTable: RDI_U32 direct_type_idx; RDI_U32 off; RDI_U32 size; - } bitfield; + } + bitfield; } ``` } @@ -756,11 +889,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)` @@ -776,6 +914,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)` @@ -789,6 +937,8 @@ RDI_EnumMemberTable: //////////////////////////////// //~ rjf: Symbol Info Tables +//- rjf: tables + @table(name value) RDI_LinkFlagTable: { @@ -808,9 +958,9 @@ RDI_LocalKindTable: @table(name value) RDI_LocationKindTable: { - {NULL 0x0} - {AddrBytecodeStream 0x1} - {ValBytecodeStream 0x2} + {NULL 0x0} + {AddrBytecodeStream 0x1} + {ValBytecodeStream 0x2} {AddrRegPlusU16 0x3} {AddrAddrRegPlusU16 0x4} {ValReg 0x5} @@ -819,66 +969,76 @@ RDI_LocationKindTable: @table(name type desc) RDI_GlobalVariableMemberTable: { - {name_string_idx RDI_U32 ""} - {link_flags RDI_LinkFlags ""} - {voff RDI_U64 ""} - {type_idx RDI_U32 ""} - {container_idx RDI_U32 ""} + {name_string_idx RDI_U32 ""} + {link_flags RDI_LinkFlags ""} + {voff RDI_U64 ""} + {type_idx RDI_U32 ""} + {container_idx RDI_U32 ""} } @table(name type desc) RDI_ThreadVariableMemberTable: { - {name_string_idx RDI_U32 ""} - {link_flags RDI_LinkFlags ""} - {tls_off RDI_U32 ""} - {type_idx RDI_U32 ""} - {container_idx RDI_U32 ""} + {name_string_idx RDI_U32 ""} + {link_flags RDI_LinkFlags ""} + {tls_off RDI_U32 ""} + {type_idx RDI_U32 ""} + {container_idx RDI_U32 ""} } @table(name type desc) RDI_ProcedureMemberTable: { - {name_string_idx RDI_U32 ""} - {link_name_string_idx RDI_U32 ""} - {link_flags RDI_LinkFlags ""} - {type_idx RDI_U32 ""} - {root_scope_idx RDI_U32 ""} - {container_idx RDI_U32 ""} + {name_string_idx RDI_U32 ""} + {link_name_string_idx RDI_U32 ""} + {link_flags RDI_LinkFlags ""} + {type_idx RDI_U32 ""} + {root_scope_idx RDI_U32 ""} + {container_idx RDI_U32 ""} } @table(name type desc) RDI_ScopeMemberTable: { - {proc_idx RDI_U32 ""} - {parent_scope_idx RDI_U32 ""} - {first_child_scope_idx RDI_U32 ""} - {next_sibling_scope_idx RDI_U32 ""} - {voff_range_first RDI_U32 ""} - {voff_range_opl RDI_U32 ""} - {local_first RDI_U32 ""} - {local_count RDI_U32 ""} - {static_local_idx_run_first RDI_U32 ""} - {static_local_count RDI_U32 ""} + {proc_idx RDI_U32 ""} + {parent_scope_idx RDI_U32 ""} + {first_child_scope_idx RDI_U32 ""} + {next_sibling_scope_idx RDI_U32 ""} + {voff_range_first RDI_U32 ""} + {voff_range_opl RDI_U32 ""} + {local_first RDI_U32 ""} + {local_count RDI_U32 ""} + {static_local_idx_run_first RDI_U32 ""} + {static_local_count RDI_U32 ""} + {inline_site_idx RDI_U32 ""} +} + +@table(name type desc) +RDI_InlineSiteMemberTable: +{ + {name_string_idx RDI_U32 ""} + {type_idx RDI_U32 ""} + {owner_type_idx RDI_U32 ""} + {line_table_idx RDI_U32 ""} } @table(name type desc) RDI_LocalMemberTable: { - {kind RDI_LocalKind ""} - {name_string_idx RDI_U32 ""} - {type_idx RDI_U32 ""} - {pad RDI_U32 ""} - {location_first RDI_U32 ""} - {location_opl RDI_U32 ""} + {kind RDI_LocalKind ""} + {name_string_idx RDI_U32 ""} + {type_idx RDI_U32 ""} + {pad RDI_U32 ""} + {location_first RDI_U32 ""} + {location_opl RDI_U32 ""} } @table(name type desc) RDI_LocationBlockMemberTable: { - {scope_off_first RDI_U32} - {scope_off_opl RDI_U32} - {location_data_off RDI_U32} + {scope_off_first RDI_U32 } + {scope_off_opl RDI_U32 } + {location_data_off RDI_U32 } } @table(name type desc) @@ -903,6 +1063,8 @@ RDI_LocationRegMemberTable: {reg_code RDI_RegCode } } +//- rjf: enums + @enum(RDI_U32) RDI_LinkFlags: { @expand(RDI_LinkFlagTable a) `$(a.name .. =>20) = $(a.value)` @@ -918,6 +1080,8 @@ RDI_LocationRegMemberTable: @expand(RDI_LocationKindTable a) `$(a.name .. =>20) = $(a.value)` } +//- rjf: xlists + @xlist RDI_LinkFlags_XList: { @expand(RDI_LinkFlagTable a) `$(a.name)`; @@ -933,6 +1097,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)` @@ -953,6 +1169,11 @@ RDI_LocationRegMemberTable: @expand(RDI_ScopeMemberTable a) `$(a.type) $(a.name)` } +@struct RDI_InlineSite: +{ + @expand(RDI_InlineSiteMemberTable a) `$(a.type) $(a.name)` +} + @struct RDI_Local: { @expand(RDI_LocalMemberTable a) `$(a.type) $(a.name)` @@ -1130,9 +1351,10 @@ RDI_NameMapKindTable: @table(name type desc) RDI_NameMapMemberTable: { - {kind RDI_NameMapKind ""} - {bucket_data_idx RDI_U32 ""} - {node_data_idx RDI_U32 ""} + {bucket_base_idx RDI_U32 ""} + {node_base_idx RDI_U32 ""} + {bucket_count RDI_U32 ""} + {node_count RDI_U32 ""} } @table(name type desc) @@ -1145,11 +1367,11 @@ RDI_NameMapBucketMemberTable: @table(name type desc) RDI_NameMapNodeMemberTable: { - {string_idx RDI_U32 ""} - {match_count RDI_U32 ""} + {string_idx RDI_U32 ""} + {match_count RDI_U32 ""} // NOTE: if (match_count == 1) then this is the index of the matching item // if (match_count > 1) then this is the first for an index run of all the matches - {match_idx_or_idx_run_first RDI_U32 ""} + {match_idx_or_idx_run_first RDI_U32 ""} } @enum(RDI_U32) RDI_NameMapKind: @@ -1162,6 +1384,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_format/rdi_format_local.c b/src/rdi_format/rdi_format_local.c index 6fae2eb3..661fb0b1 100644 --- a/src/rdi_format/rdi_format_local.c +++ b/src/rdi_format/rdi_format_local.c @@ -15,16 +15,16 @@ rdi_decompress_parsed(U8 *decompressed_data, U64 decompressed_size, RDI_Parsed * } // rjf: copy & adjust sections for decompressed version - if(og_rdi->dsec_count != 0) + if(og_rdi->sections_count != 0) { - RDI_DataSection *dsec_base = (RDI_DataSection *)(decompressed_data + dst_header->data_section_off); - MemoryCopy(dsec_base, (U8 *)og_rdi->raw_data + src_header->data_section_off, sizeof(RDI_DataSection) * og_rdi->dsec_count); - U64 off = dst_header->data_section_off + sizeof(RDI_DataSection) * og_rdi->dsec_count; + RDI_Section *dsec_base = (RDI_Section *)(decompressed_data + dst_header->data_section_off); + MemoryCopy(dsec_base, (U8 *)og_rdi->raw_data + src_header->data_section_off, sizeof(RDI_Section) * og_rdi->sections_count); + U64 off = dst_header->data_section_off + sizeof(RDI_Section) * og_rdi->sections_count; off += 7; off -= off%8; - for(U64 idx = 0; idx < og_rdi->dsec_count; idx += 1) + for(U64 idx = 0; idx < og_rdi->sections_count; idx += 1) { - dsec_base[idx].encoding = RDI_DataSectionEncoding_Unpacked; + dsec_base[idx].encoding = RDI_SectionEncoding_Unpacked; dsec_base[idx].off = off; dsec_base[idx].encoded_size = dsec_base[idx].unpacked_size; off += dsec_base[idx].unpacked_size; @@ -34,13 +34,13 @@ rdi_decompress_parsed(U8 *decompressed_data, U64 decompressed_size, RDI_Parsed * } // rjf: decompress sections into new decompressed file buffer - if(og_rdi->dsec_count != 0) + if(og_rdi->sections_count != 0) { - RDI_DataSection *src_first = og_rdi->dsecs; - RDI_DataSection *dst_first = (RDI_DataSection *)(decompressed_data + dst_header->data_section_off); - RDI_DataSection *src_opl = src_first + og_rdi->dsec_count; - RDI_DataSection *dst_opl = dst_first + og_rdi->dsec_count; - for(RDI_DataSection *src = src_first, *dst = dst_first; + RDI_Section *src_first = og_rdi->sections; + RDI_Section *dst_first = (RDI_Section *)(decompressed_data + dst_header->data_section_off); + RDI_Section *src_opl = src_first + og_rdi->sections_count; + RDI_Section *dst_opl = dst_first + og_rdi->sections_count; + for(RDI_Section *src = src_first, *dst = dst_first; src < src_opl && dst < dst_opl; src += 1, dst += 1) { diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index 9c5632b4..e0eaa4ca 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -544,7 +544,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_c13_stream_parse_task__entry_point) { P2R_C13StreamParseIn *in = (P2R_C13StreamParseIn *)p; void *out = 0; - ProfScope("parse c13 stream") out = cv_c13_from_data(arena, in->data, in->strtbl, in->coff_sections); + ProfScope("parse c13 stream") out = cv_c13_parsed_from_data(arena, in->data, in->strtbl, in->coff_sections); return out; } @@ -580,8 +580,11 @@ 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 - for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) + //////////////////////////// + //- rjf: pass 1: build per-unit info & per-unit line tables + // + ProfScope("pass 1: build per-unit info & per-unit line tables") + for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) { PDB_CompUnit *pdb_unit = in->comp_units->units[comp_unit_idx]; CV_SymParsed *pdb_unit_sym = in->comp_unit_syms[comp_unit_idx]; @@ -606,20 +609,13 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) MemoryZeroStruct(&obj_name); } - //- rjf: build unit - RDIM_Unit *dst_unit = rdim_unit_chunk_list_push(arena, &out->units, units_chunk_cap); - dst_unit->unit_name = unit_name; - dst_unit->compiler_name = pdb_unit_sym->info.compiler_name; - dst_unit->object_file = obj_name; - dst_unit->archive_file = pdb_unit->group_name; - dst_unit->language = p2r_rdi_language_from_cv_language(pdb_unit_sym->info.language); - - //- rjf: fill unit line info + //- rjf: build this unit's line table, fill out primary line info (inline info added after) + RDIM_LineTable *line_table = 0; for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; node != 0; node = node->next) { - if(node->kind == CV_C13_SubSectionKind_Lines) + if(node->kind == CV_C13SubSectionKind_Lines) { for(CV_C13LinesParsedNode *lines_n = node->lines_first; lines_n != 0; @@ -658,23 +654,37 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) 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; + // rjf: push sequence into both line table & source file's line map + if(lines->line_count != 0) + { + if(line_table == 0) + { + line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 256); + } + RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, lines->voffs, lines->line_nums, lines->col_nums, lines->line_count); + rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); + } } } } + + //- rjf: build unit + RDIM_Unit *dst_unit = rdim_unit_chunk_list_push(arena, &out->units, units_chunk_cap); + dst_unit->unit_name = unit_name; + dst_unit->compiler_name = pdb_unit_sym->info.compiler_name; + dst_unit->object_file = obj_name; + dst_unit->archive_file = pdb_unit->group_name; + dst_unit->language = p2r_rdi_language_from_cv_language(pdb_unit_sym->info.language); + dst_unit->line_table = line_table; } + //////////////////////////// //- rjf: pass 2: build per-unit voff ranges from comp unit contributions table + // PDB_CompUnitContribution *contrib_ptr = in->comp_unit_contributions->contributions; PDB_CompUnitContribution *contrib_opl = contrib_ptr + in->comp_unit_contributions->count; - for(;contrib_ptr < contrib_opl; contrib_ptr += 1) + ProfScope("pass 2: build per-unit voff ranges from comp unit contributions table") + for(;contrib_ptr < contrib_opl; contrib_ptr += 1) { if(contrib_ptr->mod < in->comp_units->count) { @@ -683,6 +693,339 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) rdim_rng1u64_list_push(arena, &unit->voff_ranges, range); } } + + //////////////////////////// + //- rjf: pass 3: parse all inlinee line tables + // + out->units_first_inline_site_line_tables = push_array(arena, RDIM_LineTable *, in->comp_units->count); + ProfScope("pass 3: parse all inlinee line tables") + for(U64 comp_unit_idx = 0; comp_unit_idx < in->comp_units->count; comp_unit_idx += 1) + { + CV_SymParsed *unit_sym = in->comp_unit_syms[comp_unit_idx]; + CV_C13Parsed *unit_c13 = in->comp_unit_c13s[comp_unit_idx]; + CV_RecRange *rec_ranges_first = unit_sym->sym_ranges.ranges; + CV_RecRange *rec_ranges_opl = rec_ranges_first+unit_sym->sym_ranges.count; + U64 base_voff = 0; + for(CV_RecRange *rec_range = rec_ranges_first; + rec_range < rec_ranges_opl; + rec_range += 1) + { + //- rjf: rec range -> symbol info range + U64 sym_off_first = rec_range->off + 2; + U64 sym_off_opl = rec_range->off + rec_range->hdr.size; + + //- rjf: skip invalid ranges + if(sym_off_opl > unit_sym->data.size || sym_off_first > unit_sym->data.size || sym_off_first > sym_off_opl) + { + continue; + } + + //- rjf: unpack symbol info + CV_SymKind kind = rec_range->hdr.kind; + U64 sym_header_struct_size = cv_header_struct_size_from_sym_kind(kind); + void *sym_header_struct_base = unit_sym->data.str + sym_off_first; + void *sym_data_opl = unit_sym->data.str + sym_off_opl; + + //- rjf: skip bad sizes + if(sym_off_first + sym_header_struct_size > sym_off_opl) + { + continue; + } + + //- rjf: process symbol + switch(kind) + { + default:{}break; + + //- rjf: LPROC32/GPROC32 (gather base address) + case CV_SymKind_LPROC32: + case CV_SymKind_GPROC32: + { + CV_SymProc32 *proc32 = (CV_SymProc32 *)sym_header_struct_base; + COFF_SectionHeader *section = (0 < proc32->sec && proc32->sec <= in->coff_sections->count) ? &in->coff_sections->sections[proc32->sec-1] : 0; + if(section != 0) + { + base_voff = section->voff + proc32->off; + } + }break; + + //- rjf: INLINESITE + case CV_SymKind_INLINESITE: + { + // rjf: unpack sym + CV_SymInlineSite *sym = (CV_SymInlineSite *)sym_header_struct_base; + String8 binary_annots = str8((U8 *)(sym+1), rec_range->hdr.size - sizeof(rec_range->hdr.kind) - sizeof(*sym)); + + // rjf: map inlinee -> parsed cv c13 inlinee line info + CV_C13InlineeLinesParsed *inlinee_lines_parsed = 0; + { + U64 hash = cv_hash_from_item_id(sym->inlinee); + U64 slot_idx = hash%unit_c13->inlinee_lines_parsed_slots_count; + for(CV_C13InlineeLinesParsedNode *n = unit_c13->inlinee_lines_parsed_slots[slot_idx]; n != 0; n = n->hash_next) + { + if(n->v.inlinee == sym->inlinee) + { + inlinee_lines_parsed = &n->v; + break; + } + } + } + + // rjf: build line table, fill with parsed binary annotations + RDIM_LineTable *line_table = 0; + if(inlinee_lines_parsed != 0) + { + // rjf: state machine registers + CV_InlineRangeKind range_kind = 0; + U32 code_length = 0; + U32 code_offset = 0; + U32 last_code_offset = code_offset; + String8 file_name = inlinee_lines_parsed->file_name; + String8 last_file_name = file_name; + S32 line = (S32)inlinee_lines_parsed->first_source_ln; + S32 last_line = line; + S32 column = 1; + S32 last_column = column; + + // rjf: gathered lines + typedef struct LineChunk LineChunk; + struct LineChunk + { + LineChunk *next; + U64 cap; + U64 count; + U64 *voffs; // [line_count + 1] (sorted) + U32 *line_nums; // [line_count] + U16 *col_nums; // [2*line_count] + }; + LineChunk *first_line_chunk = 0; + LineChunk *last_line_chunk = 0; + U64 total_line_chunk_line_count = 0; + + // rjf: grab checksums sub-section + CV_C13SubSectionNode *file_chksms = unit_c13->file_chksms_sub_section; + + // rjf: decode loop + U64 read_off = 0; + U64 read_off_opl = binary_annots.size; + for(B32 good = 1; read_off < read_off_opl && good;) + { + // rjf: decode next annotation op + U32 op = CV_InlineBinaryAnnotation_Null; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &op); + + // rjf: apply op + switch(op) + { + default:{good = 0;}break; + case CV_InlineBinaryAnnotation_Null: + { + good = 0; + }break; + case CV_InlineBinaryAnnotation_CodeOffset: + { + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_offset); + }break; + case CV_InlineBinaryAnnotation_ChangeCodeOffsetBase: + { + good = 0; + // TODO(rjf): currently untested/unknown - first guess below: + // + // U32 delta = 0; + // read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &delta); + // code_offset_base = code_offset; + // code_offset_end = code_offset + delta; + // code_offset += delta; + }break; + case CV_InlineBinaryAnnotation_ChangeCodeOffset: + { + U32 delta = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &delta); + code_offset += delta; + }break; + case CV_InlineBinaryAnnotation_ChangeCodeLength: + { + code_length = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_length); + }break; + case CV_InlineBinaryAnnotation_ChangeFile: + { + U32 new_file_off = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &new_file_off); + String8 new_file_name = {0}; + if(new_file_off + sizeof(CV_C13Checksum) <= file_chksms->size) + { + CV_C13Checksum *checksum = (CV_C13Checksum*)(unit_c13->data.str + file_chksms->off + new_file_off); + U32 name_off = checksum->name_off; + new_file_name = pdb_strtbl_string_from_off(in->pdb_strtbl, name_off); + } + file_name = new_file_name; + }break; + case CV_InlineBinaryAnnotation_ChangeLineOffset: + { + S32 delta = 0; + read_off += cv_decode_inline_annot_s32(binary_annots, read_off, &delta); + line += delta; + }break; + case CV_InlineBinaryAnnotation_ChangeLineEndDelta: + { + good = 0; + // TODO(rjf): currently untested/unknown - first guess below: + // + // S32 end_delta = 1; + // read_off += cv_decode_inline_annot_s32(binary_annots, read_off, &end_delta); + // line += end_delta; + }break; + case CV_InlineBinaryAnnotation_ChangeRangeKind: + { + good = 0; + // TODO(rjf): currently untested/unknown - first guess below: + // + // read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &range_kind); + }break; + case CV_InlineBinaryAnnotation_ChangeColumnStart: + { + good = 0; + // TODO(rjf): currently untested/unknown - first guess below: + // + // S32 delta = 0; + // read_off += cv_decode_inline_annot_s32(binary_annots, read_off, &delta); + // column += delta; + }break; + case CV_InlineBinaryAnnotation_ChangeColumnEndDelta: + { + // TODO(rjf): currently untested/unknown - first guess below: + // + // S32 end_delta = 0; + // read_off += cv_decode_inline_annot_s32(binary_annots, read_off, &end_delta); + // column += end_delta; + }break; + case CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset: + { + U32 code_offset_and_line_offset = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_offset_and_line_offset); + U32 code_delta = (code_offset_and_line_offset & 0xf); + S32 line_delta = cv_inline_annot_signed_from_unsigned_operand(code_offset_and_line_offset >> 4); + code_offset += code_delta; + line += line_delta; + }break; + case CV_InlineBinaryAnnotation_ChangeCodeLengthAndCodeOffset: + { + U32 offset_delta = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_length); + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &offset_delta); + code_offset += offset_delta; + }break; + case CV_InlineBinaryAnnotation_ChangeColumnEnd: + { + // TODO(rjf): currently untested/unknown - first guess below: + // + // U32 column_end = 0; + // read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &column_end); + }break; + } + + // rjf: gather new lines + if(!good || line != last_line || code_offset != last_code_offset) + { + LineChunk *chunk = last_line_chunk; + if(chunk == 0 || chunk->count+1 >= chunk->cap) + { + chunk = push_array(scratch.arena, LineChunk, 1); + SLLQueuePush(first_line_chunk, last_line_chunk, chunk); + chunk->cap = 256; + chunk->voffs = push_array_no_zero(scratch.arena, U64, chunk->cap); + chunk->line_nums = push_array_no_zero(scratch.arena, U32, chunk->cap); + } + chunk->voffs[chunk->count] = base_voff + code_offset; + chunk->voffs[chunk->count+1] = base_voff + code_offset + code_length; + chunk->line_nums[chunk->count] = (U32)line; + chunk->count += 1; + total_line_chunk_line_count += 1; + } + + // rjf: push line sequence to line table & source file + if(!good || (op == CV_InlineBinaryAnnotation_ChangeFile && !str8_match(last_file_name, file_name, 0))) + { + String8 seq_file_name = last_file_name; // NOTE(rjf): `file_name` is possibly changed to the next sequence, so use previous + + // rjf: file name -> normalized file path + String8 file_path = seq_file_name; + String8 file_path_normalized = lower_from_str8(scratch.arena, str8_skip_chop_whitespace(file_path)); + for(U64 idx = 0; idx < file_path_normalized.size; idx += 1) + { + if(file_path_normalized.str[idx] == '\\') + { + file_path_normalized.str[idx] = '/'; + } + } + + // rjf: normalized file path -> source file node + U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); + U64 src_file_slot = file_path_normalized_hash%src_file_map.slots_count; + P2R_SrcFileNode *src_file_node = 0; + for(P2R_SrcFileNode *n = src_file_map.slots[src_file_slot]; n != 0; n = n->next) + { + if(str8_match(n->src_file->normal_full_path, file_path_normalized, 0)) + { + src_file_node = n; + break; + } + } + if(src_file_node == 0) + { + src_file_node = push_array(scratch.arena, P2R_SrcFileNode, 1); + SLLStackPush(src_file_map.slots[src_file_slot], src_file_node); + src_file_node->src_file = rdim_src_file_chunk_list_push(arena, &out->src_files, 4096); + src_file_node->src_file->normal_full_path = push_str8_copy(arena, file_path_normalized); + } + + // rjf: gather all lines + RDI_U64 *voffs = push_array_no_zero(arena, RDI_U64, total_line_chunk_line_count+1); + RDI_U32 *line_nums = push_array_no_zero(arena, RDI_U32, total_line_chunk_line_count); + RDI_U64 line_count = total_line_chunk_line_count; + { + U64 dst_idx = 0; + for(LineChunk *chunk = first_line_chunk; chunk != 0; chunk = chunk->next) + { + MemoryCopy(voffs+dst_idx, chunk->voffs, sizeof(U64)*chunk->count); + MemoryCopy(line_nums+dst_idx, chunk->line_nums, sizeof(U32)*chunk->count); + dst_idx += chunk->count; + } + voffs[dst_idx] = 0xffffffffffffffffull; + } + + // rjf: push + if(line_count != 0) + { + if(line_table == 0) + { + line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 256); + if(out->units_first_inline_site_line_tables[comp_unit_idx] == 0) + { + out->units_first_inline_site_line_tables[comp_unit_idx] = line_table; + } + } + RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, voffs, line_nums, 0, line_count); + rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); + } + + // rjf: clear line chunks for subsequent sequences + first_line_chunk = last_line_chunk = 0; + total_line_chunk_line_count = 0; + } + + // rjf: update prev/current states + last_file_name = file_name; + last_line = line; + last_column = column; + last_code_offset = code_offset; + } + } + }break; + } + } + } } scratch_end(scratch); return out; @@ -1820,10 +2163,12 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) U64 sym_global_variables_chunk_cap = 1024; U64 sym_thread_variables_chunk_cap = 1024; U64 sym_scopes_chunk_cap = 1024; + U64 sym_inline_sites_chunk_cap = 1024; RDIM_SymbolChunkList sym_procedures = {0}; RDIM_SymbolChunkList sym_global_variables = {0}; RDIM_SymbolChunkList sym_thread_variables = {0}; RDIM_ScopeChunkList sym_scopes = {0}; + RDIM_InlineSiteChunkList sym_inline_sites = {0}; ////////////////////////// //- rjf: symbols pass 1: produce procedure frame info map (procedure -> frame info) @@ -1896,6 +2241,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) RDIM_LocationSet *defrange_target = 0; B32 defrange_target_is_param = 0; U64 procedure_num = 0; + U64 procedure_base_voff = 0; CV_RecRange *rec_ranges_first = in->sym->sym_ranges.ranges + in->sym_ranges_first; CV_RecRange *rec_ranges_opl = in->sym->sym_ranges.ranges + in->sym_ranges_opl; typedef struct P2R_ScopeNode P2R_ScopeNode; @@ -1906,6 +2252,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) }; P2R_ScopeNode *top_scope_node = 0; P2R_ScopeNode *free_scope_node = 0; + RDIM_LineTable *inline_site_line_table = in->first_inline_site_line_table; for(CV_RecRange *rec_range = rec_ranges_first; rec_range < rec_ranges_opl; rec_range += 1) @@ -2087,6 +2434,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) U64 voff_last = voff_first + proc32->len; RDIM_Rng1U64 voff_range = {voff_first, voff_last}; rdim_scope_push_voff_range(arena, &sym_scopes, procedure_root_scope, voff_range); + procedure_base_voff = voff_first; } } @@ -2496,6 +2844,206 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) defrange_target = 0; defrange_target_is_param = 0; }break; + + //- rjf: INLINESITE + case CV_SymKind_INLINESITE: + { + // rjf: unpack sym + CV_SymInlineSite *sym = (CV_SymInlineSite *)sym_header_struct_base; + String8 binary_annots = str8((U8 *)(sym+1), rec_range->hdr.size - sizeof(rec_range->hdr.kind) - sizeof(*sym)); + + // rjf: extract external info about inline site + String8 name = str8_zero(); + RDIM_Type *type = 0; + RDIM_Type *owner = 0; + if(in->ipi_leaf != 0 && in->ipi_leaf->itype_first <= sym->inlinee && sym->inlinee < in->ipi_leaf->itype_opl) + { + CV_RecRange rec_range = in->ipi_leaf->leaf_ranges.ranges[sym->inlinee - in->ipi_leaf->itype_first]; + String8 rec_data = str8_substr(in->ipi_leaf->data, rng_1u64(rec_range.off, rec_range.off + rec_range.hdr.size)); + void *raw_leaf = rec_data.str + sizeof(U16); + + // rjf: extract method inline info + if(rec_range.hdr.kind == CV_LeafIDKind_MFUNC_ID && + rec_range.hdr.size >= sizeof(CV_LeafMFuncId)) + { + CV_LeafMFuncId *mfunc_id = (CV_LeafMFuncId*)raw_leaf; + name = str8_cstring_capped(mfunc_id + 1, rec_data.str + rec_data.size); + type = p2r_type_ptr_from_itype(mfunc_id->itype); + owner = mfunc_id->owner_itype != 0 ? p2r_type_ptr_from_itype(mfunc_id->owner_itype) : 0; + } + + // rjf: extract non-method function inline info + else if(rec_range.hdr.kind == CV_LeafIDKind_FUNC_ID && + rec_range.hdr.size >= sizeof(CV_LeafFuncId)) + { + CV_LeafFuncId *func_id = (CV_LeafFuncId*)raw_leaf; + name = str8_cstring_capped(func_id + 1, rec_data.str + rec_data.size); + type = p2r_type_ptr_from_itype(func_id->itype); + owner = func_id->scope_string_id != 0 ? p2r_type_ptr_from_itype(func_id->scope_string_id) : 0; + } + } + + // rjf: build inline site + RDIM_InlineSite *inline_site = rdim_inline_site_chunk_list_push(arena, &sym_inline_sites, sym_inline_sites_chunk_cap); + inline_site->name = name; + inline_site->type = type; + inline_site->owner = owner; + inline_site->line_table = inline_site_line_table; + + // rjf: increment to next inline site line table in this unit + if(inline_site_line_table != 0 && inline_site_line_table->chunk != 0) + { + RDIM_LineTableChunkNode *chunk = inline_site_line_table->chunk; + U64 current_idx = (U64)(inline_site_line_table - chunk->v); + if(current_idx+1 < chunk->count) + { + inline_site_line_table += 1; + } + else + { + chunk = chunk->next; + inline_site_line_table = 0; + if(chunk != 0) + { + inline_site_line_table = chunk->v; + } + } + } + + // rjf: build scope + RDIM_Scope *scope = rdim_scope_chunk_list_push(arena, &sym_scopes, sym_scopes_chunk_cap); + scope->inline_site = inline_site; + if(top_scope_node == 0) + { + // TODO(rjf): log + } + if(top_scope_node != 0) + { + RDIM_Scope *top_scope = top_scope_node->scope; + SLLQueuePush_N(top_scope->first_child, top_scope->last_child, scope, next_sibling); + scope->parent_scope = top_scope; + scope->symbol = top_scope->symbol; + } + + // rjf: push this scope to scope stack + { + P2R_ScopeNode *node = free_scope_node; + if(node != 0) { SLLStackPop(free_scope_node); } + else { node = push_array_no_zero(scratch.arena, P2R_ScopeNode, 1); } + node->scope = scope; + SLLStackPush(top_scope_node, node); + } + + // rjf: parse offset ranges of this inline site - attach to scope + { + U32 code_length = 0; + U32 code_offset = 0; + U32 last_code_offset = code_offset; + U32 last_code_length = code_length; + U64 read_off = 0; + U64 read_off_opl = binary_annots.size; + for(B32 good = 1; read_off < read_off_opl && good;) + { + // rjf: decode next annotation op + U32 op = CV_InlineBinaryAnnotation_Null; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &op); + + // rjf: apply op + switch(op) + { + default:{good = 1;}break; + case CV_InlineBinaryAnnotation_Null: + { + good = 0; + }break; + case CV_InlineBinaryAnnotation_CodeOffset: + { + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_offset); + }break; + case CV_InlineBinaryAnnotation_ChangeCodeOffsetBase: + { + good = 0; + // TODO(rjf): currently untested/unknown - first guess below: + // + // U32 delta = 0; + // read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &delta); + // code_offset_base = code_offset; + // code_offset_end = code_offset + delta; + // code_offset += delta; + }break; + case CV_InlineBinaryAnnotation_ChangeCodeOffset: + { + U32 delta = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &delta); + code_offset += delta; + }break; + case CV_InlineBinaryAnnotation_ChangeCodeLength: + { + code_length = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_length); + }break; + case CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset: + { + U32 code_offset_and_line_offset = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_offset_and_line_offset); + U32 code_delta = (code_offset_and_line_offset & 0xf); + code_offset += code_delta; + }break; + case CV_InlineBinaryAnnotation_ChangeCodeLengthAndCodeOffset: + { + U32 offset_delta = 0; + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &code_length); + read_off += cv_decode_inline_annot_u32(binary_annots, read_off, &offset_delta); + code_offset += offset_delta; + }break; + } + + // rjf: gather new ranges + if(last_code_length != code_length) + { + // rjf: convert current state machine state to [first_voff, opl_voff) range + RDIM_Rng1U64 voff_range = + { + procedure_base_voff + code_offset, + procedure_base_voff + code_offset + code_length, + }; + + // rjf: attempt to extend last-added range to cover this range, if possible + if(scope->voff_ranges.last != 0 && scope->voff_ranges.last->v.max == voff_range.min) + { + scope->voff_ranges.last->v.max = voff_range.max; + } + + // rjf: cannot add to previous range? -> build new range & add to scope + else + { + rdim_scope_push_voff_range(arena, &sym_scopes, scope, voff_range); + } + + // rjf: advance + code_offset += code_length; + code_length = 0; + } + + // rjf: update prev/current states + last_code_offset = code_offset; + last_code_length = code_length; + } + } + }break; + + //- rjf: INLINESITE_END + case CV_SymKind_INLINESITE_END: + { + P2R_ScopeNode *n = top_scope_node; + if(n != 0) + { + SLLStackPop(top_scope_node); + SLLStackPush(free_scope_node, n); + } + defrange_target = 0; + defrange_target_is_param = 0; + }break; } } } @@ -2509,6 +3057,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) out->global_variables = sym_global_variables; out->thread_variables = sym_thread_variables; out->scopes = sym_scopes; + out->inline_sites = sym_inline_sites; } #undef p2r_type_ptr_from_itype @@ -2797,10 +3346,11 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) // RDIM_TopLevelInfo top_level_info = {0}; { - top_level_info.arch = arch; - top_level_info.exe_name = str8_skip_last_slash(in->input_exe_name); - top_level_info.exe_hash = exe_hash; - top_level_info.voff_max = exe_voff_max; + top_level_info.arch = arch; + top_level_info.exe_name = str8_skip_last_slash(in->input_exe_name); + top_level_info.exe_hash = exe_hash; + top_level_info.voff_max = exe_voff_max; + top_level_info.producer_name = str8_lit(BUILD_TITLE_STRING_LITERAL); } ////////////////////////////////////////////////////////////// @@ -2828,7 +3378,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) ////////////////////////////////////////////////////////////// //- rjf: kick off unit conversion & source file collection // - P2R_UnitConvertIn unit_convert_in = {comp_units, comp_unit_contributions, sym_for_unit, c13_for_unit}; + P2R_UnitConvertIn unit_convert_in = {strtbl, coff_sections, comp_units, comp_unit_contributions, sym_for_unit, c13_for_unit}; TS_Ticket unit_convert_ticket = ts_kickoff(p2r_units_convert_task__entry_point, 0, &unit_convert_in); ////////////////////////////////////////////////////////////// @@ -3436,6 +3986,22 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) link_name_map = &link_name_map__in_progress; } + ////////////////////////////////////////////////////////////// + //- rjf: join unit conversion & src file & line table tasks + // + RDIM_UnitChunkList all_units = {0}; + RDIM_SrcFileChunkList all_src_files = {0}; + RDIM_LineTableChunkList all_line_tables = {0}; + RDIM_LineTable **units_first_inline_site_line_tables = 0; + ProfScope("join unit conversion & src file tasks") + { + P2R_UnitConvertOut *out = ts_join_struct(unit_convert_ticket, max_U64, P2R_UnitConvertOut); + all_units = out->units; + all_src_files = out->src_files; + all_line_tables = out->line_tables; + units_first_inline_site_line_tables = out->units_first_inline_site_line_tables; + } + ////////////////////////////////////////////////////////////// //- rjf: produce symbols from all streams // @@ -3443,6 +4009,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) RDIM_SymbolChunkList all_global_variables = {0}; RDIM_SymbolChunkList all_thread_variables = {0}; RDIM_ScopeChunkList all_scopes = {0}; + RDIM_InlineSiteChunkList all_inline_sites = {0}; ProfScope("produce symbols from all streams") { //////////////////////////// @@ -3457,13 +4024,14 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) { for(U64 idx = 0; idx < tasks_count; idx += 1) { - tasks_inputs[idx].arch = arch; - tasks_inputs[idx].coff_sections = coff_sections; - tasks_inputs[idx].tpi_hash = tpi_hash; - tasks_inputs[idx].tpi_leaf = tpi_leaf; - tasks_inputs[idx].itype_fwd_map = itype_fwd_map; - tasks_inputs[idx].itype_type_ptrs = itype_type_ptrs; - tasks_inputs[idx].link_name_map = link_name_map; + tasks_inputs[idx].arch = arch; + tasks_inputs[idx].coff_sections = coff_sections; + tasks_inputs[idx].tpi_hash = tpi_hash; + tasks_inputs[idx].tpi_leaf = tpi_leaf; + tasks_inputs[idx].ipi_leaf = ipi_leaf; + tasks_inputs[idx].itype_fwd_map = itype_fwd_map; + tasks_inputs[idx].itype_type_ptrs = itype_type_ptrs; + tasks_inputs[idx].link_name_map = link_name_map; if(idx < global_stream_subdivision_tasks_count) { tasks_inputs[idx].sym = sym; @@ -3476,6 +4044,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) tasks_inputs[idx].sym = sym_for_unit[idx-global_stream_subdivision_tasks_count]; tasks_inputs[idx].sym_ranges_first= 0; tasks_inputs[idx].sym_ranges_opl = sym_for_unit[idx-global_stream_subdivision_tasks_count]->sym_ranges.count; + tasks_inputs[idx].first_inline_site_line_table = units_first_inline_site_line_tables[idx-global_stream_subdivision_tasks_count]; } tasks_tickets[idx] = ts_kickoff(p2r_symbol_stream_convert_task__entry_point, 0, &tasks_inputs[idx]); } @@ -3493,22 +4062,11 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) rdim_symbol_chunk_list_concat_in_place(&all_global_variables, &out->global_variables); rdim_symbol_chunk_list_concat_in_place(&all_thread_variables, &out->thread_variables); rdim_scope_chunk_list_concat_in_place(&all_scopes, &out->scopes); + rdim_inline_site_chunk_list_concat_in_place(&all_inline_sites,&out->inline_sites); } } } - ////////////////////////////////////////////////////////////// - //- rjf: join unit conversion & src file tasks - // - RDIM_UnitChunkList all_units = {0}; - RDIM_SrcFileChunkList all_src_files = {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; - } - ////////////////////////////////////////////////////////////// //- rjf: types pass 5: join UDT build tasks // @@ -3530,10 +4088,12 @@ 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; out->bake_params.scopes = all_scopes; + out->bake_params.inline_sites = all_inline_sites; } scratch_end(scratch); @@ -3619,6 +4179,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_LineTableBakeResult *out = push_array(arena, RDIM_LineTableBakeResult, 1); + ProfScope("bake line tables") *out = rdim_bake_line_tables(arena, in->line_tables); + return out; +} + #undef p2r_make_string_map_if_needed //- rjf: bake string map joining @@ -3688,108 +4256,108 @@ 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); - return s; + P2R_BakeUnitsIn *in = (P2R_BakeUnitsIn *)p; + RDIM_UnitBakeResult *out = push_array(arena, RDIM_UnitBakeResult, 1); + ProfScope("bake units") *out = rdim_bake_units(arena, in->strings, in->path_tree, in->units); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_unit_vmap_task__entry_point) { P2R_BakeUnitVMapIn *in = (P2R_BakeUnitVMapIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake unit vmap") *s = rdim_bake_unit_vmap_section_list_from_params(arena, in->params); - return s; + RDIM_UnitVMapBakeResult *out = push_array(arena, RDIM_UnitVMapBakeResult, 1); + ProfScope("bake unit vmap") *out = rdim_bake_unit_vmap(arena, in->units); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_src_files_task__entry_point) { P2R_BakeSrcFilesIn *in = (P2R_BakeSrcFilesIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake src files") *s = rdim_bake_src_file_section_list_from_params(arena, in->strings, in->path_tree, in->params); - return s; + RDIM_SrcFileBakeResult *out = push_array(arena, RDIM_SrcFileBakeResult, 1); + ProfScope("bake src files") *out = rdim_bake_src_files(arena, in->strings, in->path_tree, in->src_files); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_udts_task__entry_point) { P2R_BakeUDTsIn *in = (P2R_BakeUDTsIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake udts") *s = rdim_bake_udt_section_list_from_params(arena, in->strings, in->params); - return s; + RDIM_UDTBakeResult *out = push_array(arena, RDIM_UDTBakeResult, 1); + ProfScope("bake udts") *out = rdim_bake_udts(arena, in->strings, in->udts); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_global_variables_task__entry_point) { P2R_BakeGlobalVariablesIn *in = (P2R_BakeGlobalVariablesIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake global variables") *s = rdim_bake_global_variable_section_list_from_params(arena, in->strings, in->params); - return s; + RDIM_GlobalVariableBakeResult *out = push_array(arena, RDIM_GlobalVariableBakeResult, 1); + ProfScope("bake global variables") *out = rdim_bake_global_variables(arena, in->strings, in->global_variables); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_global_vmap_task__entry_point) { P2R_BakeGlobalVMapIn *in = (P2R_BakeGlobalVMapIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake global vmap") *s = rdim_bake_global_vmap_section_list_from_params(arena, in->params); - return s; + RDIM_GlobalVMapBakeResult *out = push_array(arena, RDIM_GlobalVMapBakeResult, 1); + ProfScope("bake global vmap") *out = rdim_bake_global_vmap(arena, in->global_variables); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_thread_variables_task__entry_point) { P2R_BakeThreadVariablesIn *in = (P2R_BakeThreadVariablesIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake thread variables") *s = rdim_bake_thread_variable_section_list_from_params(arena, in->strings, in->params); - return s; + RDIM_ThreadVariableBakeResult *out = push_array(arena, RDIM_ThreadVariableBakeResult, 1); + ProfScope("bake thread variables") *out = rdim_bake_thread_variables(arena, in->strings, in->thread_variables); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_procedures_task__entry_point) { P2R_BakeProceduresIn *in = (P2R_BakeProceduresIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake procedures") *s = rdim_bake_procedure_section_list_from_params(arena, in->strings, in->params); - return s; + RDIM_ProcedureBakeResult *out = push_array(arena, RDIM_ProcedureBakeResult, 1); + ProfScope("bake procedures") *out = rdim_bake_procedures(arena, in->strings, in->procedures); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_scopes_task__entry_point) { P2R_BakeScopesIn *in = (P2R_BakeScopesIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake scopes") *s = rdim_bake_scope_section_list_from_params(arena, in->strings, in->params); - return s; + RDIM_ScopeBakeResult *out = push_array(arena, RDIM_ScopeBakeResult, 1); + ProfScope("bake scopes") *out = rdim_bake_scopes(arena, in->strings, in->scopes); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_scope_vmap_task__entry_point) { P2R_BakeScopeVMapIn *in = (P2R_BakeScopeVMapIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake scope vmap") *s = rdim_bake_scope_vmap_section_list_from_params(arena, in->params); - return s; + RDIM_ScopeVMapBakeResult *out = push_array(arena, RDIM_ScopeVMapBakeResult, 1); + ProfScope("bake scope vmap") *out = rdim_bake_scope_vmap(arena, in->scopes); + return out; +} + +internal TS_TASK_FUNCTION_DEF(p2r_bake_inline_sites_task__entry_point) +{ + P2R_BakeInlineSitesIn *in = (P2R_BakeInlineSitesIn *)p; + RDIM_InlineSiteBakeResult *out = push_array(arena, RDIM_InlineSiteBakeResult, 1); + ProfScope("bake inline sites") *out = rdim_bake_inline_sites(arena, in->strings, in->inline_sites); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_file_paths_task__entry_point) { P2R_BakeFilePathsIn *in = (P2R_BakeFilePathsIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake file paths") *s = rdim_bake_file_path_section_list_from_path_tree(arena, in->strings, in->path_tree); - return s; + RDIM_FilePathBakeResult *out = push_array(arena, RDIM_FilePathBakeResult, 1); + ProfScope("bake file paths") *out = rdim_bake_file_paths(arena, in->strings, in->path_tree); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_strings_task__entry_point) { P2R_BakeStringsIn *in = (P2R_BakeStringsIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake strings") *s = rdim_bake_string_section_list_from_string_map(arena, in->strings); - return s; + RDIM_StringBakeResult *out = push_array(arena, RDIM_StringBakeResult, 1); + ProfScope("bake strings") *out = rdim_bake_strings(arena, in->strings); + return out; } //- rjf: pass 3: idx-run-map-dependent debug info stream builds @@ -3797,25 +4365,25 @@ internal TS_TASK_FUNCTION_DEF(p2r_bake_strings_task__entry_point) internal TS_TASK_FUNCTION_DEF(p2r_bake_type_nodes_task__entry_point) { P2R_BakeTypeNodesIn *in = (P2R_BakeTypeNodesIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake type nodes") *s = rdim_bake_type_node_section_list_from_params(arena, in->strings, in->idx_runs, in->params); - return s; + RDIM_TypeNodeBakeResult *out = push_array(arena, RDIM_TypeNodeBakeResult, 1); + ProfScope("bake type nodes") *out = rdim_bake_types(arena, in->strings, in->idx_runs, in->types); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_name_map_task__entry_point) { P2R_BakeNameMapIn *in = (P2R_BakeNameMapIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake name map %i", in->kind) *s = rdim_bake_name_map_section_list_from_params_kind_map(arena, in->strings, in->idx_runs, in->params, in->kind, in->map); - return s; + RDIM_NameMapBakeResult *out = push_array(arena, RDIM_NameMapBakeResult, 1); + ProfScope("bake name map %i", in->kind) *out = rdim_bake_name_map(arena, in->strings, in->idx_runs, in->map); + return out; } internal TS_TASK_FUNCTION_DEF(p2r_bake_idx_runs_task__entry_point) { P2R_BakeIdxRunsIn *in = (P2R_BakeIdxRunsIn *)p; - RDIM_BakeSectionList *s = push_array(arena, RDIM_BakeSectionList, 1); - ProfScope("bake idx runs") *s = rdim_bake_idx_run_section_list_from_idx_run_map(arena, in->idx_runs); - return s; + RDIM_IndexRunBakeResult *out = push_array(arena, RDIM_IndexRunBakeResult, 1); + ProfScope("bake idx runs") *out = rdim_bake_index_runs(arena, in->idx_runs); + return out; } //////////////////////////////// @@ -3825,36 +4393,36 @@ internal P2R_Bake2Serialize * p2r_bake(Arena *arena, P2R_Convert2Bake *in) { Temp scratch = scratch_begin(&arena, 1); - RDIM_BakeParams *params = &in->bake_params; - RDIM_BakeSectionList sections = {0}; + RDIM_BakeParams *in_params = &in->bake_params; + P2R_Bake2Serialize *out = push_array(arena, P2R_Bake2Serialize, 1); + RDIM_BakeResults *out_results = &out->bake_results; + ////////////////////////////// + //- rjf: kick off line tables baking + // + TS_Ticket bake_line_tables_ticket = {0}; + { + P2R_BakeLineTablesIn *in = push_array(scratch.arena, P2R_BakeLineTablesIn, 1); + in->line_tables = &in_params->line_tables; + bake_line_tables_ticket = ts_kickoff(p2r_bake_line_tables_task__entry_point, 0, in); + } + + ////////////////////////////// //- rjf: build interned path tree + // RDIM_BakePathTree *path_tree = 0; ProfScope("build interned path tree") { - path_tree = rdim_bake_path_tree_from_params(arena, 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]); - } - } + path_tree = rdim_bake_path_tree_from_params(arena, in_params); } + ////////////////////////////// //- rjf: kick off string map building tasks - RDIM_BakeStringMapTopology bake_string_map_topology = {(params->procedures.total_count*1 + - params->global_variables.total_count*1 + - params->thread_variables.total_count*1 + - params->types.total_count/2)}; + // + RDIM_BakeStringMapTopology bake_string_map_topology = {(in_params->procedures.total_count*1 + + in_params->global_variables.total_count*1 + + in_params->thread_variables.total_count*1 + + in_params->types.total_count/2)}; RDIM_BakeStringMapLoose **bake_string_maps__in_progress = push_array(scratch.arena, RDIM_BakeStringMapLoose *, ts_thread_count()); TS_TicketList bake_string_map_build_tickets = {0}; { @@ -3864,7 +4432,7 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) P2R_BakeSrcFilesStringsIn *in = push_array(scratch.arena, P2R_BakeSrcFilesStringsIn, 1); in->top = &bake_string_map_topology; in->maps = bake_string_maps__in_progress; - in->list = ¶ms->src_files; + in->list = &in_params->src_files; ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_src_files_strings_task__entry_point, 0, in)); } @@ -3874,49 +4442,71 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) P2R_BakeUnitsStringsIn *in = push_array(scratch.arena, P2R_BakeUnitsStringsIn, 1); in->top = &bake_string_map_topology; in->maps = bake_string_maps__in_progress; - in->list = ¶ms->units; + in->list = &in_params->units; ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_units_strings_task__entry_point, 0, in)); } // rjf: types ProfScope("kick off types string map build tasks") { - for(RDIM_TypeChunkNode *chunk = params->types.first; chunk != 0; chunk = chunk->next) + U64 items_per_task = 4096; + U64 num_tasks = (in_params->types.total_count+items_per_task-1)/items_per_task; + RDIM_TypeChunkNode *chunk = in_params->types.first; + U64 chunk_off = 0; + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) { - U64 items_per_task = Min(4096, chunk->count); - U64 tasks_per_this_chunk = (chunk->count+items_per_task-1)/items_per_task; - for(U64 task_idx = 0; task_idx < tasks_per_this_chunk; task_idx += 1) + P2R_BakeTypesStringsIn *in = push_array(scratch.arena, P2R_BakeTypesStringsIn, 1); + in->top = &bake_string_map_topology; + in->maps = bake_string_maps__in_progress; + U64 items_left = items_per_task; + for(;chunk != 0 && items_left > 0;) { - P2R_BakeTypesStringsIn *in = push_array(scratch.arena, P2R_BakeTypesStringsIn, 1); - in->top = &bake_string_map_topology; - in->maps = bake_string_maps__in_progress; + U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); P2R_BakeTypesStringsInNode *n = push_array(scratch.arena, P2R_BakeTypesStringsInNode, 1); SLLQueuePush(in->first, in->last, n); - n->v = chunk->v + task_idx*items_per_task; - n->count = Min(items_per_task, chunk->count - task_idx*items_per_task); - ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_types_strings_task__entry_point, 0, in)); + n->v = chunk->v + chunk_off; + n->count = items_in_this_chunk; + chunk_off += items_in_this_chunk; + items_left -= items_in_this_chunk; + if(chunk_off >= chunk->count) + { + chunk = chunk->next; + chunk_off = 0; + } } + ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_types_strings_task__entry_point, 0, in)); } } // rjf: UDTs ProfScope("kick off udts string map build tasks") { - for(RDIM_UDTChunkNode *chunk = params->udts.first; chunk != 0; chunk = chunk->next) + U64 items_per_task = 4096; + U64 num_tasks = (in_params->udts.total_count+items_per_task-1)/items_per_task; + RDIM_UDTChunkNode *chunk = in_params->udts.first; + U64 chunk_off = 0; + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) { - U64 items_per_task = Min(4096, chunk->count); - U64 tasks_per_this_chunk = (chunk->count+items_per_task-1)/items_per_task; - for(U64 task_idx = 0; task_idx < tasks_per_this_chunk; task_idx += 1) + P2R_BakeUDTsStringsIn *in = push_array(scratch.arena, P2R_BakeUDTsStringsIn, 1); + in->top = &bake_string_map_topology; + in->maps = bake_string_maps__in_progress; + U64 items_left = items_per_task; + for(;chunk != 0 && items_left > 0;) { - P2R_BakeUDTsStringsIn *in = push_array(scratch.arena, P2R_BakeUDTsStringsIn, 1); - in->top = &bake_string_map_topology; - in->maps = bake_string_maps__in_progress; + U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); P2R_BakeUDTsStringsInNode *n = push_array(scratch.arena, P2R_BakeUDTsStringsInNode, 1); SLLQueuePush(in->first, in->last, n); - n->v = chunk->v + task_idx*items_per_task; - n->count = Min(items_per_task, chunk->count - task_idx*items_per_task); - ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_udts_strings_task__entry_point, 0, in)); + n->v = chunk->v + chunk_off; + n->count = items_in_this_chunk; + chunk_off += items_in_this_chunk; + items_left -= items_in_this_chunk; + if(chunk_off >= chunk->count) + { + chunk = chunk->next; + chunk_off = 0; + } } + ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_udts_strings_task__entry_point, 0, in)); } } @@ -3925,27 +4515,38 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) { RDIM_SymbolChunkList *symbol_lists[] = { - ¶ms->global_variables, - ¶ms->thread_variables, - ¶ms->procedures, + &in_params->global_variables, + &in_params->thread_variables, + &in_params->procedures, }; for(U64 list_idx = 0; list_idx < ArrayCount(symbol_lists); list_idx += 1) { - for(RDIM_SymbolChunkNode *chunk = symbol_lists[list_idx]->first; chunk != 0; chunk = chunk->next) + U64 items_per_task = 4096; + U64 num_tasks = (symbol_lists[list_idx]->total_count+items_per_task-1)/items_per_task; + RDIM_SymbolChunkNode *chunk = symbol_lists[list_idx]->first; + U64 chunk_off = 0; + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) { - U64 items_per_task = Min(4096, chunk->count); - U64 tasks_per_this_chunk = (chunk->count+items_per_task-1)/items_per_task; - for(U64 task_idx = 0; task_idx < tasks_per_this_chunk; task_idx += 1) + P2R_BakeSymbolsStringsIn *in = push_array(scratch.arena, P2R_BakeSymbolsStringsIn, 1); + in->top = &bake_string_map_topology; + in->maps = bake_string_maps__in_progress; + U64 items_left = items_per_task; + for(;chunk != 0 && items_left > 0;) { - P2R_BakeSymbolsStringsIn *in = push_array(scratch.arena, P2R_BakeSymbolsStringsIn, 1); - in->top = &bake_string_map_topology; - in->maps = bake_string_maps__in_progress; + U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); P2R_BakeSymbolsStringsInNode *n = push_array(scratch.arena, P2R_BakeSymbolsStringsInNode, 1); SLLQueuePush(in->first, in->last, n); - n->v = chunk->v + task_idx*items_per_task; - n->count = Min(items_per_task, chunk->count - task_idx*items_per_task); - ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_symbols_strings_task__entry_point, 0, in)); + n->v = chunk->v + chunk_off; + n->count = items_in_this_chunk; + chunk_off += items_in_this_chunk; + items_left -= items_in_this_chunk; + if(chunk_off >= chunk->count) + { + chunk = chunk->next; + chunk_off = 0; + } } + ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_symbols_strings_task__entry_point, 0, in)); } } } @@ -3953,26 +4554,39 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) // rjf: scope chunks ProfScope("kick off scope chunks string map build tasks") { - for(RDIM_ScopeChunkNode *chunk = params->scopes.first; chunk != 0; chunk = chunk->next) + U64 items_per_task = 4096; + U64 num_tasks = (in_params->scopes.total_count+items_per_task-1)/items_per_task; + RDIM_ScopeChunkNode *chunk = in_params->scopes.first; + U64 chunk_off = 0; + for(U64 task_idx = 0; task_idx < num_tasks; task_idx += 1) { - U64 items_per_task = Min(4096, chunk->count); - U64 tasks_per_this_chunk = (chunk->count+items_per_task-1)/items_per_task; - for(U64 task_idx = 0; task_idx < tasks_per_this_chunk; task_idx += 1) + P2R_BakeScopesStringsIn *in = push_array(scratch.arena, P2R_BakeScopesStringsIn, 1); + in->top = &bake_string_map_topology; + in->maps = bake_string_maps__in_progress; + U64 items_left = items_per_task; + for(;chunk != 0 && items_left > 0;) { - P2R_BakeScopesStringsIn *in = push_array(scratch.arena, P2R_BakeScopesStringsIn, 1); - in->top = &bake_string_map_topology; - in->maps = bake_string_maps__in_progress; + U64 items_in_this_chunk = Min(items_per_task, chunk->count-chunk_off); P2R_BakeScopesStringsInNode *n = push_array(scratch.arena, P2R_BakeScopesStringsInNode, 1); SLLQueuePush(in->first, in->last, n); - n->v = chunk->v + task_idx*items_per_task; - n->count = Min(items_per_task, chunk->count - task_idx*items_per_task); - ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_scopes_strings_task__entry_point, 0, in)); + n->v = chunk->v + chunk_off; + n->count = items_in_this_chunk; + chunk_off += items_in_this_chunk; + items_left -= items_in_this_chunk; + if(chunk_off >= chunk->count) + { + chunk = chunk->next; + chunk_off = 0; + } } + ts_ticket_list_push(scratch.arena, &bake_string_map_build_tickets, ts_kickoff(p2r_bake_scopes_strings_task__entry_point, 0, in)); } } } + ////////////////////////////// //- rjf: kick off name map building tasks + // P2R_BuildBakeNameMapIn build_bake_name_map_in[RDI_NameMapKind_COUNT] = {0}; TS_Ticket build_bake_name_map_ticket[RDI_NameMapKind_COUNT] = {0}; for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); @@ -3980,11 +4594,13 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) k = (RDI_NameMapKind)(k+1)) { build_bake_name_map_in[k].k = k; - build_bake_name_map_in[k].params = params; + build_bake_name_map_in[k].params = in_params; build_bake_name_map_ticket[k] = ts_kickoff(p2r_build_bake_name_map_task__entry_point, 0, &build_bake_name_map_in[k]); } + ////////////////////////////// //- rjf: join string map building tasks + // ProfScope("join string map building tasks") { for(TS_TicketNode *n = bake_string_map_build_tickets.first; n != 0; n = n->next) @@ -3993,7 +4609,9 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) } } + ////////////////////////////// //- rjf: produce joined string map + // RDIM_BakeStringMapLoose *unsorted_bake_string_map = rdim_bake_string_map_loose_make(arena, &bake_string_map_topology); ProfScope("produce joined string map") { @@ -4021,12 +4639,14 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) } // rjf: insert small top-level stuff - rdim_bake_string_map_loose_push_top_level_info(arena, &bake_string_map_topology, unsorted_bake_string_map, ¶ms->top_level_info); - rdim_bake_string_map_loose_push_binary_sections(arena, &bake_string_map_topology, unsorted_bake_string_map, ¶ms->binary_sections); + rdim_bake_string_map_loose_push_top_level_info(arena, &bake_string_map_topology, unsorted_bake_string_map, &in_params->top_level_info); + rdim_bake_string_map_loose_push_binary_sections(arena, &bake_string_map_topology, unsorted_bake_string_map, &in_params->binary_sections); rdim_bake_string_map_loose_push_path_tree(arena, &bake_string_map_topology, unsorted_bake_string_map, path_tree); } + ////////////////////////////// //- rjf: kick off string map sorting tasks + // TS_TicketList sort_bake_string_map_task_tickets = {0}; RDIM_BakeStringMapLoose *sorted_bake_string_map__in_progress = rdim_bake_string_map_loose_make(arena, &bake_string_map_topology); { @@ -4050,7 +4670,9 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) } } + ////////////////////////////// //- rjf: join string map sorting tasks + // ProfScope("join string map sorting tasks") { for(TS_TicketNode *n = sort_bake_string_map_task_tickets.first; n != 0; n = n->next) @@ -4060,7 +4682,9 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) } RDIM_BakeStringMapLoose *sorted_bake_string_map = sorted_bake_string_map__in_progress; + ////////////////////////////// //- rjf: build finalized string map + // ProfBegin("build finalized string map base indices"); RDIM_BakeStringMapBaseIndices bake_string_map_base_idxes = rdim_bake_string_map_base_indices_from_map_loose(arena, &bake_string_map_topology, sorted_bake_string_map); ProfEnd(); @@ -4068,47 +4692,39 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) RDIM_BakeStringMapTight bake_strings = rdim_bake_string_map_tight_from_loose(arena, &bake_string_map_topology, &bake_string_map_base_idxes, sorted_bake_string_map); ProfEnd(); + ////////////////////////////// //- rjf: kick off pass 2 tasks - P2R_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); - P2R_BakeUnitVMapIn bake_unit_vmap_in = {params}; + // + P2R_BakeUnitsIn bake_units_top_level_in = {&bake_strings, path_tree, &in_params->units}; + TS_Ticket bake_units_ticket = ts_kickoff(p2r_bake_units_task__entry_point, 0, &bake_units_top_level_in); + P2R_BakeUnitVMapIn bake_unit_vmap_in = {&in_params->units}; TS_Ticket bake_unit_vmap_ticket = ts_kickoff(p2r_bake_unit_vmap_task__entry_point, 0, &bake_unit_vmap_in); - P2R_BakeSrcFilesIn bake_src_files_in = {&bake_strings, path_tree, params}; + P2R_BakeSrcFilesIn bake_src_files_in = {&bake_strings, path_tree, &in_params->src_files}; TS_Ticket bake_src_files_ticket = ts_kickoff(p2r_bake_src_files_task__entry_point, 0, &bake_src_files_in); - P2R_BakeUDTsIn bake_udts_in = {&bake_strings, params}; + P2R_BakeUDTsIn bake_udts_in = {&bake_strings, &in_params->udts}; TS_Ticket bake_udts_ticket = ts_kickoff(p2r_bake_udts_task__entry_point, 0, &bake_udts_in); - P2R_BakeGlobalVariablesIn bake_global_variables_in = {&bake_strings, params}; + P2R_BakeGlobalVariablesIn bake_global_variables_in = {&bake_strings, &in_params->global_variables}; TS_Ticket bake_global_variables_ticket = ts_kickoff(p2r_bake_global_variables_task__entry_point, 0, &bake_global_variables_in); - P2R_BakeGlobalVMapIn bake_global_vmap_in = {params}; + P2R_BakeGlobalVMapIn bake_global_vmap_in = {&in_params->global_variables}; TS_Ticket bake_global_vmap_ticket = ts_kickoff(p2r_bake_global_vmap_task__entry_point, 0, &bake_global_vmap_in); - P2R_BakeThreadVariablesIn bake_thread_variables_in = {&bake_strings, params}; + P2R_BakeThreadVariablesIn bake_thread_variables_in = {&bake_strings, &in_params->thread_variables}; TS_Ticket bake_thread_variables_ticket = ts_kickoff(p2r_bake_thread_variables_task__entry_point, 0, &bake_thread_variables_in); - P2R_BakeProceduresIn bake_procedures_in = {&bake_strings, params}; + P2R_BakeProceduresIn bake_procedures_in = {&bake_strings, &in_params->procedures}; TS_Ticket bake_procedures_ticket = ts_kickoff(p2r_bake_procedures_task__entry_point, 0, &bake_procedures_in); - P2R_BakeScopesIn bake_scopes_in = {&bake_strings, params}; + P2R_BakeScopesIn bake_scopes_in = {&bake_strings, &in_params->scopes}; TS_Ticket bake_scopes_ticket = ts_kickoff(p2r_bake_scopes_task__entry_point, 0, &bake_scopes_in); - P2R_BakeScopeVMapIn bake_scope_vmap_in = {params}; + P2R_BakeScopeVMapIn bake_scope_vmap_in = {&in_params->scopes}; TS_Ticket bake_scope_vmap_ticket = ts_kickoff(p2r_bake_scope_vmap_task__entry_point, 0, &bake_scope_vmap_in); + P2R_BakeInlineSitesIn bake_inline_sites_in = {&bake_strings, &in_params->inline_sites}; + TS_Ticket bake_inline_sites_ticket = ts_kickoff(p2r_bake_inline_sites_task__entry_point, 0, &bake_inline_sites_in); P2R_BakeFilePathsIn bake_file_paths_in = {&bake_strings, path_tree}; TS_Ticket bake_file_paths_ticket = ts_kickoff(p2r_bake_file_paths_task__entry_point, 0, &bake_file_paths_in); P2R_BakeStringsIn bake_strings_in = {&bake_strings}; TS_Ticket bake_strings_ticket = ts_kickoff(p2r_bake_strings_task__entry_point, 0, &bake_strings_in); - //- rjf: top-level info - ProfScope("top level info") - { - RDIM_BakeSectionList s = rdim_bake_top_level_info_section_list_from_params(arena, &bake_strings, params); - rdim_bake_section_list_concat_in_place(§ions, &s); - } - - //- rjf: binary sections - ProfScope("binary sections") - { - RDIM_BakeSectionList s = rdim_bake_binary_section_section_list_from_params(arena, &bake_strings, params); - rdim_bake_section_list_concat_in_place(§ions, &s); - } - + ////////////////////////////// //- rjf: join name map building tasks + // RDIM_BakeNameMap *name_maps[RDI_NameMapKind_COUNT] = {0}; ProfScope("join name map building tasks") { @@ -4120,164 +4736,90 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) } } + ////////////////////////////// //- rjf: build interned idx run map + // RDIM_BakeIdxRunMap *idx_runs = 0; ProfScope("build interned idx run map") { - idx_runs = rdim_bake_idx_run_map_from_params(arena, name_maps, params); + idx_runs = rdim_bake_idx_run_map_from_params(arena, name_maps, in_params); } + ////////////////////////////// + //- rjf: do small top-level bakes + // + ProfScope("top level info") out_results->top_level_info = rdim_bake_top_level_info(arena, &bake_strings, &in_params->top_level_info); + ProfScope("binary sections") out_results->binary_sections = rdim_bake_binary_sections(arena, &bake_strings, &in_params->binary_sections); + ProfScope("top level name maps section") out_results->top_level_name_maps = rdim_bake_name_maps_top_level(arena, &bake_strings, idx_runs, name_maps); + + ////////////////////////////// //- rjf: kick off pass 3 tasks - P2R_BakeTypeNodesIn bake_type_nodes_in = {&bake_strings, idx_runs, params}; + // + P2R_BakeTypeNodesIn bake_type_nodes_in = {&bake_strings, idx_runs, &in_params->types}; TS_Ticket bake_type_nodes_ticket = ts_kickoff(p2r_bake_type_nodes_task__entry_point, 0, &bake_type_nodes_in); - TS_TicketList bake_name_maps_tickets = {0}; - for(RDI_NameMapKind k = (RDI_NameMapKind)(RDI_NameMapKind_NULL+1); - k < RDI_NameMapKind_COUNT; - k = (RDI_NameMapKind)(k+1)) + TS_Ticket bake_name_maps_tickets[RDI_NameMapKind_COUNT] = {0}; { - if(name_maps[k] == 0 || name_maps[k]->name_count == 0) + for(EachNonZeroEnumVal(RDI_NameMapKind, k)) { - continue; + if(name_maps[k] == 0 || name_maps[k]->name_count == 0) + { + continue; + } + P2R_BakeNameMapIn *in = push_array(scratch.arena, P2R_BakeNameMapIn, 1); + in->strings = &bake_strings; + in->idx_runs = idx_runs; + in->map = name_maps[k]; + in->kind = k; + bake_name_maps_tickets[k] = ts_kickoff(p2r_bake_name_map_task__entry_point, 0, in); } - P2R_BakeNameMapIn *in = push_array(scratch.arena, P2R_BakeNameMapIn, 1); - in->strings = &bake_strings; - in->idx_runs = idx_runs; - in->params = params; - in->kind = k; - in->map = name_maps[k]; - ts_ticket_list_push(scratch.arena, &bake_name_maps_tickets, ts_kickoff(p2r_bake_name_map_task__entry_point, 0, in)); } P2R_BakeIdxRunsIn bake_idx_runs_in = {idx_runs}; TS_Ticket bake_idx_runs_ticket = ts_kickoff(p2r_bake_idx_runs_task__entry_point, 0, &bake_idx_runs_in); - //- rjf: bake top-level name maps section - ProfScope("top level name maps section") - { - RDIM_BakeSectionList s = rdim_bake_top_level_name_map_section_list_from_params_maps(arena, &bake_strings, idx_runs, params, name_maps); - rdim_bake_section_list_concat_in_place(§ions, &s); - } + ////////////////////////////// + //- rjf: join remaining completed bakes + // + ProfScope("top-level units info") out_results->units = *ts_join_struct(bake_units_ticket, max_U64, RDIM_UnitBakeResult); + ProfScope("unit vmap") out_results->unit_vmap = *ts_join_struct(bake_unit_vmap_ticket, max_U64, RDIM_UnitVMapBakeResult); + ProfScope("source files") out_results->src_files = *ts_join_struct(bake_src_files_ticket, max_U64, RDIM_SrcFileBakeResult); + ProfScope("UDTs") out_results->udts = *ts_join_struct(bake_udts_ticket, max_U64, RDIM_UDTBakeResult); + ProfScope("global variables") out_results->global_variables = *ts_join_struct(bake_global_variables_ticket, max_U64, RDIM_GlobalVariableBakeResult); + ProfScope("global vmap") out_results->global_vmap = *ts_join_struct(bake_global_vmap_ticket, max_U64, RDIM_GlobalVMapBakeResult); + ProfScope("thread variables") out_results->thread_variables = *ts_join_struct(bake_thread_variables_ticket, max_U64, RDIM_ThreadVariableBakeResult); + ProfScope("procedures") out_results->procedures = *ts_join_struct(bake_procedures_ticket, max_U64, RDIM_ProcedureBakeResult); + ProfScope("scopes") out_results->scopes = *ts_join_struct(bake_scopes_ticket, max_U64, RDIM_ScopeBakeResult); + ProfScope("scope vmap") out_results->scope_vmap = *ts_join_struct(bake_scope_vmap_ticket, max_U64, RDIM_ScopeVMapBakeResult); + ProfScope("inline sites") out_results->inline_sites = *ts_join_struct(bake_inline_sites_ticket, max_U64, RDIM_InlineSiteBakeResult); + ProfScope("file paths") out_results->file_paths = *ts_join_struct(bake_file_paths_ticket, max_U64, RDIM_FilePathBakeResult); + ProfScope("strings") out_results->strings = *ts_join_struct(bake_strings_ticket, max_U64, RDIM_StringBakeResult); + ProfScope("type nodes") out_results->type_nodes = *ts_join_struct(bake_type_nodes_ticket, max_U64, RDIM_TypeNodeBakeResult); + ProfScope("idx runs") out_results->idx_runs = *ts_join_struct(bake_idx_runs_ticket, max_U64, RDIM_IndexRunBakeResult); + ProfScope("line tables") out_results->line_tables = *ts_join_struct(bake_line_tables_ticket, max_U64, RDIM_LineTableBakeResult); - //- rjf: join top-level units info - ProfScope("top-level units info") + ////////////////////////////// + //- rjf: join individual name map bakes + // + RDIM_NameMapBakeResult name_map_bakes[RDI_NameMapKind_COUNT] = {0}; + ProfScope("name maps") { - RDIM_BakeSectionList *s = ts_join_struct(bake_units_top_level_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join unit vmap - ProfScope("unit vmap") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_unit_vmap_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join source files - ProfScope("source files") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_src_files_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join UDTs - ProfScope("UDTs") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_udts_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join global variables - ProfScope("global variables") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_global_variables_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join global vmap - ProfScope("global vmap") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_global_vmap_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join thread variables - ProfScope("thread variables") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_thread_variables_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join procedures - ProfScope("procedures") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_procedures_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join scopes - ProfScope("scopes") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_scopes_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join scope vmap - ProfScope("scope vmap") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_scope_vmap_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join file paths - ProfScope("file paths") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_file_paths_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join strings - ProfScope("strings") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_strings_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join type nodes - ProfScope("type nodes") - { - RDIM_BakeSectionList *s = ts_join_struct(bake_type_nodes_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); - } - - //- rjf: join name maps - ProfScope("name map") - { - for(TS_TicketNode *n = bake_name_maps_tickets.first; n != 0; n = n->next) + for(EachNonZeroEnumVal(RDI_NameMapKind, k)) { - RDIM_BakeSectionList *s = ts_join_struct(n->v, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); + RDIM_NameMapBakeResult *bake = ts_join_struct(bake_name_maps_tickets[k], max_U64, RDIM_NameMapBakeResult); + if(bake != 0) + { + name_map_bakes[k] = *bake; + } } } - //- rjf: join index runs - ProfScope("idx runs") + ////////////////////////////// + //- rjf: join all individual name map bakes + // + ProfScope("join all name map bakes into final name map bake") { - RDIM_BakeSectionList *s = ts_join_struct(bake_idx_runs_ticket, max_U64, RDIM_BakeSectionList); - rdim_bake_section_list_concat_in_place(§ions, s); + out_results->name_maps = rdim_name_map_bake_results_combine(arena, name_map_bakes, ArrayCount(name_map_bakes)); } - //- rjf: join per-unit bakes - ProfScope("units") - { - 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); - } - } - - //- rjf: fill & return - P2R_Bake2Serialize *out = push_array(arena, P2R_Bake2Serialize, 1); - out->sections = sections; scratch_end(scratch); return out; } @@ -4285,11 +4827,10 @@ p2r_bake(Arena *arena, P2R_Convert2Bake *in) //////////////////////////////// //~ rjf: Top-Level Compression Entry Point -internal P2R_Bake2Serialize * -p2r_compress(Arena *arena, P2R_Bake2Serialize *in) +internal P2R_Serialize2File * +p2r_compress(Arena *arena, P2R_Serialize2File *in) { - RDIM_BakeSectionList prepack_sections = in->sections; - RDIM_BakeSectionList postpack_sections = {0}; + P2R_Serialize2File *out = push_array(arena, P2R_Serialize2File, 1); { //- rjf: set up compression context rr_lzb_simple_context ctx = {0}; @@ -4297,18 +4838,11 @@ p2r_compress(Arena *arena, P2R_Bake2Serialize *in) ctx.m_hashTable = push_array(arena, U16, 1<next) + for(EachEnumVal(RDI_SectionKind, k)) { - RDIM_BakeSection *src = &src_n->v; - - // rjf: push new section - RDIM_BakeSection *dst = rdim_bake_section_list_push(arena, &postpack_sections); - - // rjf: unpack uncompressed section info - void *data = src->data; - RDI_DataSectionEncoding encoding = src->encoding; - RDI_U64 encoded_size = src->encoded_size; - RDI_U64 unpacked_size = src->unpacked_size; + RDIM_SerializedSection *src = &in->bundle.sections[k]; + RDIM_SerializedSection *dst = &out->bundle.sections[k]; + MemoryCopyStruct(dst, src); // rjf: determine if this section should be compressed B32 should_compress = 1; @@ -4317,22 +4851,12 @@ p2r_compress(Arena *arena, P2R_Bake2Serialize *in) if(should_compress) { MemoryZero(ctx.m_hashTable, sizeof(U16)*(1<data = push_array_no_zero(arena, U8, src->encoded_size); + dst->encoded_size = rr_lzb_simple_encode_veryfast(&ctx, src->data, src->encoded_size, dst->data); + dst->unpacked_size = src->encoded_size; + dst->encoding = RDI_SectionEncoding_LZB; } - - // rjf: fill - dst->data = data; - dst->encoding = encoding; - dst->encoded_size = encoded_size; - dst->unpacked_size = unpacked_size; - dst->tag = src->tag; - dst->tag_idx = src->tag_idx; } } - P2R_Bake2Serialize *out = push_array(arena, P2R_Bake2Serialize, 1); - out->sections = postpack_sections; return out; } diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index 27b9ff39..a0a78db5 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -55,7 +55,13 @@ struct P2R_Convert2Bake typedef struct P2R_Bake2Serialize P2R_Bake2Serialize; struct P2R_Bake2Serialize { - RDIM_BakeSectionList sections; + RDIM_BakeResults bake_results; +}; + +typedef struct P2R_Serialize2File P2R_Serialize2File; +struct P2R_Serialize2File +{ + RDIM_SerializedSectionBundle bundle; }; //////////////////////////////// @@ -167,6 +173,8 @@ struct P2R_SrcFileMap typedef struct P2R_UnitConvertIn P2R_UnitConvertIn; struct P2R_UnitConvertIn { + PDB_Strtbl *pdb_strtbl; + PDB_CoffSectionArray *coff_sections; PDB_CompUnitArray *comp_units; PDB_CompUnitContributionArray *comp_unit_contributions; CV_SymParsed **comp_unit_syms; @@ -178,6 +186,8 @@ struct P2R_UnitConvertOut { RDIM_UnitChunkList units; RDIM_SrcFileChunkList src_files; + RDIM_LineTableChunkList line_tables; + RDIM_LineTable **units_first_inline_site_line_tables; }; //- rjf: link name map building tasks @@ -242,12 +252,14 @@ struct P2R_SymbolStreamConvertIn PDB_CoffSectionArray *coff_sections; PDB_TpiHashParsed *tpi_hash; CV_LeafParsed *tpi_leaf; + CV_LeafParsed *ipi_leaf; CV_SymParsed *sym; U64 sym_ranges_first; U64 sym_ranges_opl; CV_TypeId *itype_fwd_map; RDIM_Type **itype_type_ptrs; P2R_LinkNameMap *link_name_map; + RDIM_LineTable *first_inline_site_line_table; }; typedef struct P2R_SymbolStreamConvertOut P2R_SymbolStreamConvertOut; @@ -257,11 +269,20 @@ struct P2R_SymbolStreamConvertOut RDIM_SymbolChunkList global_variables; RDIM_SymbolChunkList thread_variables; RDIM_ScopeChunkList scopes; + RDIM_InlineSiteChunkList inline_sites; }; //////////////////////////////// //~ rjf: Baking Task Types +//- rjf: line table baking task types + +typedef struct P2R_BakeLineTablesIn P2R_BakeLineTablesIn; +struct P2R_BakeLineTablesIn +{ + RDIM_LineTableChunkList *line_tables; +}; + //- rjf: string map baking task types typedef struct P2R_BakeSrcFilesStringsIn P2R_BakeSrcFilesStringsIn; @@ -390,24 +411,18 @@ struct P2R_BuildBakeNameMapIn //- rjf: debug info baking task types -typedef struct P2R_BakeUnitsTopLevelIn P2R_BakeUnitsTopLevelIn; -struct P2R_BakeUnitsTopLevelIn +typedef struct P2R_BakeUnitsIn P2R_BakeUnitsIn; +struct P2R_BakeUnitsIn { RDIM_BakeStringMapTight *strings; RDIM_BakePathTree *path_tree; - RDIM_BakeParams *params; -}; - -typedef struct P2R_BakeUnitIn P2R_BakeUnitIn; -struct P2R_BakeUnitIn -{ - RDIM_Unit *unit; + RDIM_UnitChunkList *units; }; typedef struct P2R_BakeUnitVMapIn P2R_BakeUnitVMapIn; struct P2R_BakeUnitVMapIn { - RDIM_BakeParams *params; + RDIM_UnitChunkList *units; }; typedef struct P2R_BakeSrcFilesIn P2R_BakeSrcFilesIn; @@ -415,54 +430,61 @@ struct P2R_BakeSrcFilesIn { RDIM_BakeStringMapTight *strings; RDIM_BakePathTree *path_tree; - RDIM_BakeParams *params; + RDIM_SrcFileChunkList *src_files; }; typedef struct P2R_BakeUDTsIn P2R_BakeUDTsIn; struct P2R_BakeUDTsIn { RDIM_BakeStringMapTight *strings; - RDIM_BakeParams *params; + RDIM_UDTChunkList *udts; }; typedef struct P2R_BakeGlobalVariablesIn P2R_BakeGlobalVariablesIn; struct P2R_BakeGlobalVariablesIn { RDIM_BakeStringMapTight *strings; - RDIM_BakeParams *params; + RDIM_SymbolChunkList *global_variables; }; typedef struct P2R_BakeGlobalVMapIn P2R_BakeGlobalVMapIn; struct P2R_BakeGlobalVMapIn { - RDIM_BakeParams *params; + RDIM_SymbolChunkList *global_variables; }; typedef struct P2R_BakeThreadVariablesIn P2R_BakeThreadVariablesIn; struct P2R_BakeThreadVariablesIn { RDIM_BakeStringMapTight *strings; - RDIM_BakeParams *params; + RDIM_SymbolChunkList *thread_variables; }; typedef struct P2R_BakeProceduresIn P2R_BakeProceduresIn; struct P2R_BakeProceduresIn { RDIM_BakeStringMapTight *strings; - RDIM_BakeParams *params; + RDIM_SymbolChunkList *procedures; }; typedef struct P2R_BakeScopesIn P2R_BakeScopesIn; struct P2R_BakeScopesIn { RDIM_BakeStringMapTight *strings; - RDIM_BakeParams *params; + RDIM_ScopeChunkList *scopes; }; typedef struct P2R_BakeScopeVMapIn P2R_BakeScopeVMapIn; struct P2R_BakeScopeVMapIn { - RDIM_BakeParams *params; + RDIM_ScopeChunkList *scopes; +}; + +typedef struct P2R_BakeInlineSitesIn P2R_BakeInlineSitesIn; +struct P2R_BakeInlineSitesIn +{ + RDIM_BakeStringMapTight *strings; + RDIM_InlineSiteChunkList *inline_sites; }; typedef struct P2R_BakeFilePathsIn P2R_BakeFilePathsIn; @@ -483,7 +505,7 @@ struct P2R_BakeTypeNodesIn { RDIM_BakeStringMapTight *strings; RDIM_BakeIdxRunMap *idx_runs; - RDIM_BakeParams *params; + RDIM_TypeChunkList *types; }; typedef struct P2R_BakeNameMapIn P2R_BakeNameMapIn; @@ -491,9 +513,8 @@ struct P2R_BakeNameMapIn { RDIM_BakeStringMapTight *strings; RDIM_BakeIdxRunMap *idx_runs; - RDIM_BakeParams *params; - RDI_NameMapKind kind; RDIM_BakeNameMap *map; + RDI_NameMapKind kind; }; typedef struct P2R_BakeIdxRunsIn P2R_BakeIdxRunsIn; @@ -586,6 +607,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 +619,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); @@ -624,6 +645,6 @@ internal P2R_Bake2Serialize *p2r_bake(Arena *arena, P2R_Convert2Bake *in); //////////////////////////////// //~ rjf: Top-Level Compression Entry Point -internal P2R_Bake2Serialize *p2r_compress(Arena *arena, P2R_Bake2Serialize *in); +internal P2R_Serialize2File *p2r_compress(Arena *arena, P2R_Serialize2File *in); #endif // RDI_FROM_PDB_H diff --git a/src/rdi_from_pdb/rdi_from_pdb_main.c b/src/rdi_from_pdb/rdi_from_pdb_main.c index e3c72c9a..50fd0a88 100644 --- a/src/rdi_from_pdb/rdi_from_pdb_main.c +++ b/src/rdi_from_pdb/rdi_from_pdb_main.c @@ -98,22 +98,31 @@ entry_point(CmdLine *cmdline) bake2srlz = p2r_bake(arena, convert2bake); } + //- rjf: serialize + P2R_Serialize2File *srlz2file = 0; + ProfScope("serialize") + { + srlz2file = push_array(arena, P2R_Serialize2File, 1); + srlz2file->bundle = rdim_serialized_section_bundle_from_bake_results(&bake2srlz->bake_results); + } + //- rjf: compress - P2R_Bake2Serialize *bake2srlz_compressed = bake2srlz; + P2R_Serialize2File *srlz2file_compressed = srlz2file; if(cmd_line_has_flag(cmdline, str8_lit("compress"))) ProfScope("compress") { - bake2srlz_compressed = p2r_compress(arena, bake2srlz); + srlz2file_compressed = push_array(arena, P2R_Serialize2File, 1); + srlz2file_compressed = p2r_compress(arena, srlz2file); } //- rjf: serialize - String8List serialize_out = rdim_serialized_strings_from_params_bake_section_list(arena, &convert2bake->bake_params, &bake2srlz_compressed->sections); + String8List blobs = rdim_file_blobs_from_section_bundle(arena, &srlz2file_compressed->bundle); //- rjf: write ProfScope("write") { OS_Handle output_file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Write, user2convert->output_name); U64 off = 0; - for(String8Node *n = serialize_out.first; n != 0; n = n->next) + for(String8Node *n = blobs.first; n != 0; n = n->next) { os_file_write(output_file, r1u64(off, off+n->string.size), n->string.str); off += n->string.size; diff --git a/src/scratch/ryan_scratch.c b/src/scratch/ryan_scratch.c index 1087cf13..ad4b4c8c 100644 --- a/src/scratch/ryan_scratch.c +++ b/src/scratch/ryan_scratch.c @@ -4,10 +4,6 @@ //////////////////////////////// //~ rjf: Build Options -#define BUILD_VERSION_MAJOR 0 -#define BUILD_VERSION_MINOR 9 -#define BUILD_VERSION_PATCH 10 -#define BUILD_RELEASE_PHASE_STRING_LITERAL "ALPHA" #define BUILD_TITLE "ryan_scratch" #define BUILD_CONSOLE_INTERFACE 1 @@ -16,65 +12,33 @@ //- rjf: [lib] #include "lib_rdi_format/rdi_format.h" -#include "lib_rdi_format/rdi_format_parse.h" #include "lib_rdi_format/rdi_format.c" -#include "lib_rdi_format/rdi_format_parse.c" +#include "third_party/rad_lzb_simple/rad_lzb_simple.h" +#include "third_party/rad_lzb_simple/rad_lzb_simple.c" //- rjf: [h] #include "base/base_inc.h" #include "os/os_inc.h" #include "task_system/task_system.h" -#include "rdi_make_local/rdi_make_local.h" -#include "mdesk/mdesk.h" -#include "hash_store/hash_store.h" -#include "file_stream/file_stream.h" -#include "text_cache/text_cache.h" -#include "path/path.h" -#include "txti/txti.h" +#include "rdi_make/rdi_make_local.h" #include "coff/coff.h" -#include "pe/pe.h" #include "codeview/codeview.h" #include "codeview/codeview_stringize.h" #include "msf/msf.h" #include "pdb/pdb.h" #include "pdb/pdb_stringize.h" -#include "rdi_from_pdb/rdi_from_pdb.h" -#include "regs/regs.h" -#include "regs/rdi/regs_rdi.h" -#include "type_graph/type_graph.h" -#include "dbgi/dbgi.h" -#include "demon/demon_inc.h" -#include "eval/eval_inc.h" -#include "unwind/unwind.h" -#include "ctrl/ctrl_inc.h" //- rjf: [c] #include "base/base_inc.c" #include "os/os_inc.c" #include "task_system/task_system.c" -#include "rdi_make_local/rdi_make_local.c" -#include "mdesk/mdesk.c" -#include "hash_store/hash_store.c" -#include "file_stream/file_stream.c" -#include "text_cache/text_cache.c" -#include "path/path.c" -#include "txti/txti.c" +#include "rdi_make/rdi_make_local.c" #include "coff/coff.c" -#include "pe/pe.c" #include "codeview/codeview.c" #include "codeview/codeview_stringize.c" #include "msf/msf.c" #include "pdb/pdb.c" #include "pdb/pdb_stringize.c" -#include "rdi_from_pdb/rdi_from_pdb.c" -#include "regs/regs.c" -#include "regs/rdi/regs_rdi.c" -#include "type_graph/type_graph.c" -#include "dbgi/dbgi.c" -#include "demon/demon_inc.c" -#include "eval/eval_inc.c" -#include "unwind/unwind.c" -#include "ctrl/ctrl_inc.c" //////////////////////////////// //~ rjf: Entry Point @@ -82,5 +46,13 @@ internal void entry_point(CmdLine *cmdline) { - + Arena *arena = arena_alloc(); + RDIM_SortKey keys_unsorted[] = {{1, (void *)2}, {2}, {3}, {1, (void *)1}, {2}, {3}, {1, (void *)3}, {2}, {3}, {1, (void *)4}, {2}, {3}, {1, (void *)5}, {2}, {3}}; + U64 keys_count = ArrayCount(keys_unsorted); + RDIM_SortKey *keys_sorted = rdim_sort_key_array(arena, keys_unsorted, keys_count); + for(U64 idx = 0; idx < keys_count; idx += 1) + { + printf("%I64u (%I64u),", keys_sorted[idx].key, (U64)keys_sorted[idx].val); + } + printf("\n"); } diff --git a/src/task_system/task_system.c b/src/task_system/task_system.c index 98571094..15c38a0a 100644 --- a/src/task_system/task_system.c +++ b/src/task_system/task_system.c @@ -64,7 +64,9 @@ 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 + ProfBeginFunction(); + + // rjf: obtain number & slot/stripe for next artifact U64 artifact_num = ins_atomic_u64_inc_eval(&ts_shared->artifact_num_gen); U64 slot_idx = artifact_num%ts_shared->artifact_slots_count; U64 stripe_idx = slot_idx%ts_shared->artifact_stripes_count; @@ -73,51 +75,58 @@ ts_kickoff(TS_TaskFunctionType *entry_point, Arena **optional_arena_ptr, void *p // rjf: allocate artifact TS_TaskArtifact *artifact = 0; - OS_MutexScopeW(stripe->rw_mutex) + ProfScope("allocate artifact") { - artifact = stripe->free_artifact; - if(artifact != 0) + OS_MutexScopeW(stripe->rw_mutex) { - SLLStackPop(stripe->free_artifact); + artifact = stripe->free_artifact; + if(artifact != 0) + { + SLLStackPop(stripe->free_artifact); + } + else + { + artifact = push_array_no_zero(stripe->arena, TS_TaskArtifact, 1); + } + artifact->num = artifact_num; + artifact->task_is_done = 0; + artifact->result = 0; } - else - { - artifact = push_array_no_zero(stripe->arena, TS_TaskArtifact, 1); - } - artifact->num = artifact_num; - artifact->task_is_done = 0; - artifact->result = 0; } // rjf: form ticket out of artifact info TS_Ticket ticket = {artifact_num, (U64)artifact}; // rjf: push task info to task ring buffer - OS_MutexScope(ts_shared->u2t_ring_mutex) for(;;) + ProfScope("push task info to task ring buffer") { - U64 unconsumed_size = ts_shared->u2t_ring_write_pos - ts_shared->u2t_ring_read_pos; - U64 available_size = ts_shared->u2t_ring_size-unconsumed_size; - if(available_size >= sizeof(entry_point) + sizeof(p) + sizeof(ticket)) + OS_MutexScope(ts_shared->u2t_ring_mutex) for(;;) { - Arena *task_arena = 0; - if(optional_arena_ptr != 0) + U64 unconsumed_size = ts_shared->u2t_ring_write_pos - ts_shared->u2t_ring_read_pos; + U64 available_size = ts_shared->u2t_ring_size-unconsumed_size; + if(available_size >= sizeof(entry_point) + sizeof(p) + sizeof(ticket)) { - task_arena = *optional_arena_ptr; + Arena *task_arena = 0; + if(optional_arena_ptr != 0) + { + task_arena = *optional_arena_ptr; + } + ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &entry_point); + ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &task_arena); + ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &p); + ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &ticket); + if(optional_arena_ptr != 0) + { + *optional_arena_ptr = 0; + } + break; } - ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &entry_point); - ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &task_arena); - ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &p); - ts_shared->u2t_ring_write_pos += ring_write_struct(ts_shared->u2t_ring_base, ts_shared->u2t_ring_size, ts_shared->u2t_ring_write_pos, &ticket); - if(optional_arena_ptr != 0) - { - *optional_arena_ptr = 0; - } - break; + os_condition_variable_wait(ts_shared->u2t_ring_cv, ts_shared->u2t_ring_mutex, max_U64); } - os_condition_variable_wait(ts_shared->u2t_ring_cv, ts_shared->u2t_ring_mutex, max_U64); + os_condition_variable_signal(ts_shared->u2t_ring_cv); } - os_condition_variable_broadcast(ts_shared->u2t_ring_cv); + ProfEnd(); return ticket; } diff --git a/src/type_graph/type_graph.c b/src/type_graph/type_graph.c index 4a9af695..fbf96b33 100644 --- a/src/type_graph/type_graph.c +++ b/src/type_graph/type_graph.c @@ -336,9 +336,9 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke case TG_KeyKind_Ext: { U64 type_node_idx = key.u64[0]; - if(0 <= type_node_idx && type_node_idx < rdi->type_nodes_count) + RDI_TypeNode *rdi_type = rdi_element_from_name_idx(rdi, TypeNodes, type_node_idx); + if(rdi_type->kind != RDI_TypeKind_NULL) { - RDI_TypeNode *rdi_type = &rdi->type_nodes[type_node_idx]; TG_Kind kind = tg_kind_from_rdi_type_kind(rdi_type->kind); //- rjf: record types => unpack name * members & produce @@ -349,7 +349,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size); // rjf: unpack UDT info - RDI_UDT *udt = rdi_element_from_idx(rdi, udts, rdi_type->user_defined.udt_idx); + RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, rdi_type->user_defined.udt_idx); // rjf: unpack members TG_Member *members = 0; @@ -357,19 +357,16 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke { members_count = udt->member_count; members = push_array(arena, TG_Member, members_count); - if(members_count != 0 && 0 <= udt->member_first && udt->member_first+udt->member_count <= rdi->members_count) + if(members_count != 0) { for(U32 member_idx = udt->member_first; member_idx < udt->member_first+udt->member_count; member_idx += 1) { - RDI_Member *src = &rdi->members[member_idx]; + RDI_Member *src = rdi_element_from_name_idx(rdi, Members, member_idx); TG_Kind member_type_kind = TG_Kind_Null; - if(src->type_idx < rdi->type_nodes_count) - { - RDI_TypeNode *member_type = &rdi->type_nodes[src->type_idx]; - member_type_kind = tg_kind_from_rdi_type_kind(member_type->kind); - } + RDI_TypeNode *member_type = rdi_element_from_name_idx(rdi, TypeNodes, src->type_idx); + member_type_kind = tg_kind_from_rdi_type_kind(member_type->kind); TG_Member *dst = &members[member_idx-udt->member_first]; dst->kind = tg_member_kind_from_rdi_member_kind(src->kind); dst->type_key = tg_key_ext(member_type_kind, (U64)src->type_idx); @@ -399,7 +396,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke TG_Key direct_type_key = zero_struct; if(rdi_type->user_defined.direct_type_idx < type_node_idx) { - RDI_TypeNode *direct_type_node = &rdi->type_nodes[rdi_type->user_defined.direct_type_idx]; + RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->user_defined.direct_type_idx); TG_Kind direct_type_kind = tg_kind_from_rdi_type_kind(direct_type_node->kind); direct_type_key = tg_key_ext(direct_type_kind, (U64)rdi_type->user_defined.direct_type_idx); } @@ -409,23 +406,17 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke U32 enum_vals_count = 0; { U32 udt_idx = rdi_type->user_defined.udt_idx; - if(0 <= udt_idx && udt_idx < rdi->udts_count) + RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, udt_idx); + enum_vals_count = udt->member_count; + enum_vals = push_array(arena, TG_EnumVal, enum_vals_count); + for(U32 member_idx = udt->member_first; + member_idx < udt->member_first+udt->member_count; + member_idx += 1) { - RDI_UDT *udt = &rdi->udts[udt_idx]; - enum_vals_count = udt->member_count; - enum_vals = push_array(arena, TG_EnumVal, enum_vals_count); - if(0 <= udt->member_first && udt->member_first+udt->member_count < rdi->enum_members_count) - { - for(U32 member_idx = udt->member_first; - member_idx < udt->member_first+udt->member_count; - member_idx += 1) - { - RDI_EnumMember *src = &rdi->enum_members[member_idx]; - TG_EnumVal *dst = &enum_vals[member_idx-udt->member_first]; - dst->name.str = rdi_string_from_idx(rdi, src->name_string_idx, &dst->name.size); - dst->val = src->val; - } - } + RDI_EnumMember *src = rdi_element_from_name_idx(rdi, EnumMembers, member_idx); + TG_EnumVal *dst = &enum_vals[member_idx-udt->member_first]; + dst->name.str = rdi_string_from_idx(rdi, src->name_string_idx, &dst->name.size); + dst->val = src->val; } } @@ -448,7 +439,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke U64 direct_type_byte_size = 0; if(rdi_type->constructed.direct_type_idx < type_node_idx) { - RDI_TypeNode *direct_type_node = &rdi->type_nodes[rdi_type->constructed.direct_type_idx]; + RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->constructed.direct_type_idx); TG_Kind direct_type_kind = tg_kind_from_rdi_type_kind(direct_type_node->kind); direct_type_key = tg_key_ext(direct_type_kind, (U64)rdi_type->constructed.direct_type_idx); direct_type_is_good = 1; @@ -512,7 +503,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke U32 param_type_idx = idx_run[idx]; if(param_type_idx < type_node_idx) { - RDI_TypeNode *param_type_node = &rdi->type_nodes[param_type_idx]; + RDI_TypeNode *param_type_node = rdi_element_from_name_idx(rdi, TypeNodes, param_type_idx); TG_Kind param_kind = tg_kind_from_rdi_type_kind(param_type_node->kind); type->param_type_keys[idx] = tg_key_ext(param_kind, (U64)param_type_idx); } @@ -545,7 +536,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke U32 param_type_idx = idx_run[idx]; if(param_type_idx < type_node_idx) { - RDI_TypeNode *param_type_node = &rdi->type_nodes[param_type_idx]; + RDI_TypeNode *param_type_node = rdi_element_from_name_idx(rdi, TypeNodes, param_type_idx); TG_Kind param_kind = tg_kind_from_rdi_type_kind(param_type_node->kind); type->param_type_keys[idx] = tg_key_ext(param_kind, (U64)param_type_idx); } @@ -568,7 +559,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke TG_Key owner_type_key = zero_struct; if(rdi_type->constructed.owner_type_idx < type_node_idx) { - RDI_TypeNode *owner_type_node = &rdi->type_nodes[rdi_type->constructed.owner_type_idx]; + RDI_TypeNode *owner_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->constructed.owner_type_idx); TG_Kind owner_type_kind = tg_kind_from_rdi_type_kind(owner_type_node->kind); owner_type_key = tg_key_ext(owner_type_kind, (U64)rdi_type->constructed.owner_type_idx); } @@ -593,7 +584,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke U64 direct_type_byte_size = 0; if(rdi_type->user_defined.direct_type_idx < type_node_idx) { - RDI_TypeNode *direct_type_node = &rdi->type_nodes[rdi_type->user_defined.direct_type_idx]; + RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->user_defined.direct_type_idx); TG_Kind direct_type_kind = tg_kind_from_rdi_type_kind(direct_type_node->kind); direct_type_key = tg_key_ext(direct_type_kind, (U64)rdi_type->user_defined.direct_type_idx); direct_type_byte_size = direct_type_node->byte_size; @@ -615,7 +606,7 @@ tg_type_from_graph_rdi_key(Arena *arena, TG_Graph *graph, RDI_Parsed *rdi, TG_Ke U64 direct_type_byte_size = 0; if(rdi_type->bitfield.direct_type_idx < type_node_idx) { - RDI_TypeNode *direct_type_node = &rdi->type_nodes[rdi_type->bitfield.direct_type_idx]; + RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->bitfield.direct_type_idx); TG_Kind direct_type_kind = tg_kind_from_rdi_type_kind(direct_type_node->kind); direct_type_key = tg_key_ext(direct_type_kind, (U64)rdi_type->bitfield.direct_type_idx); direct_type_byte_size = direct_type_node->byte_size;