From 390aab2699201a35922591941f700de476a0075d Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Wed, 7 Feb 2024 13:35:14 -0800 Subject: [PATCH] raddbg from pdb: correctly parse several c13 files in single c13 subsection, rather than just assuming a single one --- src/raddbg_convert/pdb/raddbg_codeview.c | 148 ++++++++++-------- src/raddbg_convert/pdb/raddbg_codeview.h | 12 +- .../pdb/raddbg_codeview_stringize.c | 19 ++- src/raddbg_convert/pdb/raddbg_from_pdb.c | 13 +- 4 files changed, 111 insertions(+), 81 deletions(-) diff --git a/src/raddbg_convert/pdb/raddbg_codeview.c b/src/raddbg_convert/pdb/raddbg_codeview.c index 099365e4..472906a9 100644 --- a/src/raddbg_convert/pdb/raddbg_codeview.c +++ b/src/raddbg_convert/pdb/raddbg_codeview.c @@ -399,76 +399,90 @@ cv_c13_from_data(Arena *arena, String8 c13_data, { // read header if (sizeof(CV_C13_SubSecLinesHeader) <= cap){ - CV_C13_SubSecLinesHeader *hdr = (CV_C13_SubSecLinesHeader*)first; + U32 read_off = 0; + U64 read_off_opl = node->size; + CV_C13_SubSecLinesHeader *hdr = (CV_C13_SubSecLinesHeader*)(first + read_off); + read_off += sizeof(*hdr); - // read file - U32 file_info_off = sizeof(*hdr); - if (file_info_off + sizeof(CV_C13_File) <= cap){ - CV_C13_File *file = (CV_C13_File*)(first + file_info_off); + // 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) + { + continue; + } + + // read files + for(;read_off+sizeof(CV_C13_File) <= 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; - // extract top level info - U32 sec_idx = hdr->sec; - if (1 <= sec_idx && sec_idx <= sections->count){ - 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; - - 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 = file_info_off + sizeof(*file); - U32 line_count_max = (cap - 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_C13LinesParsed *lines_parsed = push_array(arena, CV_C13LinesParsed, 1); - 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; - - node->lines = lines_parsed; + // 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; + if(voffs[i] == 0x0002318c) + { + int x = 0; + } + 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; } } }break; diff --git a/src/raddbg_convert/pdb/raddbg_codeview.h b/src/raddbg_convert/pdb/raddbg_codeview.h index aeed9188..3f1c5d4a 100644 --- a/src/raddbg_convert/pdb/raddbg_codeview.h +++ b/src/raddbg_convert/pdb/raddbg_codeview.h @@ -2977,14 +2977,20 @@ typedef struct CV_C13LinesParsed{ U32 line_count; } CV_C13LinesParsed; +typedef struct CV_C13LinesParsedNode CV_C13LinesParsedNode; +struct CV_C13LinesParsedNode +{ + CV_C13LinesParsedNode *next; + CV_C13LinesParsed v; +}; + typedef struct CV_C13SubSectionNode{ struct CV_C13SubSectionNode *next; CV_C13_SubSectionKind kind; U32 off; U32 size; - union{ - CV_C13LinesParsed *lines; - }; + CV_C13LinesParsedNode *lines_first; + CV_C13LinesParsedNode *lines_last; } CV_C13SubSectionNode; typedef struct CV_C13Parsed{ diff --git a/src/raddbg_convert/pdb/raddbg_codeview_stringize.c b/src/raddbg_convert/pdb/raddbg_codeview_stringize.c index 10534908..b8729609 100644 --- a/src/raddbg_convert/pdb/raddbg_codeview_stringize.c +++ b/src/raddbg_convert/pdb/raddbg_codeview_stringize.c @@ -2330,21 +2330,26 @@ cv_stringize_leaf_array(Arena *arena, String8List *out, static void cv_stringize_c13_parsed(Arena *arena, String8List *out, CV_C13Parsed *c13){ - for (CV_C13SubSectionNode *node = c13->first_sub_section; - node != 0; - node = node->next){ + for(CV_C13SubSectionNode *node = c13->first_sub_section; + node != 0; + node = node->next) + { String8 kind_str = cv_string_from_c13_sub_section_kind(node->kind); str8_list_pushf(arena, out, "C13 Sub Section [%llx] (%.*s):\n", node->off, str8_varg(kind_str)); - switch (node->kind){ + switch(node->kind) + { case CV_C13_SubSectionKind_Lines: { - CV_C13LinesParsed *lines = node->lines; - if (lines == 0){ + if (node->lines_first == 0) + { str8_list_push(arena, out, str8_lit(" failed to extract info\n")); } - else{ + else for(CV_C13LinesParsedNode *n = node->lines_first; n != 0; n = n->next) + { + CV_C13LinesParsed *lines = &n->v; + str8_list_pushf(arena, out, " section: %u\n", lines->sec_idx); str8_list_pushf(arena, out, " file off: %u\n", lines->file_off); str8_list_pushf(arena, out, " file name: %.*s\n", str8_varg(lines->file_name)); diff --git a/src/raddbg_convert/pdb/raddbg_from_pdb.c b/src/raddbg_convert/pdb/raddbg_from_pdb.c index 01963467..46eeb0d4 100644 --- a/src/raddbg_convert/pdb/raddbg_from_pdb.c +++ b/src/raddbg_convert/pdb/raddbg_from_pdb.c @@ -3419,10 +3419,15 @@ str8_list_pushf(arena, &out->errors, fmt, __VA_ARGS__);\ // unit's line info for (CV_C13SubSectionNode *node = unit_c13->first_sub_section; node != 0; - node = node->next){ - if (node->kind == CV_C13_SubSectionKind_Lines){ - CV_C13LinesParsed *lines = node->lines; - if (lines != 0){ + node = node->next) + { + if(node->kind == CV_C13_SubSectionKind_Lines) + { + for(CV_C13LinesParsedNode *lines_n = node->lines_first; + lines_n != 0; + lines_n = lines_n->next) + { + CV_C13LinesParsed *lines = &lines_n->v; CONS_LineSequence seq = {0}; seq.file_name = lines->file_name; seq.voffs = lines->voffs;