1- using Microsoft . VisualStudio . Debugger . CallStack ;
1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . Globalization ;
4+ using System . IO ;
5+ using Microsoft . VisualStudio . Debugger . CallStack ;
26using Microsoft . VisualStudio . Debugger . ComponentInterfaces ;
37
48namespace PmipMyCallStack
59{
610 public class PmipCallStackFilter : IDkmCallStackFilter
711 {
12+ private static Range [ ] _rangesSortedByIp ;
13+ private static long _previousFileLength ;
14+ private static FuzzyRangeComparer _comparer = new FuzzyRangeComparer ( ) ;
815
9- public DkmStackWalkFrame [ ] FilterNextFrame ( DkmStackContext stackContext , DkmStackWalkFrame input )
10- {
11- if ( input == null ) // after last frame
12- return null ;
16+ public DkmStackWalkFrame [ ] FilterNextFrame ( DkmStackContext stackContext , DkmStackWalkFrame input )
17+ {
18+ if ( input == null ) // after last frame
19+ return null ;
1320
14- if ( input . InstructionAddress == null ) // error case
15- return new [ ] { input } ;
21+ if ( input . InstructionAddress == null ) // error case
22+ return new [ ] { input } ;
1623
17- if ( input . InstructionAddress . ModuleInstance != null && input . InstructionAddress . ModuleInstance . Module != null ) // code in existing module
18- return new [ ] { input } ;
24+ if ( input . InstructionAddress . ModuleInstance != null && input . InstructionAddress . ModuleInstance . Module != null ) // code in existing module
25+ return new [ ] { input } ;
1926
20- var runner = new PmipRunner ( stackContext , input ) ;
21- return new [ ] { runner . PmipStackFrame ( ) } ;
22- }
23- }
27+ if ( ! stackContext . Thread . IsMainThread ) // error case
28+ return new [ ] { input } ;
29+
30+
31+ return new [ ] { PmipStackFrame ( stackContext , input ) } ;
32+ }
33+
34+ public static DkmStackWalkFrame PmipStackFrame ( DkmStackContext stackContext , DkmStackWalkFrame frame )
35+ {
36+ var fileName = Path . Combine ( Path . GetTempPath ( ) , "pmip." + frame . Process . LivePart . Id ) ;
37+ RefreshStackData ( fileName ) ;
38+ string name = null ;
39+ if ( TryGetDescriptionForIp ( frame . InstructionAddress . CPUInstructionPart . InstructionPointer , out name ) )
40+ return DkmStackWalkFrame . Create (
41+ stackContext . Thread ,
42+ frame . InstructionAddress ,
43+ frame . FrameBase ,
44+ frame . FrameSize ,
45+ frame . Flags ,
46+ name ,
47+ frame . Registers ,
48+ frame . Annotations ) ;
49+
50+ return frame ;
51+ }
52+
53+ public static void RefreshStackData ( string fileName )
54+ {
55+ try
56+ {
57+ if ( ! File . Exists ( fileName ) )
58+ return ;
59+
60+ var fileInfo = new FileInfo ( fileName ) ;
61+ if ( fileInfo . Length == _previousFileLength )
62+ return ;
63+
64+ var list = new List < Range > ( 10000 ) ;
65+ using ( var inStream = new FileStream ( fileName , FileMode . Open , FileAccess . Read , FileShare . ReadWrite ) )
66+ {
67+ using ( var file = new StreamReader ( inStream ) )
68+ {
69+ string line ;
70+ while ( ( line = file . ReadLine ( ) ) != null )
71+ {
72+ const char delemiter = ';' ;
73+ var tokens = line . Split ( delemiter ) ;
74+
75+ //should never happen, but lets be safe and not get array out of bounds if it does
76+ if ( tokens . Length != 3 )
77+ continue ;
78+
79+ var startip = tokens [ 0 ] ;
80+ var endip = tokens [ 1 ] ;
81+ var description = tokens [ 2 ] ;
82+
83+ var startiplong = ulong . Parse ( startip , NumberStyles . HexNumber ) ;
84+ var endipint = ulong . Parse ( endip , NumberStyles . HexNumber ) ;
85+
86+ list . Add ( new Range ( ) { Name = description , Start = startiplong , End = endipint } ) ;
87+ }
88+ }
89+ }
90+
91+ list . Sort ( ( r1 , r2 ) => r1 . Start . CompareTo ( r2 . Start ) ) ;
92+ _rangesSortedByIp = list . ToArray ( ) ;
93+ _previousFileLength = fileInfo . Length ;
94+ }
95+ catch ( Exception ex )
96+ {
97+ Console . WriteLine ( "Unable to read dumped pmip file: " + ex . Message ) ;
98+ }
99+
100+ }
101+
102+ public static bool TryGetDescriptionForIp ( ulong ip , out string name )
103+ {
104+ name = string . Empty ;
105+
106+ if ( _rangesSortedByIp == null )
107+ return false ;
108+
109+ var rangeToFindIp = new Range ( ) { Start = ip } ;
110+ var index = Array . BinarySearch ( _rangesSortedByIp , rangeToFindIp , _comparer ) ;
111+
112+ if ( index < 0 )
113+ return false ;
114+
115+ name = _rangesSortedByIp [ index ] . Name ;
116+
117+ return true ;
118+ }
119+ }
24120}
0 commit comments