private void ProcessStackWalk(uint osThreadId) { IXCLRDataProcess ixclrDataProcess = _context.Runtime.DacInterface; object tmp; HR.Verify(ixclrDataProcess.GetTaskByOSThreadID(osThreadId, out tmp)); IXCLRDataTask task = (IXCLRDataTask)tmp; HR.Verify(task.CreateStackWalk(0xf /*all flags*/, out tmp)); IXCLRDataStackWalk stackWalk = (IXCLRDataStackWalk)tmp; while (HR.S_OK == stackWalk.Next()) { ProcessFrame(stackWalk); } }
private void ProcessFrame(IXCLRDataStackWalk stackWalk) { object tmp; if (HR.Failed(stackWalk.GetFrame(out tmp))) return; IXCLRDataFrame frame = (IXCLRDataFrame)tmp; StringBuilder methodName = new StringBuilder(MaxNameSize); uint methodNameLen; if (HR.Failed(frame.GetCodeName(0 /*default flags*/, (uint)methodName.Capacity, out methodNameLen, methodName))) return; uint numArgs, numLocals; if (HR.Failed(frame.GetNumArguments(out numArgs))) numArgs = 0; if (HR.Failed(frame.GetNumLocalVariables(out numLocals))) numLocals = 0; FrameArgumentsAndLocals frameArgsLocals = new FrameArgumentsAndLocals() { MethodName = methodName.ToString() }; for (uint argIdx = 0; argIdx < numArgs; ++argIdx) { StringBuilder argName = new StringBuilder(MaxNameSize); uint argNameLen; if (FailedUnlessOnCLR2DAC(frame.GetArgumentByIndex(argIdx, out tmp, (uint)argName.Capacity, out argNameLen, argName)) || tmp == null) continue; var arg = new ArgumentOrLocal() { Name = argName.ToString() }; FillValue(arg, (IXCLRDataValue)tmp); frameArgsLocals.Arguments.Add(arg); } for (uint lclIdx = 0; lclIdx < numLocals; ++lclIdx) { // The mscordacwks!ClrDataFrame::GetLocalVariableByIndex implementation never returns // names for local variables. Need to go through metadata to get them. StringBuilder dummy = new StringBuilder(2); uint lclNameLen; if (FailedUnlessOnCLR2DAC(frame.GetLocalVariableByIndex(lclIdx, out tmp, (uint)dummy.Capacity, out lclNameLen, dummy)) || tmp == null) continue; string lclName = dummy.ToString(); var matchingFrame = _stackTrace.SingleOrDefault(f => f.DisplayString == frameArgsLocals.MethodName); if (matchingFrame != null) { lclName = GetLocalVariableName(matchingFrame.InstructionPointer, lclIdx); } var lcl = new ArgumentOrLocal() { Name = lclName }; FillValue(lcl, (IXCLRDataValue)tmp); frameArgsLocals.LocalVariables.Add(lcl); } _results.Add(frameArgsLocals); }
private void ProcessFrame(IXCLRDataStackWalk stackWalk) { object tmp; if (HR.Failed(stackWalk.GetFrame(out tmp))) { return; } IXCLRDataFrame frame = (IXCLRDataFrame)tmp; StringBuilder methodName = new StringBuilder(MaxNameSize); uint methodNameLen; if (HR.Failed(frame.GetCodeName(0 /*default flags*/, (uint)methodName.Capacity, out methodNameLen, methodName))) { return; } uint numArgs, numLocals; if (HR.Failed(frame.GetNumArguments(out numArgs))) { numArgs = 0; } if (HR.Failed(frame.GetNumLocalVariables(out numLocals))) { numLocals = 0; } FrameArgumentsAndLocals frameArgsLocals = new FrameArgumentsAndLocals() { MethodName = methodName.ToString() }; for (uint argIdx = 0; argIdx < numArgs; ++argIdx) { StringBuilder argName = new StringBuilder(MaxNameSize); uint argNameLen; if (FailedUnlessOnCLR2DAC(frame.GetArgumentByIndex(argIdx, out tmp, (uint)argName.Capacity, out argNameLen, argName)) || tmp == null) { continue; } var arg = new ArgumentOrLocal() { Name = argName.ToString() }; FillValue(arg, (IXCLRDataValue)tmp); frameArgsLocals.Arguments.Add(arg); } for (uint lclIdx = 0; lclIdx < numLocals; ++lclIdx) { // The mscordacwks!ClrDataFrame::GetLocalVariableByIndex implementation never returns // names for local variables. Need to go through metadata to get them. StringBuilder dummy = new StringBuilder(2); uint lclNameLen; if (FailedUnlessOnCLR2DAC(frame.GetLocalVariableByIndex(lclIdx, out tmp, (uint)dummy.Capacity, out lclNameLen, dummy)) || tmp == null) { continue; } string lclName = dummy.ToString(); var matchingFrame = _stackTrace.SingleOrDefault(f => f.DisplayString == frameArgsLocals.MethodName); if (matchingFrame != null) { lclName = GetLocalVariableName(matchingFrame.InstructionPointer, lclIdx); } var lcl = new ArgumentOrLocal() { Name = lclName }; FillValue(lcl, (IXCLRDataValue)tmp); frameArgsLocals.LocalVariables.Add(lcl); } _results.Add(frameArgsLocals); }
internal IEnumerable <ClrStackFrame> EnumerateStackFrames(DesktopThread thread) { IXCLRDataProcess proc = GetClrDataProcess(); object tmp; int res = proc.GetTaskByOSThreadID(thread.OSThreadId, out tmp); if (res < 0) { yield break; } IXCLRDataTask task = null; IXCLRDataStackWalk stackwalk = null; try { task = (IXCLRDataTask)tmp; res = task.CreateStackWalk(0xf, out tmp); if (res < 0) { yield break; } stackwalk = (IXCLRDataStackWalk)tmp; byte[] ulongBuffer = new byte[8]; byte[] context = ContextHelper.Context; do { uint size; res = stackwalk.GetContext(ContextHelper.ContextFlags, ContextHelper.Length, out size, context); if (res < 0 || res == 1) { break; } ulong ip = BitConverter.ToUInt32(context, ContextHelper.InstructionPointerOffset); ulong sp = BitConverter.ToUInt32(context, ContextHelper.StackPointerOffset); res = stackwalk.Request(0xf0000000, 0, null, (uint)ulongBuffer.Length, ulongBuffer); ulong frameVtbl = 0; if (res >= 0) { frameVtbl = BitConverter.ToUInt64(ulongBuffer, 0); if (frameVtbl != 0) { sp = frameVtbl; ReadPointer(sp, out frameVtbl); } } DesktopStackFrame frame = GetStackFrame(thread, res, ip, sp, frameVtbl); yield return(frame); } while (stackwalk.Next() == 0); } finally { if (task != null) { Marshal.FinalReleaseComObject(task); } if (stackwalk != null) { Marshal.FinalReleaseComObject(stackwalk); } } }