Code:
public class SymbolHandler : IDisposable
{
[DllImport("dbghelp.dll")]
private static extern uint SymSetOptions(SymInitOptions opts);
[DllImport("dbghelp.dll", CharSet=CharSet.Ansi)]
private static extern IntPtr SymInitialize(IntPtr hProc, string searchPath, bool invade);
[DllImport("dbghelp.dll", CharSet = CharSet.Ansi)]
private static extern ulong SymLoadModuleEx(IntPtr hProc, IntPtr hFile, string imageName,
string moduleName, ulong DllBase, uint dllSize, IntPtr pModLoadData,
SymLoadModuleOptions flags);
[DllImport("dbghelp.dll", CharSet = CharSet.Ansi)]
private static extern bool SymCleanup(IntPtr hProc);
[DllImport("dbghelp.dll", CharSet = CharSet.Ansi)]
private static extern bool SymFromName(IntPtr hProc, IntPtr name, IntPtr symInfo);
[DllImport("kernel32.dll")]
private static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[Flags()]
private enum SymLoadModuleOptions : uint
{
SLMFLAG_NONE = 0x0,
SLMFLAG_VIRTUAL = 0x1,
SLMFLAG_ALT_INDEX = 0x2,
SLMFLAG_NO_SYMBOLS = 0x4
}
[Flags()]
private enum SymInitOptions : uint
{
SYMOPT_CASE_INSENSITIVE = 0x00000001,
SYMOPT_UNDNAME = 0x00000002,
SYMOPT_DEFERRED_LOADS = 0x00000004,
SYMOPT_NO_CPP = 0x00000008,
SYMOPT_LOAD_LINES = 0x00000010,
SYMOPT_OMAP_FIND_NEAREST = 0x00000020,
SYMOPT_LOAD_ANYTHING = 0x00000040,
SYMOPT_IGNORE_CVREC = 0x00000080,
SYMOPT_NO_UNQUALIFIED_LOADS = 0x00000100,
SYMOPT_FAIL_CRITICAL_ERRORS = 0x00000200,
SYMOPT_EXACT_SYMBOLS = 0x00000400,
SYMOPT_ALLOW_ABSOLUTE_SYMBOLS = 0x00000800,
SYMOPT_IGNORE_NT_SYMPATH = 0x00001000,
SYMOPT_INCLUDE_32BIT_MODULES = 0x00002000,
SYMOPT_PUBLICS_ONLY = 0x00004000,
SYMOPT_NO_PUBLICS = 0x00008000,
SYMOPT_AUTO_PUBLICS = 0x00010000,
SYMOPT_NO_IMAGE_SEARCH = 0x00020000,
SYMOPT_SECURE = 0x00040000,
SYMOPT_NO_PROMPTS = 0x00080000,
SYMOPT_OVERWRITE = 0x00100000,
SYMOPT_IGNORE_IMAGEDIR = 0x00200000,
SYMOPT_FLAT_DIRECTORY = 0x00400000,
SYMOPT_FAVOR_COMPRESSED = 0x00800000,
SYMOPT_ALLOW_ZERO_ADDRESS = 0x01000000,
SYMOPT_DISABLE_SYMSRV_AUTODETECT = 0x02000000,
SYMOPT_DEBUG = 0x80000000
}
IntPtr _process;
public void Dispose()
{
Cleanup();
GC.SuppressFinalize(this);
}
public SymbolHandler()
{
Init(GetCurrentProcess(), null);
}
public SymbolHandler(IntPtr hProc)
{
Init(hProc, null);
}
public SymbolHandler(string searchPath)
{
Init(GetCurrentProcess(), searchPath);
}
public SymbolHandler(IntPtr hProc, string searchPath)
{
Init(hProc, searchPath);
}
public void LoadSymbolsForModule(string mod)
{
IntPtr hMod = GetModuleHandle(mod);
if (SymLoadModuleEx(_process, IntPtr.Zero, mod, null, (ulong)hMod.ToInt64(), 0, IntPtr.Zero, SymLoadModuleOptions.SLMFLAG_NONE) == 0)
{
throw new Exception("SymLoadModuleEx() failed. " + Marshal.GetLastWin32Error().ToString());
}
}
public IntPtr GetAddressFromSymbol(string symbol)
{
unsafe
{
var ptrString = Marshal.StringToHGlobalAnsi(symbol);
var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SYMBOL_INFO)) +
symbol.Length + sizeof(ulong) - 1);
SYMBOL_INFO* pInfo = (SYMBOL_INFO*)ptr;
pInfo->MaxNameLen = (uint)symbol.Length + 2;
pInfo->SizeOfStruct = (uint)Marshal.SizeOf(typeof(SYMBOL_INFO));
if (!SymFromName(_process, ptrString, ptr))
{
Marshal.FreeHGlobal(ptrString);
Marshal.FreeHGlobal(ptr);
throw new Exception("SymFromName() failed. " + Marshal.GetLastWin32Error().ToString());
}
Marshal.FreeHGlobal(ptrString);
IntPtr ret = (IntPtr)pInfo->Address;
Marshal.FreeHGlobal(ptr);
return ret;
}
}
private void Init(IntPtr proc, string searchPath)
{
if (_process != IntPtr.Zero)
Cleanup();
SymSetOptions(SymInitOptions.SYMOPT_DEBUG | SymInitOptions.SYMOPT_DEFERRED_LOADS |
SymInitOptions.SYMOPT_UNDNAME);
if (SymInitialize(proc, searchPath, false) == IntPtr.Zero)
{
throw new Exception("SymInitialize() failed. " + Marshal.GetLastWin32Error().ToString());
}
_process = proc;
}
private void Cleanup()
{
if (_process != IntPtr.Zero)
{
if (!SymCleanup(_process))
{
throw new Exception("SymCleanup() failed. " + Marshal.GetLastWin32Error().ToString());
}
_process = IntPtr.Zero;
}
}
[StructLayout(LayoutKind.Sequential)]
private unsafe struct SYMBOL_INFO {
public uint SizeOfStruct;
public uint TypeIndex; // Type Index of symbol
public fixed UInt64 Reserved[2];
public uint Index;
public uint Size;
public UInt64 ModBase; // Base Address of module comtaining this symbol
public uint Flags;
public UInt64 Value; // Value of symbol, ValuePresent should be 1
public UInt64 Address; // Address of symbol including base address of module
public uint Register; // register holding value or pointer to value
public uint Scope; // scope of the symbol
public uint Tag; // pdb classification
public uint NameLen; // Actual length of name
public uint MaxNameLen;
public fixed char Name[1]; // Name of symbol
}
}