using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; using DbgEngWrapper; using MS.Dbg; namespace DbgShell.TestHarness { [Config(typeof(MyConfig))] public class SymbolSearchPerf { public static readonly DbgEngDebugger Debugger = DbgEngDebugger.OpenDumpFile(@"C:\Users\zhent\Source\Repos\iexplore.DMP"); private static readonly WDbgHelpDia msDiaSession; private static readonly WDbgHelpDia dbghelpDiaSession; static SymbolSearchPerf() { var module = Debugger.GetModuleByName("mshtml").First(); dbghelpDiaSession = Debugger.GetDiaSession2(module); var hr = WDbgHelpDia.CreateDiaSession(module.SymbolFileName, module.BaseAddress, out msDiaSession); if (hr != 0) { Marshal.ThrowExceptionForHR(hr); } } [Benchmark(Baseline = true)] public ulong FindSymbol_Enum() { return Debugger.FindSymbol_Enum("mshtml!g_hIsolatedHeap").Last().Address; } //[Benchmark] public ulong FindSymbol_Enum_ExplicitStar() { return Debugger.FindSymbol_Enum("mshtml!*g_hIsolatedHeap").Last().Address; } //[Benchmark] public ulong FindSymbol_Enum_NoType() { return Debugger.FindSymbol_Enum("mshtml!g_hIsolatedHeap", GlobalSymbolCategory.NoType).Last().Address; } //[Benchmark] public ulong FindSymbol_Enum_Mangled_SymOpts() { uint removeOptions = 0x00000002; //SYMOPT_UNDNAME return Debugger.GetOptionWrappedSymbolEnum(0, removeOptions, "mshtml!_g_hIsolatedHeap", GlobalSymbolCategory.NoType).Last().Address; } //[Benchmark] public ulong FindSymbol_Enum_PublicsOnly_Mangled_SymOpts() { uint addOptions = 0x00004000; //SYMOPT_PUBLICS_ONLY uint removeOptions = 0x00000002; //SYMOPT_UNDNAME return Debugger.GetOptionWrappedSymbolEnum(addOptions, removeOptions, "mshtml!_g_hIsolatedHeap", GlobalSymbolCategory.NoType).Last().Address; } //[Benchmark] public ulong FindSymbol_Search_ForcedStarGlob() { return Debugger.FindSymbol_Search("mshtml!*g_hIsolatedHeap", GlobalSymbolCategory.NoType, default, SymSearchOptions.AllItems).Last().Address; } //[Benchmark] public ulong FindSymbol_Search_SecretUncodumentedWildcard() { return Debugger.FindSymbol_Search("mshtml!_#g_hIsolatedHeap", GlobalSymbolCategory.NoType, default, SymSearchOptions.AllItems).Last().Address; } //[Benchmark] public ulong FindSymbol_Search_Mangled_SymOpts() { uint removeOptions = 0x00000002; //SYMOPT_UNDNAME return Debugger.GetOptionWrappedSymbolSearch(0, removeOptions, "mshtml!_g_hIsolatedHeap", GlobalSymbolCategory.NoType).Last().Address; } //[Benchmark] public ulong findChildren_Mangled_DiaComInterop() { var module = Debugger.GetModuleByName("mshtml").First(); var dia = Debugger.GetDiaSession(module); var globalScope = dia.globalScope; globalScope.findChildren(Dia2Lib.SymTagEnum.SymTagNull, "_g_hIsolatedHeap", 0x1, out var result);//exact match, mangled name var length = (uint)result.count; var item = result.Item(length - 1); return item.relativeVirtualAddress + module.BaseAddress; } //[Benchmark] public ulong findChildren_Unmangled_DiaCppCli() { ulong result = 0; var module = Debugger.GetModuleByName("mshtml").First(); var dia = Debugger.GetDiaSession2(module); var searchFlags = DiaSearchOptions.CaseSensitive | DiaSearchOptions.UndecoratedName; dia.SearchSymbols("_g_hIsolatedHeap", Microsoft.Diagnostics.Runtime.Interop.SymTag.Null, searchFlags, (name, addr) => { result = addr; }); return result; } //[Benchmark] public ulong findChildren_Mangled_DiaCppCli() { ulong result = 0; var module = Debugger.GetModuleByName("mshtml").First(); var dia = Debugger.GetDiaSession2(module); var searchFlags = DiaSearchOptions.CaseSensitive; dia.SearchSymbols("_g_hIsolatedHeap", Microsoft.Diagnostics.Runtime.Interop.SymTag.PublicSymbol, searchFlags, (name, addr) => { result = addr; }); return result; } //[Benchmark] public ulong findChildren_Mangled_DiaCppCli_SearchGlob() { ulong result = 0; var module = Debugger.GetModuleByName("mshtml").First(); var dia = Debugger.GetDiaSession2(module); var searchFlags = DiaSearchOptions.CaseSensitive | DiaSearchOptions.RegularExpression; var searchGlob = DotNet.Globbing.Glob.Parse("*g_hIsolatedHeap"); dia.SearchSymbols(searchGlob, Microsoft.Diagnostics.Runtime.Interop.SymTag.PublicSymbol, searchFlags, (name, addr) => { result = addr; }); return result; } //[Benchmark] public ulong findChildren_Mangled_DiaCppCli_BuiltinSearchGlob() { ulong result = 0; var module = Debugger.GetModuleByName("mshtml").First(); var dia = Debugger.GetDiaSession2(module); var searchFlags = DiaSearchOptions.CaseSensitive | DiaSearchOptions.RegularExpression; dia.SearchSymbols("*g_hIsolatedHeap", Microsoft.Diagnostics.Runtime.Interop.SymTag.PublicSymbol, searchFlags, (name, addr) => { result = addr; }); return result; } [Benchmark] public ulong findChildren_Mangled_DiaCppCli_CachedSession() { ulong result = 0; var searchFlags = DiaSearchOptions.CaseSensitive; dbghelpDiaSession.SearchSymbols("_g_hIsolatedHeap", Microsoft.Diagnostics.Runtime.Interop.SymTag.PublicSymbol, searchFlags, (name, addr) => { result = addr; }); return result; } [Benchmark] public ulong findChildren_Unmangled_msdia140CppCli() { ulong result = 0; var searchFlags = DiaSearchOptions.CaseSensitive | DiaSearchOptions.UndecoratedName; msDiaSession.SearchSymbols("_g_hIsolatedHeap", Microsoft.Diagnostics.Runtime.Interop.SymTag.Null, searchFlags, (name, addr) => { result = addr; }); return result; } [Benchmark] public ulong findChildren_Mangled_msdia140CppCli() { ulong result = 0; var searchFlags = DiaSearchOptions.CaseSensitive; msDiaSession.SearchSymbols("_g_hIsolatedHeap", Microsoft.Diagnostics.Runtime.Interop.SymTag.PublicSymbol, searchFlags, (name, addr) => { result = addr; }); return result; } [Benchmark] public ulong findChildren_Mangled_msdia140CppCli_SearchGlob() { ulong result = 0; var searchFlags = DiaSearchOptions.CaseSensitive | DiaSearchOptions.RegularExpression; var searchGlob = DotNet.Globbing.Glob.Parse("*g_hIsolatedHeap"); msDiaSession.SearchSymbols(searchGlob, Microsoft.Diagnostics.Runtime.Interop.SymTag.PublicSymbol, searchFlags, (name, addr) => { result = addr; }); return result; } [Benchmark] public ulong findChildren_Mangled_msdia140CppCli_BuiltinSearchGlob() { ulong result = 0; var searchFlags = DiaSearchOptions.CaseSensitive | DiaSearchOptions.RegularExpression; msDiaSession.SearchSymbols("*g_hIsolatedHeap", Microsoft.Diagnostics.Runtime.Interop.SymTag.PublicSymbol, searchFlags, (name, addr) => { result = addr; }); return result; } } public static class DbgHelpHelpers { [DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)] private static extern uint SymGetOptions(); [DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)] private static extern uint SymSetOptions(uint SymOptions); public static IEnumerable GetOptionWrappedSymbolEnum(this DbgEngDebugger @this, uint addOptions, uint removeOptions, string search, GlobalSymbolCategory category) { var origOpts = SymGetOptions(); var newOpts = (origOpts | addOptions) & ~removeOptions; SymSetOptions(newOpts); var results = @this.FindSymbol_Enum(search, category).ToList(); SymSetOptions(origOpts); return results; } public static IEnumerable GetOptionWrappedSymbolSearch(this DbgEngDebugger @this, uint addOptions, uint removeOptions, string search, GlobalSymbolCategory category) { var origOpts = SymGetOptions(); var newOpts = (origOpts | addOptions) & ~removeOptions; SymSetOptions(newOpts); var results = @this.FindSymbol_Search(search, category, default, SymSearchOptions.AllItems).ToList(); SymSetOptions(origOpts); return results; } [DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)] private static extern unsafe uint UnDecorateSymbolName([MarshalAs(UnmanagedType.LPWStr)] string name, char* output, uint outputLen, uint flags); private static unsafe string Demangle(string demanglePlz) { var buffer = stackalloc char[1024]; var outputLen = UnDecorateSymbolName(demanglePlz, buffer, 1024, 0); if (outputLen < 1024) { return new string(buffer, 0, (int)outputLen); } return string.Empty; } } }