@@ -14,13 +14,20 @@ namespace UnityMixedCallstack
14
14
public class UnityMixedCallstackFilter : IDkmCallStackFilter , IDkmLoadCompleteNotification , IDkmModuleInstanceLoadNotification
15
15
{
16
16
private static List < Range > _rangesSortedByIp = new List < Range > ( ) ;
17
+ private static List < Range > _legacyRanges = new List < Range > ( ) ;
17
18
private static FuzzyRangeComparer _comparer = new FuzzyRangeComparer ( ) ;
18
19
private static bool _enabled ;
19
20
private static IVsOutputWindowPane _debugPane ;
20
- private static string _currentFile ;
21
+ private static Dictionary < int , PmipFile > _currentFiles = new Dictionary < int , PmipFile > ( ) ;
21
22
private static FileStream _fileStream ;
22
23
private static StreamReader _fileStreamReader ;
23
24
25
+ struct PmipFile
26
+ {
27
+ public int count ;
28
+ public string path ;
29
+ }
30
+
24
31
public void OnLoadComplete ( DkmProcess process , DkmWorkList workList , DkmEventDescriptor eventDescriptor )
25
32
{
26
33
DisposeStreams ( ) ;
@@ -30,6 +37,8 @@ public void OnLoadComplete(DkmProcess process, DkmWorkList workList, DkmEventDes
30
37
IVsOutputWindow outWindow = Package . GetGlobalService ( typeof ( SVsOutputWindow ) ) as IVsOutputWindow ;
31
38
Guid debugPaneGuid = VSConstants . GUID_OutWindowDebugPane ;
32
39
outWindow ? . GetPane ( ref debugPaneGuid , out _debugPane ) ;
40
+ if ( _debugPane != null )
41
+ _debugPane . OutputString ( "MIXEDCALLSTACK WORKS NOW?!\n " ) ;
33
42
}
34
43
}
35
44
@@ -47,12 +56,21 @@ public DkmStackWalkFrame[] FilterNextFrame(DkmStackContext stackContext, DkmStac
47
56
if ( ! _enabled ) // environment variable not set
48
57
return new [ ] { input } ;
49
58
50
- return new [ ] { UnityMixedStackFrame ( stackContext , input ) } ;
59
+ try
60
+ {
61
+ DkmStackWalkFrame [ ] retVal = new [ ] { UnityMixedStackFrame ( stackContext , input ) } ;
62
+ return retVal ;
63
+ } catch ( Exception ex )
64
+ {
65
+ _debugPane ? . OutputString ( "UNITYMIXEDCALLSTACK :: ip : " + input . Process . LivePart . Id + " threw exception: " + ex . Message + "\n " + ex . StackTrace ) ;
66
+ }
67
+ return new [ ] { input } ;
51
68
}
52
69
53
70
private static DkmStackWalkFrame UnityMixedStackFrame ( DkmStackContext stackContext , DkmStackWalkFrame frame )
54
71
{
55
72
RefreshStackData ( frame . Process . LivePart . Id ) ;
73
+ _debugPane ? . OutputString ( "UNITYMIXEDCALLSTACK :: done refreshing data\n " ) ;
56
74
string name = null ;
57
75
if ( TryGetDescriptionForIp ( frame . InstructionAddress . CPUInstructionPart . InstructionPointer , out name ) )
58
76
return DkmStackWalkFrame . Create (
@@ -88,96 +106,169 @@ private static void DisposeStreams()
88
106
_fileStream ? . Dispose ( ) ;
89
107
_fileStream = null ;
90
108
91
- _currentFile = null ;
92
-
93
109
_rangesSortedByIp . Clear ( ) ;
94
110
}
95
111
112
+ private static bool CheckForUpdatedFiles ( FileInfo [ ] taskFiles )
113
+ {
114
+ bool retVal = false ;
115
+ try
116
+ {
117
+ foreach ( FileInfo taskFile in taskFiles )
118
+ {
119
+ string fName = Path . GetFileNameWithoutExtension ( taskFile . Name ) ;
120
+ string [ ] tokens = fName . Split ( '_' ) ;
121
+ PmipFile pmipFile = new PmipFile ( )
122
+ {
123
+ count = int . Parse ( tokens [ 2 ] ) ,
124
+ path = taskFile . FullName
125
+ } ;
126
+
127
+ _debugPane ? . OutputString ( "MIXEDCALLSTACK :: parsing fName: " + fName + " Tokens length: " + tokens . Length + "\n " ) ;
128
+
129
+ // 3 is legacy and treat everything as root domain
130
+ if ( tokens . Length == 3 &&
131
+ ( ! _currentFiles . TryGetValue ( 0 , out PmipFile curFile ) ||
132
+ curFile . count < pmipFile . count ) )
133
+ {
134
+ _currentFiles [ 0 ] = pmipFile ;
135
+ retVal = true ;
136
+ }
137
+ else if ( tokens . Length == 4 )
138
+ {
139
+ int domainID = int . Parse ( tokens [ 3 ] ) ;
140
+ if ( ! _currentFiles . TryGetValue ( domainID , out PmipFile cFile ) || cFile . count < pmipFile . count )
141
+ {
142
+ _debugPane ? . OutputString ( "MIXEDCALLSTACK :: adding pmip file to list: " + pmipFile . path + "\n " ) ;
143
+ _currentFiles [ domainID ] = pmipFile ;
144
+ retVal = true ;
145
+ }
146
+ }
147
+ }
148
+ } catch ( Exception e )
149
+ {
150
+ _debugPane ? . OutputString ( "MIXEDCALLSTACK :: BAD THINGS HAPPEND: " + e . Message + "\n " ) ;
151
+ _enabled = false ;
152
+ }
153
+ return retVal ;
154
+ }
155
+
96
156
private static void RefreshStackData ( int pid )
97
157
{
98
158
DirectoryInfo taskDirectory = new DirectoryInfo ( Path . GetTempPath ( ) ) ;
99
159
FileInfo [ ] taskFiles = taskDirectory . GetFiles ( "pmip_" + pid + "_*.txt" ) ;
100
160
161
+ _debugPane ? . OutputString ( "MIXEDCALLSTACK :: taskfiles length: " + taskFiles . Length + "\n " ) ;
162
+
101
163
if ( taskFiles . Length < 1 )
102
164
return ;
103
165
104
- Array . Sort ( taskFiles , ( a , b ) => GetFileNameSequenceNum ( a . Name ) . CompareTo ( GetFileNameSequenceNum ( b . Name ) ) ) ;
105
- var fileName = taskFiles [ taskFiles . Length - 1 ] . FullName ;
166
+ if ( ! CheckForUpdatedFiles ( taskFiles ) )
167
+ return ;
106
168
107
- if ( _currentFile != fileName )
169
+ foreach ( PmipFile pmipFile in _currentFiles . Values )
108
170
{
171
+
172
+ _debugPane ? . OutputString ( "MIXEDCALLSTACK :: Reading pmip file: " + pmipFile . path + "\n " ) ;
109
173
DisposeStreams ( ) ;
110
174
try
111
175
{
112
- _fileStream = new FileStream ( fileName , FileMode . Open , FileAccess . Read , FileShare . ReadWrite | FileShare . Delete ) ;
176
+ _fileStream = new FileStream ( pmipFile . path , FileMode . Open , FileAccess . Read , FileShare . ReadWrite | FileShare . Delete ) ;
113
177
_fileStreamReader = new StreamReader ( _fileStream ) ;
114
- _currentFile = fileName ;
115
178
var versionStr = _fileStreamReader . ReadLine ( ) ;
116
179
const char delimiter = ':' ;
117
180
var tokens = versionStr . Split ( delimiter ) ;
118
181
119
182
if ( tokens . Length != 2 )
120
- throw new Exception ( "Failed reading input file " + fileName + ": Incorrect format" ) ;
183
+ throw new Exception ( "Failed reading input file " + pmipFile . path + ": Incorrect format" ) ;
121
184
122
185
if ( ! double . TryParse ( tokens [ 1 ] , NumberStyles . AllowDecimalPoint , CultureInfo . InvariantCulture , out var version ) )
123
- throw new Exception ( "Failed reading input file " + fileName + ": Incorrect version format" ) ;
186
+ throw new Exception ( "Failed reading input file " + pmipFile . path + ": Incorrect version format" ) ;
124
187
125
- if ( version > 1 .0)
126
- throw new Exception ( "Failed reading input file " + fileName + ": A newer version of UnityMixedCallstacks plugin is required to read this file" ) ;
188
+ if ( version > 2 .0)
189
+ throw new Exception ( "Failed reading input file " + pmipFile . path + ": A newer version of UnityMixedCallstacks plugin is required to read this file" ) ;
127
190
}
128
191
catch ( Exception ex )
129
192
{
130
- _debugPane ? . OutputString ( "Unable to read dumped pmip file: " + ex . Message + "\n " ) ;
193
+ _debugPane ? . OutputString ( "MIXEDCALLSTACK :: Unable to read dumped pmip file: " + ex . Message + "\n " ) ;
131
194
DisposeStreams ( ) ;
132
195
_enabled = false ;
133
196
return ;
134
197
}
135
- }
136
198
137
- try
138
- {
139
- string line ;
140
- while ( ( line = _fileStreamReader . ReadLine ( ) ) != null )
199
+ try
141
200
{
142
- const char delemiter = ';' ;
143
- var tokens = line . Split ( delemiter ) ;
144
-
145
- //should never happen, but lets be safe and not get array out of bounds if it does
146
- if ( tokens . Length != 3 )
147
- continue ;
148
-
149
- var startip = tokens [ 0 ] ;
150
- var endip = tokens [ 1 ] ;
151
- var description = tokens [ 2 ] ;
152
-
153
- var startiplong = ulong . Parse ( startip , NumberStyles . HexNumber ) ;
154
- var endipint = ulong . Parse ( endip , NumberStyles . HexNumber ) ;
155
- _rangesSortedByIp . Add ( new Range ( ) { Name = description , Start = startiplong , End = endipint } ) ;
201
+ string line ;
202
+ while ( ( line = _fileStreamReader . ReadLine ( ) ) != null )
203
+ {
204
+ const char delemiter = ';' ;
205
+ var tokens = line . Split ( delemiter ) ;
206
+
207
+ //should never happen, but lets be safe and not get array out of bounds if it does
208
+ if ( tokens . Length == 3 || tokens . Length == 4 )
209
+ {
210
+ string startip = tokens [ 0 ] ;
211
+ string endip = tokens [ 1 ] ;
212
+ string description = tokens [ 2 ] ;
213
+ string file = "" ;
214
+ if ( tokens . Length == 4 )
215
+ file = tokens [ 3 ] ;
216
+
217
+ if ( startip . StartsWith ( "---" ) )
218
+ {
219
+ startip = startip . Remove ( 0 , 3 ) ;
220
+ }
221
+
222
+ var startiplong = ulong . Parse ( startip , NumberStyles . HexNumber ) ;
223
+ var endipint = ulong . Parse ( endip , NumberStyles . HexNumber ) ;
224
+ if ( tokens [ 0 ] . StartsWith ( "---" ) )
225
+ {
226
+ // legacy stored in new pmip file
227
+ _legacyRanges . Add ( new Range ( ) { Name = description , File = file , Start = startiplong , End = endipint } ) ;
228
+ }
229
+ else
230
+ _rangesSortedByIp . Add ( new Range ( ) { Name = description , File = file , Start = startiplong , End = endipint } ) ;
231
+ }
232
+ }
233
+ _debugPane ? . OutputString ( "MIXEDCALLSTACK :: map now has " + _rangesSortedByIp . Count + " entries! legacy map has: " + _legacyRanges . Count + "\n " ) ;
234
+ }
235
+ catch ( Exception ex )
236
+ {
237
+ _debugPane ? . OutputString ( "MIXEDCALLSTACK :: Unable to read dumped pmip file: " + ex . Message + "\n " ) ;
238
+ DisposeStreams ( ) ;
239
+ _enabled = false ;
240
+ return ;
156
241
}
157
- }
158
- catch ( Exception ex )
159
- {
160
- _debugPane ? . OutputString ( "Unable to read dumped pmip file: " + ex . Message + "\n " ) ;
161
- DisposeStreams ( ) ;
162
- _enabled = false ;
163
- return ;
164
242
}
165
243
244
+ _legacyRanges . Sort ( ( r1 , r2 ) => r1 . Start . CompareTo ( r2 . Start ) ) ;
166
245
_rangesSortedByIp . Sort ( ( r1 , r2 ) => r1 . Start . CompareTo ( r2 . Start ) ) ;
167
246
}
168
247
169
248
private static bool TryGetDescriptionForIp ( ulong ip , out string name )
170
249
{
171
250
name = string . Empty ;
172
251
252
+ _debugPane ? . OutputString ( "MIXEDCALLSTACK :: Looking for ip: " + String . Format ( "{0:X}" , ip ) + "\n " ) ;
173
253
var rangeToFindIp = new Range ( ) { Start = ip } ;
174
254
var index = _rangesSortedByIp . BinarySearch ( rangeToFindIp , _comparer ) ;
255
+
256
+ if ( index >= 0 )
257
+ {
258
+ _debugPane ? . OutputString ( "MIXEDCALLSTACK :: SUCCESS!!\n " ) ;
259
+ name = _rangesSortedByIp [ index ] . Name ;
260
+ return true ;
261
+ }
175
262
176
- if ( index < 0 )
177
- return false ;
263
+ index = _legacyRanges . BinarySearch ( rangeToFindIp , _comparer ) ;
264
+ if ( index >= 0 )
265
+ {
266
+ _debugPane ? . OutputString ( "MIXEDCALLSTACK :: LEGACY SUCCESS!! " + String . Format ( "{0:X}" , _legacyRanges [ index ] . Start ) + " -- " + String . Format ( "{0:X}" , _legacyRanges [ index ] . End ) + "\n " ) ;
267
+ name = _legacyRanges [ index ] . Name ;
268
+ return true ;
269
+ }
178
270
179
- name = _rangesSortedByIp [ index ] . Name ;
180
- return true ;
271
+ return false ;
181
272
}
182
273
183
274
public void OnModuleInstanceLoad ( DkmModuleInstance moduleInstance , DkmWorkList workList , DkmEventDescriptorS eventDescriptor )
0 commit comments