internal Symbol GetSymbol(string symbolName) { // Initialise a native symbol handler if (!Dbghelp.SymSetOptions(SymbolOptions.UndecorateName).HasFlag(SymbolOptions.UndecorateName)) { throw new Win32Exception(); } if (!Dbghelp.SymInitialize(Kernel32.GetCurrentProcess(), null, false)) { throw new Win32Exception(); } try { const int pseudoDllAddress = 0x1000; // Load the symbol file into the symbol handler var symbolFileSize = new FileInfo(_pdbFilePath).Length; var symbolTableAddress = Dbghelp.SymLoadModuleEx(Kernel32.GetCurrentProcess(), IntPtr.Zero, _pdbFilePath, null, pseudoDllAddress, (int)symbolFileSize, IntPtr.Zero, 0); if (symbolTableAddress == 0) { throw new Win32Exception(); } try { // Initialise a buffer to store the symbol information Span <byte> symbolInformationBytes = stackalloc byte[(Unsafe.SizeOf <SymbolInfo>() + sizeof(char) * Constants.MaxSymbolNameLength + sizeof(long) - 1) / sizeof(long)]; MemoryMarshal.Write(symbolInformationBytes, ref Unsafe.AsRef(new SymbolInfo(Unsafe.SizeOf <SymbolInfo>(), 0, Constants.MaxSymbolNameLength))); // Retrieve the symbol information if (!Dbghelp.SymFromName(Kernel32.GetCurrentProcess(), symbolName, out symbolInformationBytes[0])) { throw new Win32Exception(); } var symbolInformation = MemoryMarshal.Read <SymbolInfo>(symbolInformationBytes); return(new Symbol((int)(symbolInformation.Address - pseudoDllAddress))); } finally { Dbghelp.SymUnloadModule64(Kernel32.GetCurrentProcess(), symbolTableAddress); } } finally { Dbghelp.SymCleanup(Kernel32.GetCurrentProcess()); } }
private async Task <Dictionary <string, IntPtr> > ParseSymbols(bool isWow64) { // Initialise a symbol handler for the local process var localProcessHandle = Process.GetCurrentProcess().SafeHandle; if (!Dbghelp.SymInitialize(localProcessHandle, IntPtr.Zero, false)) { throw new PInvokeException("Failed to call SymInitialize"); } // Load the symbol table for the PDB var pdbPathBuffer = Marshal.StringToHGlobalAnsi(await DownloadPdb(isWow64)); var symbolTableBaseAddress = Dbghelp.SymLoadModuleEx(localProcessHandle, IntPtr.Zero, pdbPathBuffer, IntPtr.Zero, _module.BaseAddress, int.MaxValue, IntPtr.Zero, 0); if (symbolTableBaseAddress == IntPtr.Zero) { throw new PInvokeException("Failed to call SymLoadModuleEx"); } // Initialise the callback used during SymEnumSymbols var symbolAddresses = new List <IntPtr>(); var symbolNames = new List <string>(); bool Callback(IntPtr symbolInfo, int symbolSize, IntPtr userContext) { symbolAddresses.Add((IntPtr)Marshal.PtrToStructure <SymbolInfo>(symbolInfo).Address); symbolNames.Add(Marshal.PtrToStringAnsi(symbolInfo + Marshal.SizeOf <SymbolInfo>())); return(true); } var callBackPointer = Marshal.GetFunctionPointerForDelegate(new Callbacks.EnumerateSymbolsCallback(Callback)); // Enumerate the PDB symbols if (!Dbghelp.SymEnumSymbols(localProcessHandle, symbolTableBaseAddress, IntPtr.Zero, callBackPointer, IntPtr.Zero)) { throw new PInvokeException("Failed to call SymEnumSymbols"); } Dbghelp.SymUnloadModule64(localProcessHandle, symbolTableBaseAddress); var symbols = new Dictionary <string, IntPtr>(); for (var symbolIndex = 0; symbolIndex < symbolNames.Count; symbolIndex++) { symbols.TryAdd(symbolNames[symbolIndex], symbolAddresses[symbolIndex]); } return(symbols); }
private static Dictionary <string, IntPtr> ParseSymbols(string pdbPath, IntPtr moduleAddress) { var symbols = new Dictionary <string, IntPtr>(); // Initialise a symbol handler for the local process using var localProcess = Process.GetCurrentProcess(); if (!Dbghelp.SymInitialize(localProcess.SafeHandle, IntPtr.Zero, false)) { throw new Win32Exception($"Failed to call SymInitialize with error code {Marshal.GetLastWin32Error()}"); } // Load the symbol table for the PDB var pdbPathBuffer = Encoding.Default.GetBytes(pdbPath); var symbolTableBaseAddress = Dbghelp.SymLoadModuleEx(localProcess.SafeHandle, IntPtr.Zero, ref pdbPathBuffer[0], IntPtr.Zero, moduleAddress, (int)new FileInfo(pdbPath).Length, IntPtr.Zero, 0); if (symbolTableBaseAddress == IntPtr.Zero) { throw new Win32Exception($"Failed to call SymLoadModuleEx with error code {Marshal.GetLastWin32Error()}"); } // Initialise the callback used during the SymEnumSymbols call bool Callback(ref SymbolInfo symbolInfo, int symbolSize, IntPtr userContext) { var symbolNameBuffer = new byte[symbolInfo.NameLen]; Unsafe.CopyBlockUnaligned(ref symbolNameBuffer[0], ref symbolInfo.Name, (uint)symbolNameBuffer.Length); symbols.TryAdd(Encoding.Default.GetString(symbolNameBuffer), (IntPtr)symbolInfo.Address); return(true); } var callbackDelegate = new Prototypes.EnumerateSymbolsCallback(Callback); // Enumerate the PDB symbols if (!Dbghelp.SymEnumSymbols(localProcess.SafeHandle, symbolTableBaseAddress, IntPtr.Zero, callbackDelegate, IntPtr.Zero)) { throw new Win32Exception($"Failed to call SymEnumSymbols with error code {Marshal.GetLastWin32Error()}"); } if (!Dbghelp.SymUnloadModule(localProcess.SafeHandle, symbolTableBaseAddress)) { throw new Win32Exception($"Failed to call SymUnloadModule with error code {Marshal.GetLastWin32Error()}"); } return(symbols); }
internal Symbol GetSymbol(string symbolName) { // Initialise a symbol handler Dbghelp.SymSetOptions(SymbolOptions.UndecorateName); var currentProcessHandle = Kernel32.GetCurrentProcess(); if (!Dbghelp.SymInitialize(currentProcessHandle, null, false)) { throw new Win32Exception(); } try { const int pseudoDllAddress = 0x1000; // Load the symbol table for the PDB into the symbol handler var pdbSize = new FileInfo(_pdbFilePath).Length; var symbolTableAddress = Dbghelp.SymLoadModule(currentProcessHandle, IntPtr.Zero, _pdbFilePath, null, pseudoDllAddress, (int)pdbSize); if (symbolTableAddress == 0) { throw new Win32Exception(); } // Initialise an array to receive the symbol information var symbolInformationSize = (Unsafe.SizeOf <SymbolInfo>() + sizeof(char) * Constants.MaxSymbolNameLength + sizeof(long) - 1) / sizeof(long); Span <byte> symbolInformationBytes = stackalloc byte[symbolInformationSize]; MemoryMarshal.Write(symbolInformationBytes, ref Unsafe.AsRef(new SymbolInfo(Unsafe.SizeOf <SymbolInfo>(), 0, Constants.MaxSymbolNameLength))); // Retrieve the symbol information if (!Dbghelp.SymFromName(currentProcessHandle, symbolName, out symbolInformationBytes[0])) { throw new Win32Exception(); } var symbolInformation = MemoryMarshal.Read <SymbolInfo>(symbolInformationBytes); return(new Symbol((int)(symbolInformation.Address - pseudoDllAddress))); } finally { Dbghelp.SymCleanup(currentProcessHandle); } }
private Dictionary <string, IntPtr> ParseSymbols(string pdbPath, IntPtr moduleAddress) { // Initialise a symbol handler for the local process var localProcessHandle = Process.GetCurrentProcess().SafeHandle; if (!Dbghelp.SymInitialize(localProcessHandle, IntPtr.Zero, false)) { throw new PInvokeException("Failed to call SymInitialize"); } // Load the symbol table for the PDB var pdbPathBuffer = Marshal.StringToHGlobalAnsi(pdbPath); var symbolTableBaseAddress = Dbghelp.SymLoadModuleEx(localProcessHandle, IntPtr.Zero, pdbPathBuffer, IntPtr.Zero, moduleAddress, int.MaxValue, IntPtr.Zero, 0); if (symbolTableBaseAddress == IntPtr.Zero) { throw new PInvokeException("Failed to call SymLoadModuleEx"); } // Initialise the callback used during the SymEnumSymbols call var symbols = new Dictionary <string, IntPtr>(); bool Callback(IntPtr symbolInfo, int symbolSize, IntPtr userContext) { symbols.TryAdd(Marshal.PtrToStringAnsi(symbolInfo + Marshal.SizeOf <SymbolInfo>()), (IntPtr)Marshal.PtrToStructure <SymbolInfo>(symbolInfo).Address); return(true); } var callbackDelegate = new Prototypes.EnumerateSymbolsCallback(Callback); var callbackPointer = Marshal.GetFunctionPointerForDelegate(callbackDelegate); // Enumerate the PDB symbols if (!Dbghelp.SymEnumSymbols(localProcessHandle, symbolTableBaseAddress, IntPtr.Zero, callbackPointer, IntPtr.Zero)) { throw new PInvokeException("Failed to call SymEnumSymbols"); } Dbghelp.SymUnloadModule64(localProcessHandle, symbolTableBaseAddress); return(symbols); }
private static ImmutableDictionary <string, int> ParseSymbolOffsets(string pdbPath, IEnumerable <string> symbolNames) { var symbolOffsets = new Dictionary <string, int>(); using var localProcess = System.Diagnostics.Process.GetCurrentProcess(); // Initialise a symbol handler Dbghelp.SymSetOptions(SymbolOptions.UndecorateName | SymbolOptions.DeferredLoads); if (!Dbghelp.SymInitialize(localProcess.SafeHandle, null, false)) { throw ExceptionBuilder.BuildWin32Exception("SymInitialize"); } // Load the symbol table for the PDB const int pseudoDllBaseAddress = 0x1000; var pdbSize = new FileInfo(pdbPath).Length; var symbolTableAddress = Dbghelp.SymLoadModuleEx(localProcess.SafeHandle, IntPtr.Zero, pdbPath, null, pseudoDllBaseAddress, (int)pdbSize, IntPtr.Zero, 0); if (symbolTableAddress == 0) { throw ExceptionBuilder.BuildWin32Exception("SymLoadModuleEx"); } // Initialise a buffer to receive the symbol information var symbolInfoBufferSize = (Unsafe.SizeOf <SymbolInfo>() + Constants.MaxSymbolName * sizeof(char) + sizeof(long) - 1) / sizeof(long); var symbolInfoBuffer = new byte[symbolInfoBufferSize]; var symbolInfo = new SymbolInfo { SizeOfStruct = Unsafe.SizeOf <SymbolInfo>(), MaxNameLen = Constants.MaxSymbolName }; MemoryMarshal.Write(symbolInfoBuffer, ref symbolInfo); // Retrieve the offsets of the symbols SymbolInfo RetrieveSymbolInformation(string symbolName) { if (!Dbghelp.SymFromName(localProcess.SafeHandle, symbolName, ref symbolInfoBuffer[0])) { throw ExceptionBuilder.BuildWin32Exception("SymFromName"); } return(MemoryMarshal.Read <SymbolInfo>(symbolInfoBuffer)); } foreach (var symbolName in symbolNames) { var symbolInformation = RetrieveSymbolInformation(symbolName); symbolOffsets.Add(symbolName, (int)(symbolInformation.Address - pseudoDllBaseAddress)); } if (!Dbghelp.SymCleanup(localProcess.SafeHandle)) { throw ExceptionBuilder.BuildWin32Exception("SymCleanup"); } return(symbolOffsets.ToImmutableDictionary()); }
private static IEnumerable <Symbol> ParseSymbols(string pdbFilePath, IEnumerable <string> symbolNames) { // Initialise a symbol handler Dbghelp.SymSetOptions(SymbolOptions.UndecorateName); using var currentProcessHandle = Kernel32.GetCurrentProcess(); if (!Dbghelp.SymInitialize(currentProcessHandle, null, false)) { throw new Win32Exception(); } try { // Load the symbol table for the PDB into the symbol handler const int pseudoDllBaseAddress = 0x1000; var pdbSize = new FileInfo(pdbFilePath).Length; var symbolTableAddress = Dbghelp.SymLoadModuleEx(currentProcessHandle, IntPtr.Zero, pdbFilePath, null, pseudoDllBaseAddress, (int)pdbSize, IntPtr.Zero, 0); if (symbolTableAddress == 0) { throw new Win32Exception(); } var symbolInformationBlockSize = (Unsafe.SizeOf <SymbolInfo>() + Constants.MaxSymbolName * sizeof(char) + sizeof(long) - 1) / sizeof(long); int GetSymbolRva(string symbolName) { // Initialise a block to receive the symbol information Span <byte> symbolInformationBlock = stackalloc byte[symbolInformationBlockSize]; var symbolInformation = new SymbolInfo(Constants.MaxSymbolName); MemoryMarshal.Write(symbolInformationBlock, ref symbolInformation); // Retrieve the symbol information if (!Dbghelp.SymFromName(currentProcessHandle, symbolName, out symbolInformationBlock[0])) { throw new Win32Exception(); } // Calculate the relative virtual address of the symbol symbolInformation = MemoryMarshal.Read <SymbolInfo>(symbolInformationBlock); return((int)(symbolInformation.Address - pseudoDllBaseAddress)); } foreach (var symbolName in symbolNames) { var symbolRva = GetSymbolRva(symbolName); yield return(new Symbol(symbolName, symbolRva)); } } finally { Dbghelp.SymCleanup(currentProcessHandle); } }