/// <summary>
        /// Looks through the configured symbol paths to find a PDB symbol
        /// file matching specified name, GUID and age parameters.
        /// </summary>
        /// <param name="pdbFileName"></param>
        /// <param name="guid"></param>
        /// <param name="age"></param>
        /// <returns></returns>
        /// <remarks>
        /// Note how we don't have to have a module loaded to find its PDB,
        /// we just look for a PDB file using name, GUID and age. These are
        /// the parameters that can be extracted from module's PE header,
        /// in the Debug Directory section.
        /// </remarks>
        public string FindPdbFile(string pdbFileName, Guid guid, int age)
        {
            DbgHelp.SymSetOptions(DbgHelp.SYMOPT_DEBUG);

            var hProcess = new IntPtr(1);

#if TARGET_NET_20
            var searchPath = string.Join(";", this.SymbolPaths.ToArray());
#else
            var searchPath = string.Join(";", this.SymbolPaths);
#endif
            DbgHelp.SymInitialize(hProcess, searchPath, false);

            var filePath   = new StringBuilder(256);
            var guidHandle = GCHandle.Alloc(guid, GCHandleType.Pinned);
            try
            {
                if (!DbgHelp.SymFindFileInPath(hProcess, null, pdbFileName,
                                               guidHandle.AddrOfPinnedObject(), (uint)age, 0,
                                               DbgHelp.SSRVOPT_GUIDPTR, filePath, null, IntPtr.Zero))
                {
                    return(null);
                }
            }
            finally
            {
                guidHandle.Free();

                DbgHelp.SymCleanup(hProcess);
            }

            return(filePath.ToString());
        }
Пример #2
0
        protected override bool ReleaseHandle()
        {
            if (IntPtr.Zero == base.handle)
            {
                return(true);
            }
            bool success;

            lock (Globals.DebugHelpLock) { success = DbgHelp.SymCleanup(handle); }
            if (success)
            {
                return(true);
            }
            Trace.TraceError("Failed to cleanup a symbol handler. Error: {0}",
                             Marshal.GetLastWin32Error());
            return(false);
        }
Пример #3
0
        public static Symbol[] GetSymbols(string DllFile)
        {
            IntPtr CurProc = Process.GetCurrentProcess().Handle;

            DbgHelp.SymInitialize(CurProc, null, false);

            if (!File.Exists(DllFile))
            {
                throw new FileNotFoundException("File not found", DllFile);
            }
            List <Symbol> Symbols = new List <Symbol>();

            ulong DllBase = DbgHelp.SymLoadModuleEx(CurProc, IntPtr.Zero, DllFile, null, 0, 0, IntPtr.Zero, 0);

            DbgHelp.SymEnumerateSymbols64(CurProc, DllBase, (Name, Addr, Size, Ctx) => {
                Symbols.Add(new Symbol(Name, DllBase - Addr, Size));
                return(true);
            }, IntPtr.Zero);

            DbgHelp.SymCleanup(CurProc);
            return(Symbols.ToArray());
        }
Пример #4
0
        public StackTrace(uint ProcessId, uint ThreadId)
        {
            List <StackCall> StackCalls = new List <StackCall>();

            //StackWalk64 Callbacks
            DbgHelp.SymFunctionTableAccess64Delegate FunctionTableAccessRoutine = new DbgHelp.SymFunctionTableAccess64Delegate(DbgHelp.SymFunctionTableAccess64);
            DbgHelp.SymGetModuleBase64Delegate       GetModuleBaseRoutine       = new DbgHelp.SymGetModuleBase64Delegate(DbgHelp.SymGetModuleBase64);

            IntPtr       lpContextRecord = new IntPtr();
            STACKFRAME64 StackFrame      = new STACKFRAME64();

            //Get handle for thread and its process
            IntPtr hProcess = Kernel32.OpenProcess(ProcessAccess.All, false, ProcessId);
            IntPtr hThread  = Kernel32.OpenThread(ThreadAccess.All, false, ThreadId);

            //Initialize Symbol handler
            DbgHelp.SymInitialize(hProcess, null, false);

            //Determine Image & Processor types
            bool Wow64         = false;
            uint ProcessorType = Functions.GetProcessorType();

            if (ProcessorType == (uint)ImageFileMachine.AMD64 | ProcessorType == (uint)ImageFileMachine.IA64)
            {
                Wow64 = Functions.IsWow64(hProcess);
            }

            //Initialize thread context & stack frame based on architectures
            if (Wow64)
            {
                ProcessorType = (uint)ImageFileMachine.I386;

                //Load 32-bit modules for symbol access
                Functions.LoadModules(hProcess, ListModules._32Bit);

                //Initialize an X86_CONTEXT
                X86_CONTEXT ContextRecord = new X86_CONTEXT();
                ContextRecord.ContextFlags = (uint)ContextFlags.X86ContextAll;
                lpContextRecord            = Marshal.AllocHGlobal(Marshal.SizeOf(ContextRecord));
                Marshal.StructureToPtr(ContextRecord, lpContextRecord, false);

                //Get context of thread
                Kernel32.Wow64SuspendThread(hThread);
                Kernel32.Wow64GetThreadContext(hThread, lpContextRecord);

                //Initialize Stack frame for first call to StackWalk64
                ContextRecord = (X86_CONTEXT)Marshal.PtrToStructure(lpContextRecord, typeof(X86_CONTEXT));
                StackFrame    = Functions.InitializeStackFrame64
                                    (AddressMode.Flat, ContextRecord.Eip, ContextRecord.Esp, ContextRecord.Ebp, new ulong());
            }
            else if (ProcessorType == (uint)ImageFileMachine.I386)
            {
                ProcessorType = (uint)ImageFileMachine.I386;

                //Load 32-bit modules for symbol access
                Functions.LoadModules(hProcess, ListModules._32Bit);

                //Initialize an X86_CONTEXT
                X86_CONTEXT ContextRecord = new X86_CONTEXT();
                ContextRecord.ContextFlags = (uint)ContextFlags.X86ContextAll;
                lpContextRecord            = Marshal.AllocHGlobal(Marshal.SizeOf(ContextRecord));
                Marshal.StructureToPtr(ContextRecord, lpContextRecord, false);

                //Get context of thread
                Kernel32.SuspendThread(hThread);
                Kernel32.GetThreadContext(hThread, lpContextRecord);

                //Initialize Stack frame for first call to StackWalk64
                ContextRecord = (X86_CONTEXT)Marshal.PtrToStructure(lpContextRecord, typeof(X86_CONTEXT));
                StackFrame    = Functions.InitializeStackFrame64
                                    (AddressMode.Flat, ContextRecord.Eip, ContextRecord.Esp, ContextRecord.Ebp, new ulong());
            }
            else if (ProcessorType == (uint)ImageFileMachine.AMD64)
            {
                //Load 64-bit modules for symbol access
                Functions.LoadModules(hProcess, ListModules._64Bit);

                //Initialize AMD64_CONTEXT
                AMD64_CONTEXT ContextRecord = new AMD64_CONTEXT();
                ContextRecord.ContextFlags = (uint)ContextFlags.AMD64ContextAll;
                lpContextRecord            = Marshal.AllocHGlobal(Marshal.SizeOf(ContextRecord));
                Marshal.StructureToPtr(ContextRecord, lpContextRecord, false);

                //Get context of thread
                Kernel32.SuspendThread(hThread);
                Kernel32.GetThreadContext(hThread, lpContextRecord);

                //Initialize Stack frame for first call to StackWalk64
                ContextRecord = (AMD64_CONTEXT)Marshal.PtrToStructure(lpContextRecord, typeof(AMD64_CONTEXT));
                StackFrame    = Functions.InitializeStackFrame64
                                    (AddressMode.Flat, ContextRecord.Rip, ContextRecord.Rsp, ContextRecord.Rsp, new ulong());
            }
            else if (ProcessorType == (uint)ImageFileMachine.IA64)
            {
                //Load 64-bit modules for symbol access
                Functions.LoadModules(hProcess, ListModules._64Bit);

                //Initialize IA64_CONTEXT
                IA64_CONTEXT ContextRecord = new IA64_CONTEXT();
                ContextRecord.ContextFlags = (uint)ContextFlags.IA64ContextAll;
                lpContextRecord            = Marshal.AllocHGlobal(Marshal.SizeOf(ContextRecord));
                Marshal.StructureToPtr(ContextRecord, lpContextRecord, false);

                //Get context of thread
                Kernel32.SuspendThread(hThread);
                Kernel32.GetThreadContext(hThread, lpContextRecord);

                //Initialize Stack frame for first call to StackWalk64
                ContextRecord = (IA64_CONTEXT)Marshal.PtrToStructure(lpContextRecord, typeof(IA64_CONTEXT));
                StackFrame    = Functions.InitializeStackFrame64
                                    (AddressMode.Flat, ContextRecord.StIIP, ContextRecord.IntSp, ContextRecord.RsBSP, ContextRecord.IntSp);
            }
            //Marshal stack frame to unmanaged memory
            IntPtr lpStackFrame = Marshal.AllocHGlobal(Marshal.SizeOf(StackFrame));

            Marshal.StructureToPtr(StackFrame, lpStackFrame, false);

            //Walk the Stack
            for (int frameNum = 0; ; frameNum++)
            {
                //Get Stack frame
                DbgHelp.StackWalk64(ProcessorType, hProcess, hThread, lpStackFrame, lpContextRecord,
                                    null, FunctionTableAccessRoutine, GetModuleBaseRoutine, null);
                StackFrame = (STACKFRAME64)Marshal.PtrToStructure(lpStackFrame, typeof(STACKFRAME64));

                if (StackFrame.AddrReturn.Offset == 0)
                {
                    break;
                }                                                 //End of stack reached

                StackCalls.Add(new StackCall(hProcess, StackFrame.AddrPC.Offset, StackFrame.AddrReturn.Offset, (int)ThreadId));
            }

            Calls = StackCalls.ToArray();

            //Cleanup
            DbgHelp.SymCleanup(hProcess);
            Marshal.FreeHGlobal(lpStackFrame);
            Marshal.FreeHGlobal(lpContextRecord);
            Kernel32.ResumeThread(hThread);
            Kernel32.CloseHandle(hThread);
            Kernel32.CloseHandle(hProcess);
        }