1
1
using System ;
2
2
using System . Collections . Generic ;
3
- using Microsoft . VisualStudio . Debugger ;
3
+ using System . Globalization ;
4
+ using System . IO ;
4
5
using Microsoft . VisualStudio . Debugger . CallStack ;
5
6
using Microsoft . VisualStudio . Debugger . ComponentInterfaces ;
6
- using Microsoft . VisualStudio . Debugger . Evaluation ;
7
7
8
8
namespace PmipMyCallStack
9
9
{
10
10
public class PmipCallStackFilter : IDkmCallStackFilter
11
11
{
12
- Guid ContextBeingWalked = new Guid ( ) ;
13
- public DkmStackWalkFrame [ ] FilterNextFrame ( DkmStackContext stackContext , DkmStackWalkFrame input )
14
- {
12
+ private static Range [ ] IPs ;
13
+ private static long previousFileLength ;
14
+ static FuzzyRangeComparer comparer = new FuzzyRangeComparer ( ) ;
15
+
16
+ public DkmStackWalkFrame [ ] FilterNextFrame ( DkmStackContext stackContext , DkmStackWalkFrame input )
17
+ {
15
18
if ( input == null ) // after last frame
16
19
return null ;
17
20
18
- if ( input . InstructionAddress == null ) // error case
19
- return new [ ] { input } ;
21
+ if ( input . InstructionAddress == null ) // error case
22
+ return new [ ] { input } ;
23
+
24
+ if ( input . InstructionAddress . ModuleInstance != null && input . InstructionAddress . ModuleInstance . Module != null ) // code in existing module
25
+ return new [ ] { input } ;
20
26
21
- if ( input . InstructionAddress . ModuleInstance != null && input . InstructionAddress . ModuleInstance . Module != null ) // code in existing module
22
- return new [ ] { input } ;
27
+ if ( ! stackContext . Thread . IsMainThread ) // error case
28
+ return new [ ] { input } ;
23
29
24
- PmipFunctionDataItem pmipPrettyDump ;
25
- if ( ! TryGetPmipPrettyDumpFunction ( stackContext , input , out pmipPrettyDump ) )
26
- return new [ ] { input } ;
27
30
28
- if ( stackContext . UniqueId != ContextBeingWalked )
31
+ return new [ ] { PmipStackFrame ( stackContext , input ) } ;
32
+ }
33
+ struct Range
34
+ {
35
+ public ulong Start ;
36
+ public ulong End ;
37
+ public string Name ;
38
+ }
39
+
40
+ class FuzzyRangeComparer : IComparer < Range >
41
+ {
42
+ public int Compare ( Range x , Range y )
29
43
{
30
- ContextBeingWalked = stackContext . UniqueId ;
31
- pmipPrettyDump . RefreshStackData ( input ) ;
32
- }
44
+ if ( x . Name == null && y . Start <= x . Start && y . End >= x . Start )
45
+ {
46
+ return 0 ;
47
+ }
33
48
34
- return new [ ] { pmipPrettyDump . PmipStackFrame ( input ) } ;
35
- }
49
+ if ( y . Name == null && x . Start <= y . Start && x . End >= y . Start )
50
+ {
51
+ return 0 ;
52
+ }
36
53
37
- private bool TryGetPmipPrettyDumpFunction ( DkmStackContext stackContext , DkmStackWalkFrame frame , out PmipFunctionDataItem pmipFunction )
54
+ return x . Start . CompareTo ( y . Start ) ;
55
+ }
56
+ }
57
+
58
+ public static bool TryGetDescriptionForIP ( ulong ip , out string name )
38
59
{
39
- pmipFunction = stackContext . GetDataItem < PmipFunctionDataItem > ( ) ;
40
- if ( pmipFunction != null )
41
- return true ;
60
+ name = string . Empty ;
61
+ if ( IPs == null )
62
+ return false ;
63
+ int index = Array . BinarySearch ( IPs , new Range ( ) { Start = ip } , comparer ) ;
64
+ int linearIndex = - 1 ;
65
+ for ( var i = 0 ; i < IPs . Length ; i ++ )
66
+ {
67
+ var item = IPs [ i ] ;
68
+ if ( ip > item . Start && ip < item . End )
69
+ {
70
+ linearIndex = i ;
71
+ break ;
72
+ }
73
+ }
42
74
43
- var pmipPrettyDump = PmipUtils . FindInstructionAddress ( "mono_dump_pmip_pretty" , frame ) ;
44
75
45
- if ( pmipPrettyDump == null )
76
+ if ( linearIndex == - 1 )
77
+ {
78
+ if ( index >= 0 )
79
+ GC . KeepAlive ( name ) ;
46
80
return false ;
81
+ }
47
82
48
- pmipFunction = new PmipFunctionDataItem ( stackContext , frame , "0x" + pmipPrettyDump . CPUInstructionPart . InstructionPointer . ToString ( "X" ) ) ;
49
- stackContext . SetDataItem ( DkmDataCreationDisposition . CreateAlways , pmipFunction ) ;
83
+ if ( linearIndex != index )
84
+ GC . KeepAlive ( name ) ;
50
85
86
+ name = IPs [ linearIndex ] . Name ;
51
87
return true ;
52
88
}
89
+
90
+ public static void RefreshStackData ( DkmStackWalkFrame frame )
91
+ {
92
+ try
93
+ {
94
+ var fileName = "D:\\ jon.txt" ;
95
+ var fileInfo = new FileInfo ( fileName ) ;
96
+ if ( fileInfo . Length == previousFileLength )
97
+ return ;
98
+
99
+ var list = new List < Range > ( IPs ? . Length * 2 ?? 1000 ) ;
100
+ using ( var inStream = new FileStream ( fileName , FileMode . Open , FileAccess . Read , FileShare . ReadWrite ) )
101
+ using ( var file = new StreamReader ( inStream ) )
102
+ {
103
+ string line ;
104
+ while ( ( line = file . ReadLine ( ) ) != null )
105
+ {
106
+ const char delemiter = ';' ;
107
+ string [ ] tokens = line . Split ( delemiter ) ;
108
+
109
+ //should never happen, but lets be safe and not get array out of bounds if it does
110
+ if ( tokens . Length != 3 )
111
+ continue ;
112
+
113
+ string startip = tokens [ 0 ] ;
114
+ string endip = tokens [ 1 ] ;
115
+ string description = tokens [ 2 ] ;
116
+
117
+ var startipint = ulong . Parse ( startip , NumberStyles . HexNumber ) ;
118
+ var endipint = ulong . Parse ( endip , NumberStyles . HexNumber ) ;
119
+
120
+ list . Add ( new Range ( ) { Name = description , Start = startipint , End = endipint } ) ;
121
+ }
122
+ }
123
+
124
+ list . Sort ( ( r1 , r2 ) => r1 . Start . CompareTo ( r2 . Start ) ) ;
125
+ IPs = list . ToArray ( ) ;
126
+ previousFileLength = fileInfo . Length ;
127
+ }
128
+ catch ( Exception ex )
129
+ {
130
+ Console . WriteLine ( "Unable to read dumped pmip file: " + ex . Message ) ;
131
+ }
132
+
133
+ }
134
+
135
+ public static DkmStackWalkFrame PmipStackFrame ( DkmStackContext stackContext , DkmStackWalkFrame frame )
136
+ {
137
+ RefreshStackData ( frame ) ;
138
+ string name = null ;
139
+ if ( TryGetDescriptionForIP ( frame . InstructionAddress . CPUInstructionPart . InstructionPointer , out name ) )
140
+ return DkmStackWalkFrame . Create (
141
+ stackContext . Thread ,
142
+ frame . InstructionAddress ,
143
+ frame . FrameBase ,
144
+ frame . FrameSize ,
145
+ frame . Flags ,
146
+ name ,
147
+ frame . Registers ,
148
+ frame . Annotations ) ;
149
+
150
+ return frame ;
151
+ }
53
152
}
54
153
}
0 commit comments