Beispiel #1
0
        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);
        }
Beispiel #2
0
        internal int GetSymbolAddress(string symbolName)
        {
            // Initialise a symbol handler

            Dbghelp.SymSetOptions(SymbolOptions.UndecorateName);

            using var currentProcessHandle = Process.GetCurrentProcess().SafeHandle;

            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(Constants.MaxSymbolNameLength)));

                try
                {
                    // Retrieve the symbol information

                    if (!Dbghelp.SymFromName(currentProcessHandle, symbolName, out symbolInformationBytes[0]))
                    {
                        throw new Win32Exception();
                    }
                }

                catch
                {
                    Dbghelp.SymUnloadModule(currentProcessHandle, pseudoDllAddress);

                    throw;
                }

                if (!Dbghelp.SymUnloadModule(currentProcessHandle, pseudoDllAddress))
                {
                    throw new Win32Exception();
                }

                // Calculate the address of the symbol

                var symbolInformation = MemoryMarshal.Read <SymbolInfo>(symbolInformationBytes);

                return((int)symbolInformation.Address - pseudoDllAddress);
            }

            finally
            {
                Dbghelp.SymCleanup(currentProcessHandle);
            }
        }