Exemplo n.º 1
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);
        }