6
6
*
7
7
* VERSION: 1.00
8
8
*
9
- * DATE: 17 Dec 2024
9
+ * DATE: 19 Dec 2024
10
10
*
11
11
* MS Symbols resolver support class.
12
12
*
16
16
* PARTICULAR PURPOSE.
17
17
*
18
18
*******************************************************************************/
19
- using System . Diagnostics ;
19
+ using Microsoft . Win32 . SafeHandles ;
20
+ using System . Collections . Concurrent ;
20
21
using System . Runtime . InteropServices ;
21
22
using System . Text ;
22
23
@@ -25,24 +26,38 @@ namespace WinDepends;
25
26
public static class CSymbolResolver
26
27
{
27
28
#region "P/Invoke stuff"
28
- [ UnmanagedFunctionPointer ( CallingConvention . Winapi , SetLastError = true ) ]
29
- public delegate IntPtr SymLoadModuleExDelegate ( IntPtr hProcess , IntPtr hFile , string ImageName , string ModuleName , long BaseOfDll , int SizeOfDll , IntPtr Data , int Flags ) ;
30
-
31
- [ UnmanagedFunctionPointer ( CallingConvention . Winapi , SetLastError = true ) ]
32
- public delegate bool SymInitializeDelegate ( IntPtr hProcess , string UserSearchPath , bool fInvadeProcess ) ;
33
-
34
- [ UnmanagedFunctionPointer ( CallingConvention . Winapi , SetLastError = true ) ]
35
- public delegate bool SymCleanupDelegate ( IntPtr hProcess ) ;
36
-
37
- [ UnmanagedFunctionPointer ( CallingConvention . Winapi , SetLastError = true ) ]
38
- public delegate bool SymFromAddrDelegate ( IntPtr hProcess , long Address , out long Displacement , ref SYMBOL_INFO Symbol ) ;
39
-
40
- [ UnmanagedFunctionPointer ( CallingConvention . Winapi , SetLastError = true ) ]
41
- public delegate uint UnDecorateSymbolNameDelegate (
42
- [ MarshalAs ( UnmanagedType . LPWStr ) ] string name ,
43
- [ Out , MarshalAs ( UnmanagedType . LPWStr ) ] StringBuilder outputString ,
44
- int maxStringLength ,
45
- UNDNAME flags ) ;
29
+ public const uint SYMOPT_CASE_INSENSITIVE = 0x00000001 ;
30
+ public const uint SYMOPT_UNDNAME = 0x00000002 ;
31
+ public const uint SYMOPT_DEFERRED_LOADS = 0x00000004 ;
32
+ public const uint SYMOPT_NO_CPP = 0x00000008 ;
33
+ public const uint SYMOPT_LOAD_LINES = 0x00000010 ;
34
+ public const uint SYMOPT_OMAP_FIND_NEAREST = 0x00000020 ;
35
+ public const uint SYMOPT_LOAD_ANYTHING = 0x00000040 ;
36
+ public const uint SYMOPT_IGNORE_CVREC = 0x00000080 ;
37
+ public const uint SYMOPT_NO_UNQUALIFIED_LOADS = 0x00000100 ;
38
+ public const uint SYMOPT_FAIL_CRITICAL_ERRORS = 0x00000200 ;
39
+ public const uint SYMOPT_EXACT_SYMBOLS = 0x00000400 ;
40
+ public const uint SYMOPT_ALLOW_ABSOLUTE_SYMBOLS = 0x00000800 ;
41
+ public const uint SYMOPT_IGNORE_NT_SYMPATH = 0x00001000 ;
42
+ public const uint SYMOPT_INCLUDE_32BIT_MODULES = 0x00002000 ;
43
+ public const uint SYMOPT_PUBLICS_ONLY = 0x00004000 ;
44
+ public const uint SYMOPT_NO_PUBLICS = 0x00008000 ;
45
+ public const uint SYMOPT_AUTO_PUBLICS = 0x00010000 ;
46
+ public const uint SYMOPT_NO_IMAGE_SEARCH = 0x00020000 ;
47
+ public const uint SYMOPT_SECURE = 0x00040000 ;
48
+ public const uint SYMOPT_NO_PROMPTS = 0x00080000 ;
49
+ public const uint SYMOPT_OVERWRITE = 0x00100000 ;
50
+ public const uint SYMOPT_IGNORE_IMAGEDIR = 0x00200000 ;
51
+ public const uint SYMOPT_FLAT_DIRECTORY = 0x00400000 ;
52
+ public const uint SYMOPT_FAVOR_COMPRESSED = 0x00800000 ;
53
+ public const uint SYMOPT_ALLOW_ZERO_ADDRESS = 0x01000000 ;
54
+ public const uint SYMOPT_DISABLE_SYMSRV_AUTODETECT = 0x02000000 ;
55
+ public const uint SYMOPT_READONLY_CACHE = 0x04000000 ;
56
+ public const uint SYMOPT_SYMPATH_LAST = 0x08000000 ;
57
+ public const uint SYMOPT_DISABLE_FAST_SYMBOLS = 0x10000000 ;
58
+ public const uint SYMOPT_DISABLE_SYMSRV_TIMEOUT = 0x20000000 ;
59
+ public const uint SYMOPT_DISABLE_SRVSTAR_ON_STARTUP = 0x40000000 ;
60
+ public const uint SYMOPT_DEBUG = 0x80000000 ;
46
61
47
62
[ Flags ]
48
63
public enum UNDNAME : uint
@@ -99,29 +114,75 @@ public enum UNDNAME : uint
99
114
NoThrowSignatures = 0x0100 ,
100
115
}
101
116
102
- [ StructLayout ( LayoutKind . Sequential ) ]
117
+ [ StructLayout ( LayoutKind . Sequential , CharSet = CharSet . Unicode ) ]
103
118
public struct SYMBOL_INFO
104
119
{
105
- public uint SizeOfStruct ;
106
- public uint TypeIndex ;
107
- public ulong Reserved ;
108
- public ulong ModBase ;
109
- public uint Flags ;
110
- public ulong Value ;
111
- public ulong Address ;
112
- public uint Register ;
113
- public uint Scope ;
114
- public uint Tag ;
115
- public uint NameLen ;
116
- public uint MaxNameLen ;
117
- [ MarshalAs ( UnmanagedType . ByValTStr , SizeConst = 1024 ) ]
120
+ public UInt32 SizeOfStruct ;
121
+ public UInt32 TypeIndex ;
122
+ public UInt64 Reserved ;
123
+ public UInt64 Reserved2 ;
124
+ public UInt32 Index ;
125
+ public UInt32 Size ;
126
+ public UInt64 ModBase ;
127
+ public UInt32 Flags ;
128
+ public UInt64 Value ;
129
+ public UInt64 Address ;
130
+ public UInt32 Register ;
131
+ public UInt32 Scope ;
132
+ public UInt32 Tag ;
133
+ public UInt32 NameLen ;
134
+ public UInt32 MaxNameLen ;
135
+ [ MarshalAs ( UnmanagedType . ByValTStr , SizeConst = 2000 ) ]
118
136
public string Name ;
119
137
}
120
138
#endregion
121
139
140
+ static readonly UInt32 MAX_SYM_NAME = 2000 ;
141
+ static readonly UInt32 SIZE_OF_SYMBOL_INFO = ( uint ) Marshal . SizeOf ( typeof ( SYMBOL_INFO ) ) - ( MAX_SYM_NAME * 2 ) ;
142
+
122
143
// P/Invoke delegates
144
+ [ UnmanagedFunctionPointer ( CallingConvention . Winapi , SetLastError = true ) ]
145
+ delegate IntPtr SymLoadModuleExDelegate ( SafeProcessHandle hProcess ,
146
+ IntPtr hFile ,
147
+ [ MarshalAs ( UnmanagedType . LPWStr ) ] string ImageName ,
148
+ [ MarshalAs ( UnmanagedType . LPWStr ) ] string ModuleName ,
149
+ UInt64 BaseOfDll ,
150
+ int SizeOfDll ,
151
+ IntPtr Data ,
152
+ int Flags ) ;
153
+
154
+ [ UnmanagedFunctionPointer ( CallingConvention . Winapi , SetLastError = true ) ]
155
+ delegate bool SymInitializeDelegate ( SafeProcessHandle hProcess ,
156
+ [ MarshalAs ( UnmanagedType . LPWStr ) ] string UserSearchPath ,
157
+ bool fInvadeProcess ) ;
158
+
159
+ [ UnmanagedFunctionPointer ( CallingConvention . Winapi , SetLastError = true ) ]
160
+ delegate bool SymCleanupDelegate ( SafeProcessHandle hProcess ) ;
161
+
162
+ [ UnmanagedFunctionPointer ( CallingConvention . Winapi , SetLastError = true ) ]
163
+ delegate bool SymFromAddrDelegate (
164
+ SafeProcessHandle hProcess ,
165
+ UInt64 Address ,
166
+ out UInt64 Displacement ,
167
+ ref SYMBOL_INFO Symbol ) ;
168
+
169
+ [ UnmanagedFunctionPointer ( CallingConvention . Winapi , SetLastError = true ) ]
170
+ delegate uint SymGetOptionsDelegate ( ) ;
171
+
172
+ [ UnmanagedFunctionPointer ( CallingConvention . Winapi , SetLastError = true ) ]
173
+ delegate uint SymSetOptionsDelegate ( uint options ) ;
174
+
175
+ [ UnmanagedFunctionPointer ( CallingConvention . Winapi , SetLastError = true ) ]
176
+ delegate uint UnDecorateSymbolNameDelegate (
177
+ [ MarshalAs ( UnmanagedType . LPWStr ) ] string name ,
178
+ [ Out , MarshalAs ( UnmanagedType . LPWStr ) ] StringBuilder outputString ,
179
+ int maxStringLength ,
180
+ UNDNAME flags ) ;
181
+
123
182
static SymLoadModuleExDelegate SymLoadModuleEx ;
124
183
static SymInitializeDelegate SymInitialize ;
184
+ static SymGetOptionsDelegate SymGetOptions ;
185
+ static SymSetOptionsDelegate SymSetOptions ;
125
186
static SymCleanupDelegate SymCleanup ;
126
187
static SymFromAddrDelegate SymFromAddr ;
127
188
static UnDecorateSymbolNameDelegate UnDecorateSymbolName ;
@@ -132,23 +193,55 @@ public struct SYMBOL_INFO
132
193
public static string DllsPath { get ; set ; }
133
194
public static string StorePath { get ; set ; }
134
195
196
+ static readonly SafeProcessHandle CurrentProcess = new SafeProcessHandle ( new IntPtr ( - 1 ) , false ) ;
197
+
198
+ private struct SymModuleItem
199
+ {
200
+ public IntPtr BaseAddress ;
201
+ }
202
+
203
+ static readonly ConcurrentDictionary < string , SymModuleItem > symModulesCache = new ( ) ;
204
+
205
+ public static void CacheSymModule ( string symModuleName , IntPtr baseAddress )
206
+ {
207
+ var item = new SymModuleItem { BaseAddress = baseAddress } ;
208
+ symModulesCache . AddOrUpdate ( symModuleName , item , ( key , oldValue ) => item ) ;
209
+ }
210
+
211
+ public static IntPtr RetrieveCachedSymModule ( string symModuleName )
212
+ {
213
+ if ( symModulesCache . TryGetValue ( symModuleName , out var item ) )
214
+ {
215
+ return item . BaseAddress ;
216
+ }
217
+ else
218
+ {
219
+ return IntPtr . Zero ;
220
+ }
221
+ }
222
+
135
223
private static void ClearDelegates ( )
136
224
{
137
225
SymLoadModuleEx = null ;
138
226
SymInitialize = null ;
139
227
SymCleanup = null ;
140
228
SymFromAddr = null ;
141
229
UnDecorateSymbolName = null ;
230
+ SymSetOptions = null ;
231
+ SymGetOptions = null ;
142
232
}
143
233
private static bool InitializeDelegates ( )
144
234
{
145
235
UnDecorateSymbolName = Marshal . GetDelegateForFunctionPointer < UnDecorateSymbolNameDelegate > ( NativeMethods . GetProcAddress ( DbgHelpModule , "UnDecorateSymbolNameW" ) ) ;
146
236
SymLoadModuleEx = Marshal . GetDelegateForFunctionPointer < SymLoadModuleExDelegate > ( NativeMethods . GetProcAddress ( DbgHelpModule , "SymLoadModuleExW" ) ) ;
147
- SymInitialize = Marshal . GetDelegateForFunctionPointer < SymInitializeDelegate > ( NativeMethods . GetProcAddress ( DbgHelpModule , "SymInitialize" ) ) ;
237
+ SymGetOptions = Marshal . GetDelegateForFunctionPointer < SymGetOptionsDelegate > ( NativeMethods . GetProcAddress ( DbgHelpModule , "SymGetOptions" ) ) ;
238
+ SymSetOptions = Marshal . GetDelegateForFunctionPointer < SymSetOptionsDelegate > ( NativeMethods . GetProcAddress ( DbgHelpModule , "SymSetOptions" ) ) ;
239
+ SymInitialize = Marshal . GetDelegateForFunctionPointer < SymInitializeDelegate > ( NativeMethods . GetProcAddress ( DbgHelpModule , "SymInitializeW" ) ) ;
240
+ SymFromAddr = Marshal . GetDelegateForFunctionPointer < SymFromAddrDelegate > ( NativeMethods . GetProcAddress ( DbgHelpModule , "SymFromAddrW" ) ) ;
148
241
SymCleanup = Marshal . GetDelegateForFunctionPointer < SymCleanupDelegate > ( NativeMethods . GetProcAddress ( DbgHelpModule , "SymCleanup" ) ) ;
149
- SymFromAddr = Marshal . GetDelegateForFunctionPointer < SymFromAddrDelegate > ( NativeMethods . GetProcAddress ( DbgHelpModule , "SymFromAddr" ) ) ;
150
242
151
- if ( UnDecorateSymbolName == null || SymLoadModuleEx == null || SymInitialize == null || SymCleanup == null || SymFromAddr == null )
243
+ if ( UnDecorateSymbolName == null || SymLoadModuleEx == null || SymGetOptions == null || SymSetOptions == null ||
244
+ SymInitialize == null || SymCleanup == null || SymFromAddr == null )
152
245
{
153
246
ClearDelegates ( ) ;
154
247
return false ;
@@ -157,17 +250,25 @@ private static bool InitializeDelegates()
157
250
return true ;
158
251
}
159
252
160
- public static void AllocateSymbolResolver ( string dllsPath , string storePath )
253
+ public static void AllocateSymbolResolver ( string dllPath , string storePath )
161
254
{
162
- DllsPath = string . IsNullOrEmpty ( dllsPath ) ? CConsts . DbgHelpDll : Path . Combine ( dllsPath , CConsts . DbgHelpDll ) ;
255
+ DllsPath = Path . Combine ( dllPath , CConsts . DbgHelpDll ) ;
163
256
StorePath = storePath ;
164
257
165
- DbgHelpModule = NativeMethods . LoadLibraryEx ( DllsPath , IntPtr . Zero , NativeMethods . LoadLibraryFlags . LOAD_LIBRARY_SEARCH_SYSTEM32 ) ;
258
+ DbgHelpModule = NativeMethods . LoadLibraryEx ( DllsPath , IntPtr . Zero , 0 ) ;
166
259
if ( DbgHelpModule != IntPtr . Zero )
167
260
{
168
261
if ( InitializeDelegates ( ) )
169
262
{
170
- SymbolsInitialized = SymInitialize ( Process . GetCurrentProcess ( ) . Handle , StorePath , false ) ;
263
+ var symOptions = SymGetOptions ( ) ;
264
+
265
+ //SymSetOptions((symOptions | SYMOPT_DEFERRED_LOADS | SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_PUBLICS_ONLY) & ~SYMOPT_UNDNAME);
266
+ SymSetOptions ( symOptions | SYMOPT_DEFERRED_LOADS |
267
+ SYMOPT_CASE_INSENSITIVE |
268
+ SYMOPT_UNDNAME |
269
+ SYMOPT_AUTO_PUBLICS ) ;
270
+
271
+ SymbolsInitialized = SymInitialize ( CurrentProcess , StorePath , false ) ;
171
272
}
172
273
}
173
274
@@ -179,11 +280,12 @@ public static void ReleaseSymbolResolver()
179
280
{
180
281
if ( SymbolsInitialized )
181
282
{
182
- SymCleanup ( Process . GetCurrentProcess ( ) . Handle ) ;
283
+ SymCleanup ( CurrentProcess ) ;
183
284
}
184
285
NativeMethods . FreeLibrary ( DbgHelpModule ) ;
185
286
DbgHelpModule = IntPtr . Zero ;
186
287
ClearDelegates ( ) ;
288
+ SymbolsInitialized = false ;
187
289
}
188
290
}
189
291
@@ -208,42 +310,47 @@ static internal string UndecorateFunctionName(string functionName)
208
310
209
311
return string . Empty ;
210
312
}
211
- static internal bool LoadPDBFile ( string pdbFileName )
313
+ static internal IntPtr LoadModule ( string fileName , UInt64 baseAddress )
212
314
{
213
- if ( SymbolsInitialized == false )
315
+ if ( ! SymbolsInitialized )
214
316
{
215
- return false ;
317
+ return IntPtr . Zero ;
216
318
}
217
319
else
218
320
{
219
- return IntPtr . Zero != SymLoadModuleEx ( Process . GetCurrentProcess ( ) . Handle ,
220
- IntPtr . Zero ,
221
- pdbFileName ,
222
- null ,
223
- 0 ,
224
- 0 ,
225
- IntPtr . Zero ,
226
- 0 ) ;
321
+ return SymLoadModuleEx ( CurrentProcess ,
322
+ IntPtr . Zero ,
323
+ fileName ,
324
+ null ,
325
+ baseAddress ,
326
+ 0 ,
327
+ IntPtr . Zero ,
328
+ 0 ) ;
227
329
}
228
330
}
229
331
230
- public static bool QuerySymbolForAddress ( long address , out string symbolName )
332
+ public static bool QuerySymbolForAddress ( UInt64 address , out string symbolName )
231
333
{
232
- if ( SymbolsInitialized == false )
334
+ symbolName = null ;
335
+
336
+ if ( ! SymbolsInitialized )
233
337
{
234
- symbolName = null ;
235
338
return false ;
236
339
}
237
340
238
- SYMBOL_INFO symbol = new ( ) ;
239
- symbol . SizeOfStruct = ( uint ) Marshal . SizeOf ( symbol ) ;
341
+ var symbolInfo = new SYMBOL_INFO
342
+ {
343
+ SizeOfStruct = SIZE_OF_SYMBOL_INFO ,
344
+ MaxNameLen = MAX_SYM_NAME
345
+ } ;
240
346
241
- if ( SymFromAddr ( Process . GetCurrentProcess ( ) . Handle , address , out long displacement , ref symbol ) )
347
+ UInt64 displacement = 0 ;
348
+ if ( SymFromAddr ( CurrentProcess , address , out displacement , ref symbolInfo ) )
242
349
{
243
- symbolName = symbol . Name ;
350
+ symbolName = symbolInfo . Name ;
244
351
return true ;
245
352
}
246
- symbolName = null ;
353
+
247
354
return false ;
248
355
}
249
356
0 commit comments