From db737941d8a5278d28ad3170ff31ed526fc7531c Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Wed, 1 May 2024 16:54:15 -0700 Subject: [PATCH 1/5] codeview: inline binary annot format and decode helpers --- src/codeview/codeview.c | 68 +++++++++++++++++++++++++++++++++++++++++ src/codeview/codeview.h | 58 +++++++++++++++++++++++++++-------- 2 files changed, 113 insertions(+), 13 deletions(-) diff --git a/src/codeview/codeview.c b/src/codeview/codeview.c index ad1b528e..06b2d2c8 100644 --- a/src/codeview/codeview.c +++ b/src/codeview/codeview.c @@ -165,6 +165,74 @@ cv_f64_from_numeric(CV_NumericParsed *num){ return(result); } +//////////////////////////////// +//~ Inline Binary Annotation Helpers + +internal U64 +cv_decode_inline_annot_u32(String8 data, U64 offset, U32 *out_value) +{ + U32 value; + + U64 cursor = offset; + + U8 header = 0; + cursor += str8_deserial_read_struct(data, cursor, &header); + + // 1 byte + if((header & 0x80) == 0) + { + value = header; + } + // 2 bytes + else if((header & 0xC0) == 0x80) + { + Assert(cursor + sizeof(U8) * 2 <= data.size); + U8 second_byte; + cursor += str8_deserial_read_struct(data, cursor, &second_byte); + value = ((header & 0x3F) << 8) | second_byte; + } + // 4 bytes + else if((header & 0xE0) == 0xC0) + { + Assert(cursor + sizeof(U8) * 3 <= data.size); + U8 second_byte, third_byte, fourth_byte; + cursor += str8_deserial_read_struct(data, cursor, &second_byte); + cursor += str8_deserial_read_struct(data, cursor, &third_byte); + cursor += str8_deserial_read_struct(data, cursor, &fourth_byte); + value = (((U32)header & 0x1F) << 24) | ((U32)second_byte << 16) | ((U32)third_byte << 8) | (U32)fourth_byte; + } + // bad encode + else if((header & 0xE0) == 0xE0) + { + value = max_U32; + } + + *out_value = value; + + U64 read_size = cursor - offset; + return read_size; +} + +internal U64 +cv_decode_inline_annot_s32(String8 data, U64 offset, S32 *out_value) +{ + U32 value; + + U64 read_size = cv_decode_inline_annot_u32(data, offset, &value); + + if(value & 1) + { + value = -(value >> 1); + } + else + { + value = value >> 1; + } + + *out_value = (S32)value; + + return read_size; +} //////////////////////////////// //~ CodeView Sym Parser Functions diff --git a/src/codeview/codeview.h b/src/codeview/codeview.h index a037bee2..ff9f348e 100644 --- a/src/codeview/codeview.h +++ b/src/codeview/codeview.h @@ -1761,13 +1761,51 @@ struct CV_SymBuildInfo //- (SymKind: INLINESITE) +typedef U32 CV_InlineBinaryAnnotaiton; +typedef enum CV_InlineBinaryAnnotationenum +{ + CV_InlineBinaryAnnotation_Null, + CV_InlineBinaryAnnotation_CodeOffset, + CV_InlineBinaryAnnotation_ChangeCodeOffsetBase, + CV_InlineBinaryAnnotation_ChangeCodeOffset, + CV_InlineBinaryAnnotation_ChangeCodeLength, + CV_InlineBinaryAnnotation_ChnageFile, + CV_InlineBinaryAnnotation_ChangeLineOffset, + CV_InlineBinaryAnnotation_ChnageLineEndDelta, + CV_InlineBinaryAnnotation_ChangeRangeKind, + CV_InlineBinaryAnnotation_ChangeColumnStart, + CV_InlineBinaryAnnotation_ChangeColumnEndDelta, + CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset, + CV_InlineBinaryAnnotation_ChangeCodeLengthAndCodeOffset, + CV_InlineBinaryAnnotaiton_ChangeColumnEnd +}; + +typedef U32 CV_InlineRangeKind; +typedef enum CV_InlnineRangeKindEnum +{ + CV_InlineRangeKind_Expr, + CV_InlineRangeKind_Stmt +}; + typedef struct CV_SymInlineSite CV_SymInlineSite; struct CV_SymInlineSite { U32 parent; U32 end; CV_ItemId inlinee; - // CV_BinaryAnnotation annotations (rest of data) + // U8 annotations[] (rest of data) +}; + +//- (SymKind: INLINESITE2) + +typedef struct CV_SymInlineSite2 CV_SymInlineSite2; +struct CV_SymInlineSite2 +{ + U32 parent_off; + U32 end_off; + CV_ItemId inlinee; + U32 invocations; + // U8 annotations[] (rest of data) }; //- (SymKind: INLINESITE_END) (empty) @@ -1835,18 +1873,6 @@ struct CV_SymPogoInfo U32 post_inline_static_inst_count; }; -//- (SymKind: INLINESITE2) - -typedef struct CV_SymInlineSite2 CV_SymInlineSite2; -struct CV_SymInlineSite2 -{ - U32 parent_off; - U32 end_off; - CV_ItemId inlinee; - U32 invocations; - // CV_BinaryAnnotation annotations (rest of data) -}; - //- (SymKind: HEAPALLOCSITE) typedef struct CV_SymHeapAllocSite CV_SymHeapAllocSite; @@ -2905,6 +2931,12 @@ 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_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 From c767f03f327b616188651d040cb9a72e166b3d6c Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Sun, 26 May 2024 14:56:13 -0700 Subject: [PATCH 2/5] clean up & merge inline binary annotation decoders --- src/codeview/codeview.c | 77 ++++++++++++++++++++++------------------- src/codeview/codeview.h | 13 +++---- 2 files changed, 49 insertions(+), 41 deletions(-) diff --git a/src/codeview/codeview.c b/src/codeview/codeview.c index 06b2d2c8..f7a88fd0 100644 --- a/src/codeview/codeview.c +++ b/src/codeview/codeview.c @@ -171,44 +171,51 @@ cv_f64_from_numeric(CV_NumericParsed *num){ internal U64 cv_decode_inline_annot_u32(String8 data, U64 offset, U32 *out_value) { - U32 value; - U64 cursor = offset; - + + // rjf: read header U8 header = 0; cursor += str8_deserial_read_struct(data, cursor, &header); - - // 1 byte - if((header & 0x80) == 0) + + // rjf: decode value + U32 value = 0; { - value = header; + // 1 byte + if((header & 0x80) == 0) + { + value = header; + } + + // 2 bytes + else if((header & 0xC0) == 0x80 && cursor+2 <= data.size) + { + U8 second_byte; + cursor += str8_deserial_read_struct(data, cursor, &second_byte); + value = ((header & 0x3F) << 8) | second_byte; + } + + // 4 bytes + else if((header & 0xE0) == 0xC0 && cursor+3 <= data.size) + { + U8 second_byte, third_byte, fourth_byte; + cursor += str8_deserial_read_struct(data, cursor, &second_byte); + cursor += str8_deserial_read_struct(data, cursor, &third_byte); + cursor += str8_deserial_read_struct(data, cursor, &fourth_byte); + value = (((U32)header & 0x1F) << 24) | ((U32)second_byte << 16) | ((U32)third_byte << 8) | (U32)fourth_byte; + } + + // bad encode + else if((header & 0xE0) == 0xE0) + { + value = max_U32; + } } - // 2 bytes - else if((header & 0xC0) == 0x80) + + // rjf: output results + if(out_value) { - Assert(cursor + sizeof(U8) * 2 <= data.size); - U8 second_byte; - cursor += str8_deserial_read_struct(data, cursor, &second_byte); - value = ((header & 0x3F) << 8) | second_byte; + *out_value = value; } - // 4 bytes - else if((header & 0xE0) == 0xC0) - { - Assert(cursor + sizeof(U8) * 3 <= data.size); - U8 second_byte, third_byte, fourth_byte; - cursor += str8_deserial_read_struct(data, cursor, &second_byte); - cursor += str8_deserial_read_struct(data, cursor, &third_byte); - cursor += str8_deserial_read_struct(data, cursor, &fourth_byte); - value = (((U32)header & 0x1F) << 24) | ((U32)second_byte << 16) | ((U32)third_byte << 8) | (U32)fourth_byte; - } - // bad encode - else if((header & 0xE0) == 0xE0) - { - value = max_U32; - } - - *out_value = value; - U64 read_size = cursor - offset; return read_size; } @@ -217,9 +224,9 @@ internal U64 cv_decode_inline_annot_s32(String8 data, U64 offset, S32 *out_value) { U32 value; - + U64 read_size = cv_decode_inline_annot_u32(data, offset, &value); - + if(value & 1) { value = -(value >> 1); @@ -228,9 +235,9 @@ cv_decode_inline_annot_s32(String8 data, U64 offset, S32 *out_value) { value = value >> 1; } - + *out_value = (S32)value; - + return read_size; } diff --git a/src/codeview/codeview.h b/src/codeview/codeview.h index ff9f348e..5c3fe546 100644 --- a/src/codeview/codeview.h +++ b/src/codeview/codeview.h @@ -1761,8 +1761,8 @@ struct CV_SymBuildInfo //- (SymKind: INLINESITE) -typedef U32 CV_InlineBinaryAnnotaiton; -typedef enum CV_InlineBinaryAnnotationenum +typedef U32 CV_InlineBinaryAnnotation; +typedef enum CV_InlineBinaryAnnotationEnum { CV_InlineBinaryAnnotation_Null, CV_InlineBinaryAnnotation_CodeOffset, @@ -1778,14 +1778,16 @@ typedef enum CV_InlineBinaryAnnotationenum CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset, CV_InlineBinaryAnnotation_ChangeCodeLengthAndCodeOffset, CV_InlineBinaryAnnotaiton_ChangeColumnEnd -}; +} +CV_InlineBinaryAnnotationEnum; typedef U32 CV_InlineRangeKind; -typedef enum CV_InlnineRangeKindEnum +typedef enum CV_InlineRangeKindEnum { CV_InlineRangeKind_Expr, CV_InlineRangeKind_Stmt -}; +} +CV_InlineRangeKindEnum; typedef struct CV_SymInlineSite CV_SymInlineSite; struct CV_SymInlineSite @@ -2917,7 +2919,6 @@ struct CV_TypeIdArray U64 count; }; - //////////////////////////////// //~ CodeView Common Functions From d2f9bdeefbd7b5bf10ad17740abe1a3ef6d20e76 Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Wed, 1 May 2024 17:06:12 -0700 Subject: [PATCH 3/5] codeview: new sub-section types --- src/codeview/codeview.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/codeview/codeview.h b/src/codeview/codeview.h index 5c3fe546..5bf4e76d 100644 --- a/src/codeview/codeview.h +++ b/src/codeview/codeview.h @@ -2664,7 +2664,9 @@ X(IlLines, 0xF9)\ X(FuncMDTokenMap, 0xFA)\ X(TypeMDTokenMap, 0xFB)\ X(MergedAssemblyInput, 0xFC)\ -X(CoffSymbolRVA, 0xFD) +X(CoffSymbolRVA, 0xFD)\ +X(XfgHashType, 0xFF)\ +X(XfgHashVirtual, 0x100) typedef U32 CV_C13_SubSectionKind; typedef enum From eea3c6b53cd86742cb0783787d0e710058fbcb9d Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Wed, 1 May 2024 17:11:29 -0700 Subject: [PATCH 4/5] codeview: struct defs for $$INLINEE_LINES --- src/codeview/codeview.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/codeview/codeview.h b/src/codeview/codeview.h index 5bf4e76d..ef3706d3 100644 --- a/src/codeview/codeview.h +++ b/src/codeview/codeview.h @@ -2772,6 +2772,26 @@ struct CV_C13_FrameData CV_C13_FrameDataFlags flags; }; +//- InlineLines sub-section + +typedef U32 CV_C13_InlineeLinesSig; +enum +{ + CV_C13_InlineeLinesSig_NORMAL, + CV_C13_InlineeLinesSig_EXTRA_FILES, +}; + +typedef struct CV_C13_InlineeSourceLineHeader CV_C13_InlineeSourceLineHeader; +struct CV_C13_InlineeSourceLineHeader +{ + 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 + // U32 extra_file_count; + // U32 files[]; +}; + #pragma pack(pop) //////////////////////////////// From 6a32c197fa8b3ccdd2e487852b0fafefc2a1a329 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Sun, 26 May 2024 15:07:38 -0700 Subject: [PATCH 5/5] rdi_dump: stringize source file's path --- src/codeview/codeview.h | 22 +++++++++++++--------- src/rdi_dump/rdi_dump.c | 5 +++++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/codeview/codeview.h b/src/codeview/codeview.h index ef3706d3..9c99b25a 100644 --- a/src/codeview/codeview.h +++ b/src/codeview/codeview.h @@ -1152,6 +1152,7 @@ struct CV_SymFrameproc }; //- (SymKind: ANNOTATION) + typedef struct CV_SymAnnotation CV_SymAnnotation; struct CV_SymAnnotation { @@ -1769,15 +1770,15 @@ typedef enum CV_InlineBinaryAnnotationEnum CV_InlineBinaryAnnotation_ChangeCodeOffsetBase, CV_InlineBinaryAnnotation_ChangeCodeOffset, CV_InlineBinaryAnnotation_ChangeCodeLength, - CV_InlineBinaryAnnotation_ChnageFile, + CV_InlineBinaryAnnotation_ChangeFile, CV_InlineBinaryAnnotation_ChangeLineOffset, - CV_InlineBinaryAnnotation_ChnageLineEndDelta, + CV_InlineBinaryAnnotation_ChangeLineEndDelta, CV_InlineBinaryAnnotation_ChangeRangeKind, CV_InlineBinaryAnnotation_ChangeColumnStart, CV_InlineBinaryAnnotation_ChangeColumnEndDelta, CV_InlineBinaryAnnotation_ChangeCodeOffsetAndLineOffset, CV_InlineBinaryAnnotation_ChangeCodeLengthAndCodeOffset, - CV_InlineBinaryAnnotaiton_ChangeColumnEnd + CV_InlineBinaryAnnotation_ChangeColumnEnd } CV_InlineBinaryAnnotationEnum; @@ -1826,7 +1827,7 @@ struct CV_SymFileStatic //- (SymKind: ARMSWITCHTABLE) typedef U16 CV_ArmSwitchKind; -typedef enum +typedef enum CV_ArmSwitchKindEnum { CV_ArmSwitchKind_INT1, CV_ArmSwitchKind_UINT1, @@ -1839,7 +1840,8 @@ typedef enum CV_ArmSwitchKind_UINT2SHL1, CV_ArmSwitchKind_INT1SSHL1, CV_ArmSwitchKind_INT2SSHL1, -} CV_ArmSwitchKindEnum; +} +CV_ArmSwitchKindEnum; typedef struct CV_SymArmSwitchTable CV_SymArmSwitchTable; struct CV_SymArmSwitchTable @@ -2669,12 +2671,13 @@ X(XfgHashType, 0xFF)\ X(XfgHashVirtual, 0x100) typedef U32 CV_C13_SubSectionKind; -typedef enum +typedef enum CV_C13_SubSectionKindEnum { #define X(N,c) CV_C13_SubSectionKind_##N = c, CV_C13_SubSectionKindXList(X) #undef X -} CV_C13_SubSectionKindEnum; +} +CV_C13_SubSectionKindEnum; typedef struct CV_C13_SubSectionHeader CV_C13_SubSectionHeader; struct CV_C13_SubSectionHeader @@ -2686,13 +2689,14 @@ struct CV_C13_SubSectionHeader //- FileChksms sub-section typedef U8 CV_C13_ChecksumKind; -typedef enum +typedef enum CV_C13_ChecksumKindEnum { CV_C13_ChecksumKind_Null, CV_C13_ChecksumKind_MD5, CV_C13_ChecksumKind_SHA1, CV_C13_ChecksumKind_SHA256, -} CV_C13_ChecksumKindEnum; +} +CV_C13_ChecksumKindEnum; typedef struct CV_C13_Checksum CV_C13_Checksum; struct CV_C13_Checksum diff --git a/src/rdi_dump/rdi_dump.c b/src/rdi_dump/rdi_dump.c index 92f96225..54372d81 100644 --- a/src/rdi_dump/rdi_dump.c +++ b/src/rdi_dump/rdi_dump.c @@ -240,6 +240,11 @@ rdi_stringize_source_file(Arena *arena, String8List *out, RDI_Parsed *parsed, RDI_ParsedLineMap line_map = {0}; rdi_line_map_from_source_file(parsed, source_file, &line_map); + // normal source path + String8 path = {0}; + path.str = rdi_string_from_idx(parsed, 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);