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 ;
2
6
using Microsoft . VisualStudio . Debugger . ComponentInterfaces ;
3
7
4
8
namespace PmipMyCallStack
5
9
{
6
10
public class PmipCallStackFilter : IDkmCallStackFilter
7
11
{
12
+ private static Range [ ] _rangesSortedByIp ;
13
+ private static long _previousFileLength ;
14
+ private static FuzzyRangeComparer _comparer = new FuzzyRangeComparer ( ) ;
8
15
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 ;
13
20
14
- if ( input . InstructionAddress == null ) // error case
15
- return new [ ] { input } ;
21
+ if ( input . InstructionAddress == null ) // error case
22
+ return new [ ] { input } ;
16
23
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 } ;
19
26
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
+ }
24
120
}
0 commit comments