From a73cde28648d98ff1b9e4f71aeb0fedd7bfed9ba Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 7 Jun 2024 16:40:21 -0700 Subject: [PATCH] codeview c13 inlinee lines info parsing, lookup in inline site parsing path --- src/codeview/codeview.c | 589 ++++++++++++++++-------------- src/codeview/codeview.h | 180 ++++----- src/codeview/codeview_stringize.c | 12 +- src/codeview/codeview_stringize.h | 2 +- src/rdi_from_pdb/rdi_from_pdb.c | 111 +++--- src/rdi_from_pdb/rdi_from_pdb.h | 1 + 6 files changed, 489 insertions(+), 406 deletions(-) diff --git a/src/codeview/codeview.c b/src/codeview/codeview.c index 5e3d5e6c..1919ad64 100644 --- a/src/codeview/codeview.c +++ b/src/codeview/codeview.c @@ -7,21 +7,44 @@ #include "generated/codeview.meta.c" //////////////////////////////// -//~ CodeView Common Functions +//~ CodeView Common Decoding Helper Functions + +internal U64 +cv_hash_from_string(String8 string) +{ + U64 result = 5381; + for(U64 i = 0; i < string.size; i += 1) + { + result = ((result << 5) + result) + string.str[i]; + } + return result; +} + +internal U64 +cv_hash_from_item_id(CV_ItemId item_id) +{ + U64 result = cv_hash_from_string(str8_struct(&item_id)); + return result; +} internal CV_NumericParsed -cv_numeric_from_data_range(U8 *first, U8 *opl){ +cv_numeric_from_data_range(U8 *first, U8 *opl) +{ CV_NumericParsed result = {0}; - if (first + 2 <= opl){ + if(first + 2 <= opl) + { U16 x = *(U16*)first; - if (x < 0x8000){ + if(x < 0x8000) + { result.kind = CV_NumericKind_USHORT; result.val = first; result.encoded_size = 2; } - else{ + else + { U64 val_size = 0; - switch (x){ + switch(x) + { case CV_NumericKind_CHAR: val_size = 1; break; case CV_NumericKind_SHORT: case CV_NumericKind_USHORT: val_size = 2; break; @@ -46,21 +69,23 @@ cv_numeric_from_data_range(U8 *first, U8 *opl){ case CV_NumericKind_UTF8STRING:val_size = 0; break; // TODO: ??? case CV_NumericKind_FLOAT16: val_size = 2; break; } - - if (first + 2 + val_size <= opl){ + if(first + 2 + val_size <= opl) + { result.kind = x; result.val = (first + 2); result.encoded_size = 2 + val_size; } } } - return(result); + return result; } internal B32 -cv_numeric_fits_in_u64(CV_NumericParsed *num){ +cv_numeric_fits_in_u64(CV_NumericParsed *num) +{ B32 result = 0; - switch (num->kind){ + switch(num->kind) + { case CV_NumericKind_USHORT: case CV_NumericKind_ULONG: case CV_NumericKind_UQUADWORD: @@ -68,13 +93,15 @@ cv_numeric_fits_in_u64(CV_NumericParsed *num){ result = 1; }break; } - return(result); + return result; } internal B32 -cv_numeric_fits_in_s64(CV_NumericParsed *num){ +cv_numeric_fits_in_s64(CV_NumericParsed *num) +{ B32 result = 0; - switch (num->kind){ + switch(num->kind) + { case CV_NumericKind_CHAR: case CV_NumericKind_SHORT: case CV_NumericKind_LONG: @@ -83,91 +110,63 @@ cv_numeric_fits_in_s64(CV_NumericParsed *num){ result = 1; }break; } - return(result); + return result; } internal B32 -cv_numeric_fits_in_f64(CV_NumericParsed *num){ +cv_numeric_fits_in_f64(CV_NumericParsed *num) +{ B32 result = 0; - switch (num->kind){ + switch(num->kind) + { case CV_NumericKind_FLOAT32: case CV_NumericKind_FLOAT64: { result = 1; }break; } - return(result); + return result; } internal U64 -cv_u64_from_numeric(CV_NumericParsed *num){ +cv_u64_from_numeric(CV_NumericParsed *num) +{ U64 result = 0; - switch (num->kind){ - case CV_NumericKind_USHORT: - { - result = *(U16*)num->val; - }break; - - case CV_NumericKind_ULONG: - { - result = *(U32*)num->val; - }break; - - case CV_NumericKind_UQUADWORD: - { - result = *(U64*)num->val; - }break; + switch(num->kind) + { + case CV_NumericKind_USHORT: {result = *(U16*)num->val;}break; + case CV_NumericKind_ULONG: {result = *(U32*)num->val;}break; + case CV_NumericKind_UQUADWORD:{result = *(U64*)num->val;}break; } - return(result); + return result; } internal S64 -cv_s64_from_numeric(CV_NumericParsed *num){ +cv_s64_from_numeric(CV_NumericParsed *num) +{ S64 result = 0; - switch (num->kind){ - case CV_NumericKind_CHAR: - { - result = *(S8*)num->val; - }break; - - case CV_NumericKind_SHORT: - { - result = *(S16*)num->val; - }break; - - case CV_NumericKind_LONG: - { - result = *(S32*)num->val; - }break; - - case CV_NumericKind_QUADWORD: - { - result = *(S64*)num->val; - }break; + switch(num->kind) + { + case CV_NumericKind_CHAR: {result = *(S8*)num->val;}break; + case CV_NumericKind_SHORT: {result = *(S16*)num->val;}break; + case CV_NumericKind_LONG: {result = *(S32*)num->val;}break; + case CV_NumericKind_QUADWORD: {result = *(S64*)num->val;}break; } return(result); } internal F64 -cv_f64_from_numeric(CV_NumericParsed *num){ +cv_f64_from_numeric(CV_NumericParsed *num) +{ F64 result = 0; - switch (num->kind){ - case CV_NumericKind_FLOAT32: - { - result = *(F32*)num->val; - }break; - - case CV_NumericKind_FLOAT64: - { - result = *(F64*)num->val; - }break; + switch(num->kind) + { + case CV_NumericKind_FLOAT32:{result = *(F32*)num->val;}break; + case CV_NumericKind_FLOAT64:{result = *(F64*)num->val;}break; } return(result); } -//////////////////////////////// -//~ Inline Binary Annotation Helpers - internal U64 cv_decode_inline_annot_u32(String8 data, U64 offset, U32 *out_value) { @@ -239,27 +238,27 @@ cv_decode_inline_annot_s32(String8 data, U64 offset, S32 *out_value) } //////////////////////////////// -//~ CodeView Sym Parser Functions +//~ CodeView Parsing Functions -//- the first pass parser +//- rjf: record range stream parsing internal CV_RecRangeStream* -cv_rec_range_stream_from_data(Arena *arena, String8 sym_data, U64 sym_align){ +cv_rec_range_stream_from_data(Arena *arena, String8 sym_data, U64 sym_align) +{ Assert(1 <= sym_align && IsPow2OrZero(sym_align)); - CV_RecRangeStream *result = push_array(arena, CV_RecRangeStream, 1); - U8 *data = sym_data.str; U64 cursor = 0; U64 cap = sym_data.size; - for (;cursor + sizeof(CV_RecHeader) <= cap;){ + for(;cursor + sizeof(CV_RecHeader) <= cap;) + { // setup a new chunk arena_push_align(arena, 64); - CV_RecRangeChunk *cur_chunk = cv_rec_range_stream_push_chunk(arena, result); - + CV_RecRangeChunk *cur_chunk = push_array_no_zero(arena, CV_RecRangeChunk, 1); + SLLQueuePush(result->first_chunk, result->last_chunk, cur_chunk); U64 partial_count = 0; - for (;partial_count < CV_REC_RANGE_CHUNK_SIZE && cursor + sizeof(CV_RecHeader) <= cap; - partial_count += 1){ + for(;partial_count < CV_REC_RANGE_CHUNK_SIZE && cursor + sizeof(CV_RecHeader) <= cap; partial_count += 1) + { // compute cap CV_RecHeader *hdr = (CV_RecHeader*)(data + cursor); U64 symbol_cap_unclamped = cursor + 2 + hdr->size; @@ -273,110 +272,110 @@ cv_rec_range_stream_from_data(Arena *arena, String8 sym_data, U64 sym_align){ U32 next_pos = AlignPow2(symbol_cap, sym_align); cursor = next_pos; } - result->total_count += partial_count; } - - return(result); + return result; } -//- sym +internal CV_RecRangeArray +cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream) +{ + U64 total_count = stream->total_count; + CV_RecRange *ranges = push_array_no_zero(arena, CV_RecRange, total_count); + U64 idx = 0; + for(CV_RecRangeChunk *chunk = stream->first_chunk; chunk != 0; chunk = chunk->next) + { + U64 copy_count_raw = total_count - idx; + U64 copy_count = ClampTop(copy_count_raw, CV_REC_RANGE_CHUNK_SIZE); + MemoryCopy(ranges + idx, chunk->ranges, copy_count*sizeof(CV_RecRange)); + idx += copy_count; + } + CV_RecRangeArray result = {0}; + result.ranges = ranges; + result.count = total_count; + return result; +} -internal CV_SymParsed* -cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align){ +//- rjf: sym stream parsing + +internal CV_SymParsed * +cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align) +{ Assert(1 <= sym_align && IsPow2OrZero(sym_align)); - ProfBegin("cv_sym_from_data"); - + ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); - // gather up symbols + //- rjf: gather symbols CV_RecRangeStream *stream = cv_rec_range_stream_from_data(scratch.arena, sym_data, sym_align); - // convert to result + //- rjf: convert to result, fill basics CV_SymParsed *result = push_array(arena, CV_SymParsed, 1); result->data = sym_data; result->sym_align = sym_align; result->sym_ranges = cv_rec_range_array_from_stream(arena, stream); - cv_sym_top_level_info_from_syms(arena, sym_data, &result->sym_ranges, &result->info); - scratch_end(scratch); - - ProfEnd(); - - return(result); -} - -internal void -cv_sym_top_level_info_from_syms(Arena *arena, String8 sym_data, - CV_RecRangeArray *ranges, - CV_SymTopLevelInfo *info_out){ - MemoryZeroStruct(info_out); - - CV_RecRange *range = ranges->ranges; - CV_RecRange *opl = range + ranges->count; - for (; range < opl; range += 1){ - U8 *first = sym_data.str + range->off + 2; - U64 cap = range->hdr.size - 2; - - switch (range->hdr.kind){ - case CV_SymKind_COMPILE: + //- rjf: extract top-level-info + { + CV_RecRange *range = result->sym_ranges.ranges; + CV_RecRange *opl = range + result->sym_ranges.count; + for(;range < opl; range += 1) + { + U8 *first = sym_data.str + range->off + 2; + U64 cap = range->hdr.size - 2; + switch(range->hdr.kind) { - if (sizeof(CV_SymCompile) <= cap){ + case CV_SymKind_COMPILE: + if(sizeof(CV_SymCompile) <= cap) + { CV_SymCompile *compile = (CV_SymCompile*)first; - String8 ver_str = str8_cstring_capped((char*)(compile + 1), (char *)(first + cap)); - - info_out->arch = compile->machine; - info_out->language = CV_CompileFlags_ExtractLanguage(compile->flags);; - info_out->compiler_name = ver_str; - } - }break; - - case CV_SymKind_COMPILE2: - { - if (sizeof(CV_SymCompile2) <= cap){ + result->info.arch = compile->machine; + result->info.language = CV_CompileFlags_ExtractLanguage(compile->flags);; + result->info.compiler_name = ver_str; + }break; + case CV_SymKind_COMPILE2: + if(sizeof(CV_SymCompile2) <= cap) + { CV_SymCompile2 *compile2 = (CV_SymCompile2*)first; - String8 ver_str = str8_cstring_capped((char*)(compile2 + 1), (char*)(first + cap)); String8 compiler_name = push_str8f(arena, "%.*s %u.%u.%u", str8_varg(ver_str), compile2->ver_major, compile2->ver_minor, compile2->ver_build); - - info_out->arch = compile2->machine; - info_out->language = CV_Compile2Flags_ExtractLanguage(compile2->flags);; - info_out->compiler_name = compiler_name; - } - }break; - - case CV_SymKind_COMPILE3: - { - if (sizeof(CV_SymCompile3) <= cap){ + result->info.arch = compile2->machine; + result->info.language = CV_Compile2Flags_ExtractLanguage(compile2->flags);; + result->info.compiler_name = compiler_name; + }break; + case CV_SymKind_COMPILE3: + if(sizeof(CV_SymCompile3) <= cap) + { CV_SymCompile3 *compile3 = (CV_SymCompile3*)first; - String8 ver_str = str8_cstring_capped((char*)(compile3 + 1), (char *)(first + cap)); String8 compiler_name = push_str8f(arena, "%.*s %u.%u.%u", str8_varg(ver_str), compile3->ver_major, compile3->ver_minor, compile3->ver_build); - - info_out->arch = compile3->machine; - info_out->language = CV_Compile3Flags_ExtractLanguage(compile3->flags);; - info_out->compiler_name = compiler_name; - } - }break; + result->info.arch = compile3->machine; + result->info.language = CV_Compile3Flags_ExtractLanguage(compile3->flags);; + result->info.compiler_name = compiler_name; + }break; + } } } + + scratch_end(scratch); + ProfEnd(); + return result; } -//- leaf +//- rjf: leaf stream parsing -internal CV_LeafParsed* -cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId itype_first){ - ProfBegin("cv_leaf_from_data"); - +internal CV_LeafParsed * +cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId itype_first) +{ + ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); // gather up symbols @@ -390,57 +389,31 @@ cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId itype_first){ result->leaf_ranges = cv_rec_range_array_from_stream(arena, stream); scratch_end(scratch); - ProfEnd(); - - return(result); -} - -//- range streams - -internal CV_RecRangeChunk* -cv_rec_range_stream_push_chunk(Arena *arena, CV_RecRangeStream *stream){ - CV_RecRangeChunk *result = push_array_no_zero(arena, CV_RecRangeChunk, 1); - SLLQueuePush(stream->first_chunk, stream->last_chunk, result); - return(result); -} - -internal CV_RecRangeArray -cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream){ - U64 total_count = stream->total_count; - CV_RecRange *ranges = push_array_no_zero(arena, CV_RecRange, total_count); - U64 idx = 0; - for (CV_RecRangeChunk *chunk = stream->first_chunk; - chunk != 0; - chunk = chunk->next){ - U64 copy_count_raw = total_count - idx; - U64 copy_count = ClampTop(copy_count_raw, CV_REC_RANGE_CHUNK_SIZE); - MemoryCopy(ranges + idx, chunk->ranges, copy_count*sizeof(CV_RecRange)); - idx += copy_count; - } - CV_RecRangeArray result = {0}; - result.ranges = ranges; - result.count = total_count; - return(result); + return result; } //////////////////////////////// //~ CodeView C13 Parser Functions -internal CV_C13Parsed* -cv_c13_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSectionArray *sections){ - ProfBegin("cv_c13_from_data"); +internal CV_C13Parsed * +cv_c13_parsed_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSectionArray *sections) +{ + ProfBeginFunction(); - // gather c13 data + ////////////////////////////// + //- rjf: gather c13 sub-sections + // CV_C13SubSectionNode *file_chksms = 0; CV_C13SubSectionNode *first = 0; CV_C13SubSectionNode *last = 0; U64 count = 0; { U32 cursor = 0; - for (; cursor + sizeof(CV_C13_SubSectionHeader) <= c13_data.size;){ + for(; cursor + sizeof(CV_C13SubSectionHeader) <= c13_data.size;) + { // read header - CV_C13_SubSectionHeader *hdr = (CV_C13_SubSectionHeader*)(c13_data.str + cursor); + CV_C13SubSectionHeader *hdr = (CV_C13SubSectionHeader*)(c13_data.str + cursor); // get sub section info U32 sub_section_off = cursor + sizeof(*hdr); @@ -450,15 +423,16 @@ cv_c13_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSec U32 sub_section_size = after_sub_section_off - sub_section_off; // emit sub section - if (!(hdr->kind & CV_C13_SubSectionKind_IgnoreFlag)){ + if(!(hdr->kind & CV_C13SubSectionKind_IgnoreFlag)) + { CV_C13SubSectionNode *node = push_array(arena, CV_C13SubSectionNode, 1); SLLQueuePush(first, last, node); count += 1; node->kind = hdr->kind; node->off = sub_section_off; node->size = sub_section_size; - - if (hdr->kind == CV_C13_SubSectionKind_FileChksms){ + if(hdr->kind == CV_C13SubSectionKind_FileChksms) + { file_chksms = node; } } @@ -468,112 +442,181 @@ cv_c13_from_data(Arena *arena, String8 c13_data, PDB_Strtbl *strtbl, PDB_CoffSec } } - // parse each section - for (CV_C13SubSectionNode *node = first; - node != 0; - node = node->next){ + ////////////////////////////// + //- rjf: parse each sub-section + // + U64 inlinee_lines_parsed_slots_count = 4096; + CV_C13InlineeLinesParsedNode **inlinee_lines_parsed_slots = push_array(arena, CV_C13InlineeLinesParsedNode *, inlinee_lines_parsed_slots_count); + for(CV_C13SubSectionNode *node = first; + node != 0; + node = node->next) + { U8 *first = c13_data.str + node->off; U32 cap = node->size; - - switch (node->kind){ - case CV_C13_SubSectionKind_Lines: + switch(node->kind) + { + default:{}break; + + ////////////////////////// + //- rjf: line info sub-section + // + case CV_C13SubSectionKind_Lines: + if(sizeof(CV_C13SubSecLinesHeader) <= cap) { // read header - if (sizeof(CV_C13_SubSecLinesHeader) <= cap){ - U32 read_off = 0; - U64 read_off_opl = node->size; - CV_C13_SubSecLinesHeader *hdr = (CV_C13_SubSecLinesHeader*)(first + read_off); + U32 read_off = 0; + U64 read_off_opl = node->size; + CV_C13SubSecLinesHeader *hdr = (CV_C13SubSecLinesHeader*)(first + read_off); + read_off += sizeof(*hdr); + + // extract top level info + U32 sec_idx = hdr->sec; + B32 has_cols = !!(hdr->flags & CV_C13SubSecLinesFlag_HasColumns); + U64 secrel_off = hdr->sec_off; + U64 secrel_opl = secrel_off + hdr->len; + U64 sec_base_off = sections->sections[sec_idx - 1].voff; + + // rjf: bad section index -> skip + if(sec_idx < 1 || sections->count < sec_idx) + { + continue; + } + + // read files + for(;read_off+sizeof(CV_C13File) <= read_off_opl;) + { + // rjf: grab next file header + CV_C13File *file = (CV_C13File*)(first + read_off); + U32 file_off = file->file_off; + U32 line_count_unclamped = file->num_lines; + U32 block_size = file->block_size; + + // file_name from file_off + String8 file_name = {0}; + if(file_off + sizeof(CV_C13Checksum) <= file_chksms->size) + { + CV_C13Checksum *checksum = (CV_C13Checksum*)(c13_data.str + file_chksms->off + file_off); + U32 name_off = checksum->name_off; + file_name = pdb_strtbl_string_from_off(strtbl, name_off); + } + + // array layouts + U32 line_item_size = sizeof(CV_C13Line); + if (has_cols){ + line_item_size += sizeof(CV_C13Column); + } + + U32 line_array_off = read_off + sizeof(*file); + U32 line_count_max = (read_off_opl - line_array_off) / line_item_size; + U32 line_count = ClampTop(line_count_unclamped, line_count_max); + + U32 col_array_off = line_array_off + line_count*sizeof(CV_C13Line); + + // parse lines + U64 *voffs = push_array_no_zero(arena, U64, line_count + 1); + U32 *line_nums = push_array_no_zero(arena, U32, line_count); + + { + CV_C13Line *line_ptr = (CV_C13Line*)(first + line_array_off); + CV_C13Line *line_opl = line_ptr + line_count; + + // TODO(allen): check order correctness here + + U32 i = 0; + for (; line_ptr < line_opl; line_ptr += 1, i += 1){ + voffs[i] = line_ptr->off + secrel_off + sec_base_off; + line_nums[i] = CV_C13LineFlags_ExtractLineNumber(line_ptr->flags); + } + voffs[i] = secrel_opl + sec_base_off; + } + + // emit parsed lines + CV_C13LinesParsedNode *lines_parsed_node = push_array(arena, CV_C13LinesParsedNode, 1); + CV_C13LinesParsed *lines_parsed = &lines_parsed_node->v; + lines_parsed->sec_idx = sec_idx; + lines_parsed->file_off = file_off; + lines_parsed->secrel_base_off = secrel_off; + lines_parsed->file_name = file_name; + lines_parsed->voffs = voffs; + lines_parsed->line_nums = line_nums; + lines_parsed->line_count = line_count; + SLLQueuePush(node->lines_first, node->lines_last, lines_parsed_node); + + // rjf: advance + read_off += sizeof(*file); + read_off += line_item_size*line_count; + } + }break; + + ////////////////////////// + //- rjf: inlinee line info sub-section + // + case CV_C13SubSectionKind_InlineeLines: + if(sizeof(CV_C13InlineeLinesSig) <= cap) + { + // rjf: read sig + U32 read_off = 0; + U64 read_off_opl = node->size; + CV_C13InlineeLinesSig *sig = (CV_C13InlineeLinesSig *)(first + read_off); + read_off += sizeof(*sig); + + // rjf: read source lines + for(;read_off + sizeof(CV_C13InlineeSourceLineHeader) <= read_off_opl;) + { + // rjf: read next header + CV_C13InlineeSourceLineHeader *hdr = (CV_C13InlineeSourceLineHeader *)(first + read_off); read_off += sizeof(*hdr); - // extract top level info - U32 sec_idx = hdr->sec; - B32 has_cols = !!(hdr->flags & CV_C13_SubSecLinesFlag_HasColumns); - U64 secrel_off = hdr->sec_off; - U64 secrel_opl = secrel_off + hdr->len; - U64 sec_base_off = sections->sections[sec_idx - 1].voff; - - // rjf: bad section index -> skip - if(sec_idx < 1 || sections->count < sec_idx) + // rjf: file_off -> file_name + String8 file_name = {0}; + if(hdr->file_off + sizeof(CV_C13Checksum) <= file_chksms->size) { - continue; + CV_C13Checksum *checksum = (CV_C13Checksum*)(c13_data.str + file_chksms->off + hdr->file_off); + U32 name_off = checksum->name_off; + file_name = pdb_strtbl_string_from_off(strtbl, name_off); } - // read files - for(;read_off+sizeof(CV_C13_File) <= read_off_opl;) + // rjf: parse extra files + U32 extra_file_count = 0; + U32 *extra_files = 0; + if(*sig == CV_C13InlineeLinesSig_EXTRA_FILES && read_off+sizeof(U32) <= read_off_opl) { - // rjf: grab next file header - CV_C13_File *file = (CV_C13_File*)(first + read_off); - U32 file_off = file->file_off; - U32 line_count_unclamped = file->num_lines; - U32 block_size = file->block_size; - - // file_name from file_off - String8 file_name = {0}; - if (file_off + sizeof(CV_C13_Checksum) <= file_chksms->size){ - CV_C13_Checksum *checksum = (CV_C13_Checksum*)(c13_data.str + file_chksms->off + file_off); - U32 name_off = checksum->name_off; - file_name = pdb_strtbl_string_from_off(strtbl, name_off); - } - - // array layouts - U32 line_item_size = sizeof(CV_C13_Line); - if (has_cols){ - line_item_size += sizeof(CV_C13_Column); - } - - U32 line_array_off = read_off + sizeof(*file); - U32 line_count_max = (read_off_opl - line_array_off) / line_item_size; - U32 line_count = ClampTop(line_count_unclamped, line_count_max); - - U32 col_array_off = line_array_off + line_count*sizeof(CV_C13_Line); - - // parse lines - U64 *voffs = push_array_no_zero(arena, U64, line_count + 1); - U32 *line_nums = push_array_no_zero(arena, U32, line_count); - - { - CV_C13_Line *line_ptr = (CV_C13_Line*)(first + line_array_off); - CV_C13_Line *line_opl = line_ptr + line_count; - - // TODO(allen): check order correctness here - - U32 i = 0; - for (; line_ptr < line_opl; line_ptr += 1, i += 1){ - voffs[i] = line_ptr->off + secrel_off + sec_base_off; - line_nums[i] = CV_C13_LineFlags_ExtractLineNumber(line_ptr->flags); - } - voffs[i] = secrel_opl + sec_base_off; - } - - // emit parsed lines - CV_C13LinesParsedNode *lines_parsed_node = push_array(arena, CV_C13LinesParsedNode, 1); - CV_C13LinesParsed *lines_parsed = &lines_parsed_node->v; - lines_parsed->sec_idx = sec_idx; - lines_parsed->file_off = file_off; - lines_parsed->secrel_base_off = secrel_off; - lines_parsed->file_name = file_name; - lines_parsed->voffs = voffs; - lines_parsed->line_nums = line_nums; - lines_parsed->line_count = line_count; - SLLQueuePush(node->lines_first, node->lines_last, lines_parsed_node); - - // rjf: advance - read_off += sizeof(*file); - read_off += line_item_size*line_count; + U32 *extra_file_count_ptr = (U32 *)(first + read_off); + read_off += sizeof(*extra_file_count_ptr); + U32 max_extra_file_count = (read_off_opl-read_off)/sizeof(U32); + extra_file_count = Min(*extra_file_count_ptr, max_extra_file_count); + extra_files = (U32 *)(first + read_off); + read_off += sizeof(*extra_files)*extra_file_count; } + + // rjf: push node for this inlinee lines parsed into this subsection's list + CV_C13InlineeLinesParsedNode *n = push_array(arena, CV_C13InlineeLinesParsedNode, 1); + SLLQueuePush(node->inlinee_lines_first, node->inlinee_lines_last, n); + n->v.inlinee = hdr->inlinee; + n->v.file_name = file_name; + n->v.first_source_ln = hdr->first_source_ln; + n->v.extra_file_count = extra_file_count; + n->v.extra_files = extra_files; + + // rjf: push node into inlinee parse hash table + U64 hash = cv_hash_from_item_id(hdr->inlinee); + U64 slot_idx = hash%inlinee_lines_parsed_slots_count; + SLLStackPush_N(inlinee_lines_parsed_slots[slot_idx], n, hash_next); } }break; } } - // convert to result + ////////////////////////////// + //- rjf: fill output + // CV_C13Parsed *result = push_array(arena, CV_C13Parsed, 1); result->first_sub_section = first; result->last_sub_section = last; result->sub_section_count = count; result->file_chksms_sub_section = file_chksms; - + result->inlinee_lines_parsed_slots = inlinee_lines_parsed_slots; + result->inlinee_lines_parsed_slots_count = inlinee_lines_parsed_slots_count; ProfEnd(); - - return(result); + return result; } diff --git a/src/codeview/codeview.h b/src/codeview/codeview.h index 015829d3..4b5c4000 100644 --- a/src/codeview/codeview.h +++ b/src/codeview/codeview.h @@ -2651,9 +2651,9 @@ struct CV_LeafUDTModSrcLine //////////////////////////////// //~ CodeView Format C13 Line Info Types -#define CV_C13_SubSectionKind_IgnoreFlag 0x80000000 +#define CV_C13SubSectionKind_IgnoreFlag 0x80000000 -#define CV_C13_SubSectionKindXList(X)\ +#define CV_C13SubSectionKindXList(X)\ X(Symbols, 0xF1)\ X(Lines, 0xF2)\ X(StringTable, 0xF3)\ @@ -2670,83 +2670,83 @@ X(CoffSymbolRVA, 0xFD)\ X(XfgHashType, 0xFF)\ X(XfgHashVirtual, 0x100) -typedef U32 CV_C13_SubSectionKind; -typedef enum CV_C13_SubSectionKindEnum +typedef U32 CV_C13SubSectionKind; +typedef enum CV_C13SubSectionKindEnum { -#define X(N,c) CV_C13_SubSectionKind_##N = c, - CV_C13_SubSectionKindXList(X) +#define X(N,c) CV_C13SubSectionKind_##N = c, + CV_C13SubSectionKindXList(X) #undef X } -CV_C13_SubSectionKindEnum; +CV_C13SubSectionKindEnum; -typedef struct CV_C13_SubSectionHeader CV_C13_SubSectionHeader; -struct CV_C13_SubSectionHeader +typedef struct CV_C13SubSectionHeader CV_C13SubSectionHeader; +struct CV_C13SubSectionHeader { - CV_C13_SubSectionKind kind; + CV_C13SubSectionKind kind; U32 size; }; //- FileChksms sub-section -typedef U8 CV_C13_ChecksumKind; -typedef enum CV_C13_ChecksumKindEnum +typedef U8 CV_C13ChecksumKind; +typedef enum CV_C13ChecksumKindEnum { - CV_C13_ChecksumKind_Null, - CV_C13_ChecksumKind_MD5, - CV_C13_ChecksumKind_SHA1, - CV_C13_ChecksumKind_SHA256, + CV_C13ChecksumKind_Null, + CV_C13ChecksumKind_MD5, + CV_C13ChecksumKind_SHA1, + CV_C13ChecksumKind_SHA256, } -CV_C13_ChecksumKindEnum; +CV_C13ChecksumKindEnum; -typedef struct CV_C13_Checksum CV_C13_Checksum; -struct CV_C13_Checksum +typedef struct CV_C13Checksum CV_C13Checksum; +struct CV_C13Checksum { U32 name_off; U8 len; - CV_C13_ChecksumKind kind; + CV_C13ChecksumKind kind; }; //- Lines sub-section -typedef U16 CV_C13_SubSecLinesFlags; +typedef U16 CV_C13SubSecLinesFlags; enum { - CV_C13_SubSecLinesFlag_HasColumns = (1 << 0) + CV_C13SubSecLinesFlag_HasColumns = (1 << 0) }; -typedef struct CV_C13_SubSecLinesHeader CV_C13_SubSecLinesHeader; -struct CV_C13_SubSecLinesHeader +typedef struct CV_C13SubSecLinesHeader CV_C13SubSecLinesHeader; +struct CV_C13SubSecLinesHeader { U32 sec_off; CV_SectionIndex sec; - CV_C13_SubSecLinesFlags flags; + CV_C13SubSecLinesFlags flags; U32 len; }; -typedef struct CV_C13_File CV_C13_File; -struct CV_C13_File +typedef struct CV_C13File CV_C13File; +struct CV_C13File { U32 file_off; U32 num_lines; U32 block_size; - // CV_C13_Line[num_lines] lines; - // CV_C13_Column[num_lines] columns; (if HasColumns) + // CV_C13Line[num_lines] lines; + // CV_C13Column[num_lines] columns; (if HasColumns) }; -typedef U32 CV_C13_LineFlags; -#define CV_C13_LineFlags_ExtractLineNumber(f) ((f)&0xFFFFFF) -#define CV_C13_LineFlags_ExtractDeltaToEnd(f) (((f)>>24)&0x7F) -#define CV_C13_LineFlags_ExtractStatement(f) (((f)>>31)&0x1) +typedef U32 CV_C13LineFlags; +#define CV_C13LineFlags_ExtractLineNumber(f) ((f)&0xFFFFFF) +#define CV_C13LineFlags_ExtractDeltaToEnd(f) (((f)>>24)&0x7F) +#define CV_C13LineFlags_ExtractStatement(f) (((f)>>31)&0x1) -typedef struct CV_C13_Line CV_C13_Line; -struct CV_C13_Line +typedef struct CV_C13Line CV_C13Line; +struct CV_C13Line { U32 off; - CV_C13_LineFlags flags; + CV_C13LineFlags flags; }; -typedef struct CV_C13_Column CV_C13_Column; -struct CV_C13_Column +typedef struct CV_C13Column CV_C13Column; +struct CV_C13Column { U16 start; U16 end; @@ -2754,16 +2754,16 @@ struct CV_C13_Column //- FrameData sub-section -typedef U32 CV_C13_FrameDataFlags; +typedef U32 CV_C13FrameDataFlags; enum { - CV_C13_FrameDataFlag_HasStructuredExceptionHandling = (1 << 0), - CV_C13_FrameDataFlag_HasExceptionHandling = (1 << 1), - CV_C13_FrameDataFlag_HasIsFuncStart = (1 << 2), + CV_C13FrameDataFlag_HasStructuredExceptionHandling = (1 << 0), + CV_C13FrameDataFlag_HasExceptionHandling = (1 << 1), + CV_C13FrameDataFlag_HasIsFuncStart = (1 << 2), }; -typedef struct CV_C13_FrameData CV_C13_FrameData; -struct CV_C13_FrameData +typedef struct CV_C13FrameData CV_C13FrameData; +struct CV_C13FrameData { U32 start_voff; U32 code_size; @@ -2773,25 +2773,25 @@ struct CV_C13_FrameData U32 frame_func; U16 prolog_size; U16 saved_reg_size; - CV_C13_FrameDataFlags flags; + CV_C13FrameDataFlags flags; }; //- InlineLines sub-section -typedef U32 CV_C13_InlineeLinesSig; +typedef U32 CV_C13InlineeLinesSig; enum { - CV_C13_InlineeLinesSig_NORMAL, - CV_C13_InlineeLinesSig_EXTRA_FILES, + CV_C13InlineeLinesSig_NORMAL, + CV_C13InlineeLinesSig_EXTRA_FILES, }; -typedef struct CV_C13_InlineeSourceLineHeader CV_C13_InlineeSourceLineHeader; -struct CV_C13_InlineeSourceLineHeader +typedef struct CV_C13InlineeSourceLineHeader CV_C13InlineeSourceLineHeader; +struct CV_C13InlineeSourceLineHeader { CV_ItemId inlinee; // LF_FUNC_ID or LF_MFUNC_ID U32 file_off; // offset into FileChksms sub-section U32 first_source_ln; // base source line number for binary annotations - // if sig set to CV_C13_InlineeLinesSig_EXTRA_FILES + // if sig set to CV_C13InlineeLinesSig_EXTRA_FILES // U32 extra_file_count; // U32 files[]; }; @@ -2871,7 +2871,6 @@ struct CV_SymParsed CV_SymTopLevelInfo info; }; - //////////////////////////////// //~ CodeView Leaf Parser Types @@ -2913,26 +2912,51 @@ struct CV_C13LinesParsedNode CV_C13LinesParsed v; }; +typedef struct CV_C13InlineeLinesParsed CV_C13InlineeLinesParsed; +struct CV_C13InlineeLinesParsed +{ + CV_ItemId inlinee; + String8 file_name; + U32 first_source_ln; + U32 extra_file_count; + U32 *extra_files; +}; + +typedef struct CV_C13InlineeLinesParsedNode CV_C13InlineeLinesParsedNode; +struct CV_C13InlineeLinesParsedNode +{ + CV_C13InlineeLinesParsedNode *next; + CV_C13InlineeLinesParsedNode *hash_next; + CV_C13InlineeLinesParsed v; +}; + typedef struct CV_C13SubSectionNode CV_C13SubSectionNode; struct CV_C13SubSectionNode { struct CV_C13SubSectionNode *next; - CV_C13_SubSectionKind kind; + CV_C13SubSectionKind kind; U32 off; U32 size; CV_C13LinesParsedNode *lines_first; CV_C13LinesParsedNode *lines_last; + CV_C13InlineeLinesParsedNode *inlinee_lines_first; + CV_C13InlineeLinesParsedNode *inlinee_lines_last; }; typedef struct CV_C13Parsed CV_C13Parsed; struct CV_C13Parsed { + // rjf: full sub-section list CV_C13SubSectionNode *first_sub_section; CV_C13SubSectionNode *last_sub_section; U64 sub_section_count; - // accelerator + // rjf: fastpath to file checksums section CV_C13SubSectionNode *file_chksms_sub_section; + + // rjf: fastpath to map inlinee CV_ItemId -> CV_InlineeLinesParsed quickly + CV_C13InlineeLinesParsedNode **inlinee_lines_parsed_slots; + U64 inlinee_lines_parsed_slots_count; }; //////////////////////////////// @@ -2946,52 +2970,42 @@ struct CV_TypeIdArray }; //////////////////////////////// -//~ CodeView Common Functions +//~ CodeView Common Decoding Helper Functions + +internal U64 cv_hash_from_string(String8 string); +internal U64 cv_hash_from_item_id(CV_ItemId item_id); internal CV_NumericParsed cv_numeric_from_data_range(U8 *first, U8 *opl); -internal B32 cv_numeric_fits_in_u64(CV_NumericParsed *num); -internal B32 cv_numeric_fits_in_s64(CV_NumericParsed *num); -internal B32 cv_numeric_fits_in_f64(CV_NumericParsed *num); +internal B32 cv_numeric_fits_in_u64(CV_NumericParsed *num); +internal B32 cv_numeric_fits_in_s64(CV_NumericParsed *num); +internal B32 cv_numeric_fits_in_f64(CV_NumericParsed *num); -internal U64 cv_u64_from_numeric(CV_NumericParsed *num); -internal S64 cv_s64_from_numeric(CV_NumericParsed *num); -internal F64 cv_f64_from_numeric(CV_NumericParsed *num); - -//////////////////////////////// -//~ Inline Binary Annotation Helpers +internal U64 cv_u64_from_numeric(CV_NumericParsed *num); +internal S64 cv_s64_from_numeric(CV_NumericParsed *num); +internal F64 cv_f64_from_numeric(CV_NumericParsed *num); internal U64 cv_decode_inline_annot_u32(String8 data, U64 offset, U32 *out_value); internal U64 cv_decode_inline_annot_s32(String8 data, U64 offset, S32 *out_value); //////////////////////////////// -//~ CodeView Sym/Leaf Parser Functions +//~ CodeView Parsing Functions -//- the first pass parser -internal CV_RecRangeStream* cv_rec_range_stream_from_data(Arena *arena, String8 data, U64 align); +//- rjf: record range stream parsing +internal CV_RecRangeStream *cv_rec_range_stream_from_data(Arena *arena, String8 data, U64 align); +internal CV_RecRangeArray cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream); -//- sym -internal CV_SymParsed* cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align); +//- rjf: sym stream parsing +internal CV_SymParsed *cv_sym_from_data(Arena *arena, String8 sym_data, U64 sym_align); -internal void cv_sym_top_level_info_from_syms(Arena *arena, String8 sym_data, - CV_RecRangeArray *ranges, - CV_SymTopLevelInfo *info_out); - -//- leaf -internal CV_LeafParsed* cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId first); - -//- range streams -internal CV_RecRangeChunk* cv_rec_range_stream_push_chunk(Arena *arena, - CV_RecRangeStream *stream); -// TODO(allen): check why this isn't a pointer return - -// leave a note if there's a good reason, otherwise switch to pointer return -internal CV_RecRangeArray cv_rec_range_array_from_stream(Arena *arena, CV_RecRangeStream *stream); +//- rjf: leaf stream parsing +internal CV_LeafParsed *cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_TypeId first); //////////////////////////////// //~ CodeView C13 Parser Functions typedef struct PDB_Strtbl PDB_Strtbl; typedef struct PDB_CoffSectionArray PDB_CoffSectionArray; -internal CV_C13Parsed* cv_c13_from_data(Arena *arena, String8 c13_data, struct PDB_Strtbl *strtbl, struct PDB_CoffSectionArray *sections); +internal CV_C13Parsed *cv_c13_parsed_from_data(Arena *arena, String8 c13_data, struct PDB_Strtbl *strtbl, struct PDB_CoffSectionArray *sections); #endif // CODEVIEW_H diff --git a/src/codeview/codeview_stringize.c b/src/codeview/codeview_stringize.c index 9c1245ae..8539ab96 100644 --- a/src/codeview/codeview_stringize.c +++ b/src/codeview/codeview_stringize.c @@ -49,12 +49,12 @@ cv_stringize_lvar_addr_gap_list(Arena *arena, String8List *out, void *first, voi } internal String8 -cv_string_from_c13_sub_section_kind(CV_C13_SubSectionKind kind){ +cv_string_from_c13_sub_section_kind(CV_C13SubSectionKind kind){ String8 result = str8_lit("UNRECOGNIZED_C13_SUB_SECTION_KIND"); switch (kind){ case 0: str8_lit("PARSE_ERROR"); break; -#define X(N,c) case CV_C13_SubSectionKind_##N: result = str8_lit(#N); break; - CV_C13_SubSectionKindXList(X) +#define X(N,c) case CV_C13SubSectionKind_##N: result = str8_lit(#N); break; + CV_C13SubSectionKindXList(X) #undef X } return(result); @@ -2280,7 +2280,7 @@ cv_stringize_c13_parsed(Arena *arena, String8List *out, CV_C13Parsed *c13){ switch(node->kind) { - case CV_C13_SubSectionKind_Lines: + case CV_C13SubSectionKind_Lines: { if (node->lines_first == 0) { @@ -2309,12 +2309,12 @@ cv_stringize_c13_parsed(Arena *arena, String8List *out, CV_C13Parsed *c13){ } }break; - case CV_C13_SubSectionKind_FileChksms: + case CV_C13SubSectionKind_FileChksms: { str8_list_push(arena, out, str8_lit(" no stringizer path\n")); }break; - case CV_C13_SubSectionKind_InlineeLines: + case CV_C13SubSectionKind_InlineeLines: { str8_list_push(arena, out, str8_lit(" no stringizer path\n")); }break; diff --git a/src/codeview/codeview_stringize.h b/src/codeview/codeview_stringize.h index b37cd904..9a94d9c4 100644 --- a/src/codeview/codeview_stringize.h +++ b/src/codeview/codeview_stringize.h @@ -27,7 +27,7 @@ internal void cv_stringize_lvar_addr_gap_list(Arena *arena, String8List *out, void *first, void *opl); internal String8 cv_string_from_basic_type(CV_BasicType basic_type); -internal String8 cv_string_from_c13_sub_section_kind(CV_C13_SubSectionKind kind); +internal String8 cv_string_from_c13_sub_section_kind(CV_C13SubSectionKind kind); internal String8 cv_string_from_reg(CV_Arch arch, CV_Reg reg); internal String8 cv_string_from_pointer_kind(CV_PointerKind ptr_kind); internal String8 cv_string_from_pointer_mode(CV_PointerMode ptr_mode); diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index e31518eb..2204645c 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -544,7 +544,7 @@ internal TS_TASK_FUNCTION_DEF(p2r_c13_stream_parse_task__entry_point) { P2R_C13StreamParseIn *in = (P2R_C13StreamParseIn *)p; void *out = 0; - ProfScope("parse c13 stream") out = cv_c13_from_data(arena, in->data, in->strtbl, in->coff_sections); + ProfScope("parse c13 stream") out = cv_c13_parsed_from_data(arena, in->data, in->strtbl, in->coff_sections); return out; } @@ -608,59 +608,67 @@ internal TS_TASK_FUNCTION_DEF(p2r_units_convert_task__entry_point) //- rjf: build this unit's line table RDIM_LineTable *line_table = rdim_line_table_chunk_list_push(arena, &out->line_tables, 256); - if(pdb_unit_c13->first_sub_section != 0) + for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; + node != 0; + node = node->next) { - for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; - node != 0; - node = node->next) + if(node->kind == CV_C13SubSectionKind_Lines) { - if(node->kind == CV_C13_SubSectionKind_Lines) + for(CV_C13LinesParsedNode *lines_n = node->lines_first; + lines_n != 0; + lines_n = lines_n->next) { - for(CV_C13LinesParsedNode *lines_n = node->lines_first; - lines_n != 0; - lines_n = lines_n->next) + CV_C13LinesParsed *lines = &lines_n->v; + + // rjf: file name -> normalized file path + String8 file_path = lines->file_name; + String8 file_path_normalized = lower_from_str8(scratch.arena, str8_skip_chop_whitespace(file_path)); + for(U64 idx = 0; idx < file_path_normalized.size; idx += 1) { - CV_C13LinesParsed *lines = &lines_n->v; - - // rjf: file name -> normalized file path - String8 file_path = lines->file_name; - String8 file_path_normalized = lower_from_str8(scratch.arena, str8_skip_chop_whitespace(file_path)); - for(U64 idx = 0; idx < file_path_normalized.size; idx += 1) + if(file_path_normalized.str[idx] == '\\') { - if(file_path_normalized.str[idx] == '\\') - { - file_path_normalized.str[idx] = '/'; - } + file_path_normalized.str[idx] = '/'; } - - // rjf: normalized file path -> source file node - U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); - U64 src_file_slot = file_path_normalized_hash%src_file_map.slots_count; - P2R_SrcFileNode *src_file_node = 0; - for(P2R_SrcFileNode *n = src_file_map.slots[src_file_slot]; n != 0; n = n->next) - { - if(str8_match(n->src_file->normal_full_path, file_path_normalized, 0)) - { - src_file_node = n; - break; - } - } - if(src_file_node == 0) - { - src_file_node = push_array(scratch.arena, P2R_SrcFileNode, 1); - SLLStackPush(src_file_map.slots[src_file_slot], src_file_node); - src_file_node->src_file = rdim_src_file_chunk_list_push(arena, &out->src_files, 4096); - src_file_node->src_file->normal_full_path = push_str8_copy(arena, file_path_normalized); - } - - // rjf: push sequence into both line table & source file's line map - RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, lines->voffs, lines->line_nums, lines->col_nums, lines->line_count); - rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); } + + // rjf: normalized file path -> source file node + U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size); + U64 src_file_slot = file_path_normalized_hash%src_file_map.slots_count; + P2R_SrcFileNode *src_file_node = 0; + for(P2R_SrcFileNode *n = src_file_map.slots[src_file_slot]; n != 0; n = n->next) + { + if(str8_match(n->src_file->normal_full_path, file_path_normalized, 0)) + { + src_file_node = n; + break; + } + } + if(src_file_node == 0) + { + src_file_node = push_array(scratch.arena, P2R_SrcFileNode, 1); + SLLStackPush(src_file_map.slots[src_file_slot], src_file_node); + src_file_node->src_file = rdim_src_file_chunk_list_push(arena, &out->src_files, 4096); + src_file_node->src_file->normal_full_path = push_str8_copy(arena, file_path_normalized); + } + + // rjf: push sequence into both line table & source file's line map + RDIM_LineSequence *seq = rdim_line_table_push_sequence(arena, &out->line_tables, line_table, src_file_node->src_file, lines->voffs, lines->line_nums, lines->col_nums, lines->line_count); + rdim_src_file_push_line_sequence(arena, &out->src_files, src_file_node->src_file, seq); } } } + //- rjf: build all inlinee line tables within this unit + for(CV_C13SubSectionNode *node = pdb_unit_c13->first_sub_section; + node != 0; + node = node->next) + { + if(node->kind == CV_C13SubSectionKind_InlineeLines) + { + + } + } + //- rjf: build unit RDIM_Unit *dst_unit = rdim_unit_chunk_list_push(arena, &out->units, units_chunk_cap); dst_unit->unit_name = unit_name; @@ -2506,6 +2514,22 @@ internal TS_TASK_FUNCTION_DEF(p2r_symbol_stream_convert_task__entry_point) CV_SymInlineSite *sym = (CV_SymInlineSite *)sym_header_struct_base; String8 binary_annots = str8((U8 *)(sym+1), rec_range->hdr.size - sizeof(rec_range->hdr.kind) - sizeof(*sym)); + // rjf: map inlinee -> parsed cv c13 inlinee line info + CV_C13InlineeLinesParsed *inlinee_lines_parsed = 0; + if(in->c13 != 0) + { + U64 hash = cv_hash_from_item_id(sym->inlinee); + U64 slot_idx = in->c13->inlinee_lines_parsed_slots_count; + for(CV_C13InlineeLinesParsedNode *n = in->c13->inlinee_lines_parsed_slots[slot_idx]; n != 0; n = n->hash_next) + { + if(n->v.inlinee == sym->inlinee) + { + inlinee_lines_parsed = &n->v; + break; + } + } + } + // rjf: extract external info about inline site String8 name = str8_zero(); RDIM_Type *type = 0; @@ -3577,6 +3601,7 @@ p2r_convert(Arena *arena, P2R_User2Convert *in) tasks_inputs[idx].sym = sym_for_unit[idx-global_stream_subdivision_tasks_count]; tasks_inputs[idx].sym_ranges_first= 0; tasks_inputs[idx].sym_ranges_opl = sym_for_unit[idx-global_stream_subdivision_tasks_count]->sym_ranges.count; + tasks_inputs[idx].c13 = c13_for_unit[idx-global_stream_subdivision_tasks_count]; } tasks_tickets[idx] = ts_kickoff(p2r_symbol_stream_convert_task__entry_point, 0, &tasks_inputs[idx]); } diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index c8f776b9..2a17447a 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -251,6 +251,7 @@ struct P2R_SymbolStreamConvertIn CV_LeafParsed *tpi_leaf; CV_LeafParsed *ipi_leaf; CV_SymParsed *sym; + CV_C13Parsed *c13; U64 sym_ranges_first; U64 sym_ranges_opl; CV_TypeId *itype_fwd_map;