From 343cf9339df33e8e6a73bb2c59444d6327dbc0c0 Mon Sep 17 00:00:00 2001 From: Tim Van Holder Date: Sat, 11 Jun 2022 01:15:12 +0200 Subject: [PATCH] Emit sequence points in ascending offset order This is required by the Portable PDB specification, and the sequence point collection in `MethodDebugInfo` does not guarantee it. This also tweaks the writing of hidden sequence points to use two writes of 0 as compressed unsigned integer, instead of a single write of 0 as a plain short, to more closely match the specification. Fixes #840. --- Mono.Cecil/AssemblyWriter.cs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Mono.Cecil/AssemblyWriter.cs b/Mono.Cecil/AssemblyWriter.cs index 3cba95edd..5cff01127 100644 --- a/Mono.Cecil/AssemblyWriter.cs +++ b/Mono.Cecil/AssemblyWriter.cs @@ -3302,8 +3302,15 @@ public void WriteSequencePoints (MethodDebugInformation info) if (!info.TryGetUniqueDocument (out previous_document)) previous_document = null; - for (int i = 0; i < info.SequencePoints.Count; i++) { - var sequence_point = info.SequencePoints [i]; + // The sequence points need to be emitted in strict ascending offset order, which is not guaranteed to be the case for + // info.SequencePoints. + var sequencePoints = new SortedDictionary (); + foreach (var sequence_point in info.SequencePoints) { + sequencePoints [sequence_point.Offset] = sequence_point; + } + + var previous_offset = 0; + foreach (var sequence_point in sequencePoints.Values) { var document = sequence_point.Document; if (previous_document != document) { @@ -3316,13 +3323,12 @@ public void WriteSequencePoints (MethodDebugInformation info) previous_document = document; } - if (i > 0) - WriteCompressedUInt32 ((uint) (sequence_point.Offset - info.SequencePoints [i - 1].Offset)); - else - WriteCompressedUInt32 ((uint) sequence_point.Offset); + WriteCompressedUInt32 ((uint) (sequence_point.Offset - previous_offset)); + previous_offset = sequence_point.Offset; if (sequence_point.IsHidden) { - WriteInt16 (0); + WriteCompressedUInt32 (0); + WriteCompressedUInt32 (0); continue; }