3 using System
.Collections
.Generic
;
7 static class BinaryReaderExtensions
9 public static int ReadVariableInt (this BinaryReader reader
)
12 for (var i
= 0; i
< 4; i
++) {
13 var b
= reader
.ReadByte ();
14 val
|= (b
& 0x7f) << (7 * i
);
19 throw new Exception ("Invalid variable int");
22 public static int ReadVariableZigZagInt (this BinaryReader reader
)
24 int enc
= ReadVariableInt (reader
);
26 return ((enc
& 1) == 0)? val
: -val
;
34 List
<SeqPoint
> seqPoints
;
36 public static MethodData
Read (BinaryReader reader
)
38 var hasDebugData
= reader
.ReadVariableInt () != 0;
39 var dataSize
= reader
.ReadVariableInt ();
40 var dataEnd
= reader
.BaseStream
.Position
+ dataSize
;
42 var seqPoints
= new List
<SeqPoint
> ();
44 while (reader
.BaseStream
.Position
< dataEnd
) {
45 var seqPoint
= SeqPoint
.Read (reader
, prev
, hasDebugData
);
46 seqPoints
.Add (seqPoint
);
50 if (reader
.BaseStream
.Position
!= dataEnd
)
51 throw new Exception ("Read more seq point than expected.");
53 return new MethodData () { seqPoints = seqPoints }
;
56 public bool TryGetILOffset (int nativeOffset
, out int ilOffset
)
60 foreach (var seqPoint
in seqPoints
) {
61 if (seqPoint
.NativeOffset
> nativeOffset
)
69 ilOffset
= prev
.ILOffset
;
76 public readonly int ILOffset
;
77 public readonly int NativeOffset
;
79 public SeqPoint (int ilOffset
, int nativeOffset
)
82 NativeOffset
= nativeOffset
;
85 public static SeqPoint
Read (BinaryReader reader
, SeqPoint prev
, bool hasDebug
)
87 var ilOffset
= reader
.ReadVariableZigZagInt ();
88 var nativeOffset
= reader
.ReadVariableZigZagInt ();
90 // Respect delta encoding
92 ilOffset
+= prev
.ILOffset
;
93 nativeOffset
+= prev
.NativeOffset
;
96 //Read everything to ensure the buffer position is at the end of the seq point data.
98 reader
.ReadVariableInt (); // flags
100 var next_length
= reader
.ReadVariableInt ();
101 for (var i
= 0; i
< next_length
; ++i
)
102 reader
.ReadVariableInt ();
105 return new SeqPoint (ilOffset
, nativeOffset
);
109 Dictionary
<Tuple
<int,int>, MethodData
> dataByIds
;
110 Dictionary
<int, MethodData
> dataByTokens
;
112 public static SeqPointInfo
Read (string path
)
114 using (var reader
= new BinaryReader (File
.Open (path
, FileMode
.Open
)))
116 var dataByIds
= new Dictionary
<Tuple
<int,int>, MethodData
> ();
117 var dataByTokens
= new Dictionary
<int, MethodData
> ();
119 var methodCount
= reader
.ReadVariableInt ();
121 for (var i
= 0; i
< methodCount
; ++i
) {
122 var methodToken
= reader
.ReadVariableInt ();
123 var methodIndex
= reader
.ReadVariableInt ();
124 var methodId
= new Tuple
<int, int> (methodToken
, methodIndex
);
126 var methodData
= MethodData
.Read (reader
);
128 dataByIds
.Add (methodId
, methodData
);
129 if (!dataByTokens
.ContainsKey (methodToken
))
130 dataByTokens
.Add (methodToken
, methodData
);
133 return new SeqPointInfo { dataByIds = dataByIds, dataByTokens = dataByTokens }
;
137 public int GetILOffset (int methodToken
, uint methodIndex
, int nativeOffset
)
139 MethodData methodData
;
140 if (methodIndex
== 0xffffff) {
141 if (!dataByTokens
.TryGetValue (methodToken
, out methodData
))
142 throw new Exception (string.Format ("Could not find data for method token {0:X}", methodToken
));
144 var methodId
= new Tuple
<int, int> (methodToken
, (int)methodIndex
);
145 if (!dataByIds
.TryGetValue (methodId
, out methodData
))
146 throw new Exception (string.Format ("Could not find data for method token {0:X} with index {1:X}", methodToken
, methodIndex
));
150 if (!methodData
.TryGetILOffset (nativeOffset
, out ilOffset
))
151 throw new Exception ("Could not retrieve IL offset");