30
30
31
31
namespace NtApiDotNet . Win32 . Debugger
32
32
{
33
- internal sealed partial class DbgHelpSymbolResolver : ISymbolResolver , ISymbolTypeResolver , IDisposable
33
+ internal sealed partial class DbgHelpSymbolResolver : ISymbolResolver , ISymbolTypeResolver , ISymbolEnumerator , IDisposable
34
34
{
35
35
public static string DEFAULT_SYMSRV = "https://msdl.microsoft.com/download/symbols" ;
36
36
@@ -215,6 +215,13 @@ delegate bool SymGetHomeDirectoryW(
215
215
HomeDirectoryType type ,
216
216
[ In , Out ] StringBuilder dir ,
217
217
IntPtr size
218
+ ) ;
219
+
220
+ [ UnmanagedFunctionPointer ( CallingConvention . StdCall , CharSet = CharSet . Unicode , SetLastError = true ) ]
221
+ delegate bool SymGetDiaSession (
222
+ SafeKernelObjectHandle hProcess ,
223
+ long BaseOfDll ,
224
+ [ MarshalAs ( UnmanagedType . Interface ) ] out IDiaSession DiaSession
218
225
) ;
219
226
220
227
private readonly SafeLoadLibraryHandle _dbghelp_lib ;
@@ -239,6 +246,7 @@ IntPtr size
239
246
private readonly SymSetContext _sym_set_context ;
240
247
private readonly SymEnumSymbolsW _sym_enum_symbols ;
241
248
private readonly SymGetHomeDirectoryW _sym_get_home_directory ;
249
+ private readonly SymGetDiaSession _sym_get_dia_session ;
242
250
private IEnumerable < SymbolLoadedModule > _loaded_modules ;
243
251
private readonly TextWriter _trace_writer ;
244
252
private readonly bool _trace_symbol_loading ;
@@ -250,6 +258,11 @@ IntPtr size
250
258
private void GetFunc < T > ( ref T f ) where T : Delegate
251
259
{
252
260
f = _dbghelp_lib . GetFunctionPointer < T > ( ) ;
261
+ }
262
+
263
+ private void GetFuncNoThrow < T > ( ref T f ) where T : Delegate
264
+ {
265
+ f = _dbghelp_lib . GetFunctionPointer < T > ( false ) ;
253
266
}
254
267
255
268
private void GetFunc < T > ( ref T f , string name ) where T : Delegate
@@ -267,6 +280,29 @@ private static string GetNameFromSymbolInfo(SafeStructureInOutBuffer<SYMBOL_INFO
267
280
return buffer . Data . ReadNulTerminatedUnicodeString ( ) ;
268
281
}
269
282
283
+ private DllMachineType GetSymbolMachineType ( SYMBOL_INFO sym_info )
284
+ {
285
+ IDiaSession session = null ;
286
+ IDiaSymbol symbol = null ;
287
+ try
288
+ {
289
+ if ( _sym_get_dia_session == null || ! _sym_get_dia_session ( Handle , sym_info . ModBase , out session ) )
290
+ return DllMachineType . UNKNOWN ;
291
+
292
+ if ( session . findSymbolByVA ( sym_info . Address , sym_info . Tag , out symbol ) != 0 )
293
+ return DllMachineType . UNKNOWN ;
294
+
295
+ return ( DllMachineType ) symbol . machineType ;
296
+ }
297
+ finally
298
+ {
299
+ if ( symbol != null )
300
+ Marshal . ReleaseComObject ( symbol ) ;
301
+ if ( session != null )
302
+ Marshal . ReleaseComObject ( session ) ;
303
+ }
304
+ }
305
+
270
306
private static SafeStructureInOutBuffer < SYMBOL_INFO > MapSymbolInfo ( IntPtr symbol_info )
271
307
{
272
308
int base_size = Marshal . SizeOf ( typeof ( SYMBOL_INFO ) ) ;
@@ -707,7 +743,8 @@ private DataSymbolInformation GetSymbolInfoForAddress(IntPtr address)
707
743
var result = sym_info . Result ;
708
744
709
745
return new DataSymbolInformation ( result . Tag , result . Size , result . TypeIndex ,
710
- result . Address , GetModuleForAddress ( new IntPtr ( result . ModBase ) ) , GetNameFromSymbolInfo ( sym_info ) ) ;
746
+ result . Address , GetModuleForAddress ( new IntPtr ( result . ModBase ) ) ,
747
+ GetNameFromSymbolInfo ( sym_info ) , GetSymbolMachineType ( result ) ) ;
711
748
}
712
749
713
750
return null ;
@@ -724,7 +761,8 @@ private DataSymbolInformation GetSymbolInfoForName(string name)
724
761
}
725
762
var result = sym_info . Result ;
726
763
return new DataSymbolInformation ( result . Tag , result . Size , result . TypeIndex ,
727
- result . Address , GetModuleForAddress ( new IntPtr ( result . ModBase ) ) , GetNameFromSymbolInfo ( sym_info ) ) ;
764
+ result . Address , GetModuleForAddress ( new IntPtr ( result . ModBase ) ) ,
765
+ GetNameFromSymbolInfo ( sym_info ) , GetSymbolMachineType ( result ) ) ;
728
766
}
729
767
}
730
768
@@ -850,8 +888,20 @@ private Tuple<string, Uri> GetFallbackSymbolPaths(string symbol_path)
850
888
}
851
889
}
852
890
return Tuple . Create ( cache_path , server_path ) ;
891
+ }
892
+
893
+ private bool GetSymbolInfo ( List < SymbolInformation > symbols , IntPtr symbol_info , Dictionary < long , SymbolLoadedModule > modules )
894
+ {
895
+ using ( var sym_info = MapSymbolInfo ( symbol_info ) )
896
+ {
897
+ var result = sym_info . Result ;
898
+ var symbol = new DataSymbolInformation ( result . Tag , result . Size , result . TypeIndex ,
899
+ result . Address , GetModuleForAddress ( new IntPtr ( result . ModBase ) ) ,
900
+ GetNameFromSymbolInfo ( sym_info ) , GetSymbolMachineType ( result ) ) ;
901
+ symbols . Add ( symbol ) ;
902
+ return true ;
903
+ }
853
904
}
854
-
855
905
#endregion
856
906
857
907
#region Public Methods
@@ -1058,6 +1108,23 @@ public TypeInformation GetTypeForSymbolByAddress(IntPtr address)
1058
1108
var ret = CreateType ( type_cache , symbol . Tag , symbol . Module . BaseAddress . ToInt64 ( ) , symbol . TypeIndex , symbol . Size , symbol . Module , symbol . Name , symbol . Address ) ;
1059
1109
type_cache . FixupPointerTypes ( ) ;
1060
1110
return ret ;
1111
+ }
1112
+
1113
+ public IEnumerable < SymbolInformation > EnumerateSymbols ( IntPtr base_address , string mask )
1114
+ {
1115
+ if ( string . IsNullOrWhiteSpace ( mask ) )
1116
+ {
1117
+ throw new ArgumentException ( $ "'{ nameof ( mask ) } ' cannot be null or whitespace.", nameof ( mask ) ) ;
1118
+ }
1119
+
1120
+ List < SymbolInformation > symbols = new List < SymbolInformation > ( ) ;
1121
+ Dictionary < long , SymbolLoadedModule > modules = GetLoadedModules ( ) . ToDictionary ( m => m . BaseAddress . ToInt64 ( ) ) ;
1122
+ if ( ! _sym_enum_symbols ( Handle , base_address . ToInt64 ( ) ,
1123
+ mask , ( s , z , x ) => GetSymbolInfo ( symbols , s , modules ) , IntPtr . Zero ) )
1124
+ {
1125
+ Win32Utils . GetLastWin32Error ( ) . ToNtException ( ) ;
1126
+ }
1127
+ return symbols . AsReadOnly ( ) ;
1061
1128
}
1062
1129
1063
1130
#endregion
@@ -1091,6 +1158,7 @@ internal DbgHelpSymbolResolver(NtProcess process, string dbghelp_path, string sy
1091
1158
GetFunc ( ref _sym_enum_symbols ) ;
1092
1159
GetFunc ( ref _sym_set_context ) ;
1093
1160
GetFunc ( ref _sym_get_home_directory ) ;
1161
+ GetFuncNoThrow ( ref _sym_get_dia_session ) ;
1094
1162
1095
1163
_trace_writer = trace_writer ?? new TraceTextWriter ( ) ;
1096
1164
SymOptions options = SymOptions . INCLUDE_32BIT_MODULES | SymOptions . UNDNAME | SymOptions . DEFERRED_LOADS ;
@@ -1178,8 +1246,8 @@ void IDisposable.Dispose()
1178
1246
{
1179
1247
Dispose ( true ) ;
1180
1248
GC . SuppressFinalize ( this ) ;
1181
- }
1182
-
1249
+ }
1250
+
1183
1251
#endregion
1184
1252
}
1185
1253
}
0 commit comments