public DkmStackWalkFrame[] FilterNextFrame(DkmStackContext stackContext, DkmStackWalkFrame input) { if (input == null) // after last frame { return(null); } if (input.InstructionAddress == null) // error case { return new[] { input } } ; if (input.InstructionAddress.ModuleInstance != null && input.InstructionAddress.ModuleInstance.Module != null) // code in existing module { return new[] { input } } ; if (!_enabled) // environment variable not set { return new[] { input } } ; return(new[] { UnityMixedStackFrame(stackContext, input) }); }
internal string ExecuteExpression(string expression, DkmStackContext stackContext, DkmStackWalkFrame input, bool allowZero) { var compilerId = new DkmCompilerId(DkmVendorId.Microsoft, DkmLanguageId.Cpp); var language = DkmLanguage.Create("C++", compilerId); var languageExpression = DkmLanguageExpression.Create(language, DkmEvaluationFlags.None, expression, null); var inspectionContext = DkmInspectionContext.Create(stackContext.InspectionSession, input.RuntimeInstance, stackContext.Thread, 200, DkmEvaluationFlags.None, DkmFuncEvalFlags.None, 10, language, null); var workList = DkmWorkList.Create(null); string resultText = null; inspectionContext.EvaluateExpression(workList, languageExpression, input, res => { if (res.ErrorCode == 0) { var result = res.ResultObject as DkmSuccessEvaluationResult; if (result != null && result.TagValue == DkmEvaluationResult.Tag.SuccessResult && (allowZero || result.Address.Value != 0)) { resultText = result.Value; } res.ResultObject.Close(); } }); workList.Execute(); return(resultText); }
public DkmStackWalkFrame[] FilterNextFrame(DkmStackContext stackContext, DkmStackWalkFrame input) { if (input == null) // after last frame { return(null); } if (input.InstructionAddress == null) // error case { return new[] { input } } ; if (input.InstructionAddress.ModuleInstance != null) // code in existing module { return new[] { input } } ; var runner = new PmipRunner(stackContext, input); return(new[] { runner.PmipStackFrame() }); } } }
DkmStackWalkFrame[] IDkmCallStackFilter.FilterNextFrame(DkmStackContext stackContext, DkmStackWalkFrame input) { // The HelloWorld sample is a very simple debugger component which modified the call stack // so that there is a '[Hello World]' frame at the top of the call stack. All the frames // below this are left the same. if (input == null) // null input frame indicates the end of the call stack. This sample does nothing on end-of-stack. { return(null); } // Get the HelloWorldDataItem which is associated with this stack walk. This // lets us keep data associated with this stack walk. HelloWordDataItem dataItem = HelloWordDataItem.GetInstance(stackContext); DkmStackWalkFrame[] frames; // Now use this data item to see if we are looking at the first (top-most) frame if (dataItem.State == State.Initial) { // On the top most frame, we want to return back two different frames. First // we place the '[Hello World]' frame, and under that we put the input frame. frames = new DkmStackWalkFrame[2]; // Create the hello world frame object, and stick it in the array frames[0] = DkmStackWalkFrame.Create( stackContext.Thread, null, // Annotated frame, so no instruction address input.FrameBase, // Use the same frame base as the input frame 0, // annoted frame uses zero bytes DkmStackWalkFrameFlags.None, "[Hello World]", // Description of the frame which will appear in the call stack null, // Annotated frame, so no registers null ); // Add the input frame into the array as well frames[1] = input; // Update our state so that on the next frame we know not to add '[Hello World]' again. dataItem.State = State.HelloWorldFrameAdded; } else { // We have already added '[Hello World]' to this call stack, so just return // the input frame. frames = new DkmStackWalkFrame[1] { input }; } return(frames); }
/// <summary> /// Returns the instance of HelloWorldDataItem associated with the input DkmStackContext /// object. If there is not currently an associated HelloWorldDataItem, a new data item /// will be created. /// </summary> /// <param name="context">Object to obtain the data item from</param> /// <returns>The associated data item</returns> public static HelloWordDataItem GetInstance(DkmStackContext context) { HelloWordDataItem item = GetExistingInstance(context); if (item != null) return item; item = new HelloWordDataItem(); context.SetDataItem<HelloWordDataItem>(DkmDataCreationDisposition.CreateNew, item); return item; }
private static DkmInspectionContext CreateInspectionContext(DkmStackContext stackContext, DkmStackWalkFrame frame) { return DkmInspectionContext.Create( stackContext.InspectionSession, frame.RuntimeInstance, frame.Thread, 1000, DkmEvaluationFlags.None, DkmFuncEvalFlags.None, 10, CppLanguage, null); }
private static DkmInspectionContext CreateInspectionContext(DkmStackContext stackContext, DkmStackWalkFrame frame) { return(DkmInspectionContext.Create( stackContext.InspectionSession, frame.RuntimeInstance, frame.Thread, 1000, DkmEvaluationFlags.None, DkmFuncEvalFlags.None, 10, CppLanguage, null)); }
DkmStackWalkFrame[] IDkmCallStackFilter.FilterNextFrame(DkmStackContext stackContext, DkmStackWalkFrame input) { // The HelloWorld sample is a very simple debugger component which modified the call stack // so that there is a '[Hello World]' frame at the top of the call stack. All the frames // below this are left the same. if (input == null) // null input frame indicates the end of the call stack. This sample does nothing on end-of-stack. return null; // Get the HelloWorldDataItem which is associated with this stack walk. This // lets us keep data associated with this stack walk. HelloWordDataItem dataItem = HelloWordDataItem.GetInstance(stackContext); DkmStackWalkFrame[] frames; // Now use this data item to see if we are looking at the first (top-most) frame if (dataItem.State == State.Initial) { // On the top most frame, we want to return back two different frames. First // we place the '[Hello World]' frame, and under that we put the input frame. frames = new DkmStackWalkFrame[2]; // Create the hello world frame object, and stick it in the array frames[0] = DkmStackWalkFrame.Create( stackContext.Thread, null, // Annotated frame, so no instruction address input.FrameBase, // Use the same frame base as the input frame 0, // annoted frame uses zero bytes DkmStackWalkFrameFlags.None, "[Hello World]", // Description of the frame which will appear in the call stack null, // Annotated frame, so no registers null ); // Add the input frame into the array as well frames[1] = input; // Update our state so that on the next frame we know not to add '[Hello World]' again. dataItem.State = State.HelloWorldFrameAdded; } else { // We have already added '[Hello World]' to this call stack, so just return // the input frame. frames = new DkmStackWalkFrame[1] { input }; } return frames; }
public DkmStackWalkFrame[] FilterNextFrame(DkmStackContext stackContext, DkmStackWalkFrame input) { if (input == null) // after last frame return null; if (input.InstructionAddress == null) // error case return new[] { input }; if (input.InstructionAddress.ModuleInstance != null) // code in existing module return new[] { input }; var runner = new PmipRunner(stackContext, input); return new[] { runner.PmipStackFrame() }; }
/// <summary> /// Returns the instance of HelloWorldDataItem associated with the input DkmStackContext /// object. If there is not currently an associated HelloWorldDataItem, a new data item /// will be created. /// </summary> /// <param name="context">Object to obtain the data item from</param> /// <returns>The associated data item</returns> public static HelloWordDataItem GetInstance(DkmStackContext context) { HelloWordDataItem item = GetExistingInstance(context); if (item != null) { return(item); } item = new HelloWordDataItem(); context.SetDataItem <HelloWordDataItem>(DkmDataCreationDisposition.CreateNew, item); return(item); }
DkmStackWalkFrame[] IDkmCallStackFilter.FilterNextFrame(DkmStackContext stackContext, DkmStackWalkFrame input) { if (input == null) { return(null); } var filter = input.Process.GetDataItem <CallStackFilter>(); try { if (filter != null) { return(filter.FilterNextFrame(stackContext, input)); } } catch (DkmException) { } return(new[] { input }); }
private static DkmStackWalkFrame UnityMixedStackFrame(DkmStackContext stackContext, DkmStackWalkFrame frame) { RefreshStackData(frame.Process.LivePart.Id); string name = null; if (TryGetDescriptionForIp(frame.InstructionAddress.CPUInstructionPart.InstructionPointer, out name)) { return(DkmStackWalkFrame.Create( stackContext.Thread, frame.InstructionAddress, frame.FrameBase, frame.FrameSize, frame.Flags, name, frame.Registers, frame.Annotations)); } return(frame); }
public DkmStackWalkFrame[] FilterNextFrame(DkmStackContext stackContext, DkmStackWalkFrame nativeFrame) { PyFrameObject pythonFrame = null; var nativeModuleInstance = nativeFrame.ModuleInstance; if (nativeModuleInstance == _pyrtInfo.DLLs.DebuggerHelper) { if (_pyrtInfo.LanguageVersion < PythonLanguageVersion.V36 || (pythonFrame = PyFrameObject.TryCreate(nativeFrame)) == null) { return(DebuggerOptions.ShowNativePythonFrames ? new[] { nativeFrame } : new DkmStackWalkFrame[0]); } } var result = new List <DkmStackWalkFrame>(); if (pythonFrame == null) { var stackWalkData = stackContext.GetDataItem <StackWalkContextData>(); if (stackWalkData == null) { stackWalkData = new StackWalkContextData(); stackContext.SetDataItem(DkmDataCreationDisposition.CreateNew, stackWalkData); } bool?wasLastFrameNative = stackWalkData.IsLastFrameNative; if (nativeModuleInstance != _pyrtInfo.DLLs.Python && nativeModuleInstance != _pyrtInfo.DLLs.CTypes) { stackWalkData.IsLastFrameNative = true; if (wasLastFrameNative == false) { result.Add(DkmStackWalkFrame.Create(nativeFrame.Thread, null, nativeFrame.FrameBase, nativeFrame.FrameSize, DkmStackWalkFrameFlags.NonuserCode, Strings.DebugCallStackNativeToPythonTransition, null, null)); } else { stackWalkData.IsLastFrameNative = true; } result.Add(nativeFrame); return(result.ToArray()); } else { stackWalkData.IsLastFrameNative = false; if (wasLastFrameNative == true) { result.Add(DkmStackWalkFrame.Create(nativeFrame.Thread, null, nativeFrame.FrameBase, nativeFrame.FrameSize, DkmStackWalkFrameFlags.NonuserCode, Strings.DebugCallStackPythonToNativeTransition, null, null)); } } pythonFrame = PyFrameObject.TryCreate(nativeFrame); } if (pythonFrame == null) { if (DebuggerOptions.ShowNativePythonFrames) { result.Add(nativeFrame); } return(result.ToArray()); } PyCodeObject code = pythonFrame.f_code.Read(); var loc = new SourceLocation( code.co_filename.Read().ToStringOrNull(), pythonFrame.f_lineno.Read(), code.co_name.Read().ToStringOrNull(), nativeFrame.InstructionAddress as DkmNativeInstructionAddress); var pythonRuntime = _process.GetPythonRuntimeInstance(); var pythonModuleInstances = pythonRuntime.GetModuleInstances().OfType <DkmCustomModuleInstance>(); var pyModuleInstance = pythonModuleInstances.Where(m => m.FullName == loc.FileName).FirstOrDefault(); if (pyModuleInstance == null) { pyModuleInstance = pythonModuleInstances.Single(m => m.Module.Id.Mvid == Guids.UnknownPythonModuleGuid); } var encodedLocation = loc.Encode(); var instrAddr = DkmCustomInstructionAddress.Create(pythonRuntime, pyModuleInstance, encodedLocation, 0, encodedLocation, null); var frame = DkmStackWalkFrame.Create( nativeFrame.Thread, instrAddr, nativeFrame.FrameBase, nativeFrame.FrameSize, DkmStackWalkFrameFlags.None, null, nativeFrame.Registers, nativeFrame.Annotations); result.Add(frame); if (DebuggerOptions.ShowNativePythonFrames) { result.Add(nativeFrame); } return(result.ToArray()); }
public Tuple <ulong, ulong, ulong>[] GetThreadStackTrace(uint threadId, byte[] threadContextBytes) { return(ExecuteOnDkmInitializedThread(() => { DkmThread thread = GetThread(threadId); List <DkmStackFrame> frames = new List <DkmStackFrame>(); DkmProcess process = thread.Process; using (DkmInspectionSession dkmInspectionSession = DkmInspectionSession.Create(process, null)) { using (DkmStackContext dkmStackContext = DkmStackContext.Create(dkmInspectionSession, thread, DkmCallStackFilterOptions.None, new DkmFrameFormatOptions(), new System.Collections.ObjectModel.ReadOnlyCollection <byte>(threadContextBytes), null)) { bool done = false; while (!done) { DkmWorkList dkmWorkList = DkmWorkList.Create(null); dkmStackContext.GetNextFrames(dkmWorkList, int.MaxValue, (ar) => { frames.AddRange(ar.Frames); done = ar.Frames.Length == 0; }); dkmWorkList.Execute(); } } } threads[(int)threadId].Frames.Value = frames.ToArray(); Tuple <ulong, ulong, ulong>[] result = new Tuple <ulong, ulong, ulong> [frames.Count]; for (int i = 0; i < result.Length; i++) { ulong stackOffset, instructionOffset; switch (frames[i].Registers.TagValue) { case DkmFrameRegisters.Tag.X64Registers: { DkmX64FrameRegisters registers = (DkmX64FrameRegisters)frames[i].Registers; instructionOffset = registers.Rip; stackOffset = registers.Rsp; } break; case DkmFrameRegisters.Tag.X86Registers: { DkmX86FrameRegisters registers = (DkmX86FrameRegisters)frames[i].Registers; instructionOffset = registers.Eip; stackOffset = registers.Esp; } break; default: throw new NotImplementedException("Unexpected DkmFrameRegisters.Tag"); } bool found = false; ulong frameOffset = 0; for (int j = 0; !found && j < frames[i].Registers.UnwoundRegisters.Count; j++) { switch ((Dia2Lib.CV_HREG_e)frames[i].Registers.UnwoundRegisters[j].Identifier) { case Dia2Lib.CV_HREG_e.CV_AMD64_EBP: case Dia2Lib.CV_HREG_e.CV_AMD64_RBP: { byte[] bytes = frames[i].Registers.UnwoundRegisters[j].Value.ToArray(); found = true; frameOffset = bytes.Length == 8 ? BitConverter.ToUInt64(bytes, 0) : BitConverter.ToUInt32(bytes, 0); break; } } } if (instructionOffset != frames[i].InstructionAddress.CPUInstructionPart.InstructionPointer) { throw new Exception("Instruction offset is not the same?"); } result[i] = Tuple.Create(instructionOffset, stackOffset, frameOffset); } return result; })); }
/// <summary> /// Returns the instance of HelloWorldDataItem associated with the input DkmStackContext /// object. If there is not currently an associated HelloWorldDataItem, return null. /// </summary> /// <param name="context">Object to obtain the data item from</param> /// <returns>[OPTIONAL] The associated data item</returns> public static HelloWordDataItem GetExistingInstance(DkmStackContext context) { return context.GetDataItem<HelloWordDataItem>(); }
public PmipRunner(DkmStackContext stackContext, DkmStackWalkFrame frame) { _stackContext = stackContext; _frame = frame; _inspectionContext = CreateInspectionContext(stackContext, frame); }
/// <summary> /// Returns the instance of HelloWorldDataItem associated with the input DkmStackContext /// object. If there is not currently an associated HelloWorldDataItem, return null. /// </summary> /// <param name="context">Object to obtain the data item from</param> /// <returns>[OPTIONAL] The associated data item</returns> public static HelloWordDataItem GetExistingInstance(DkmStackContext context) { return(context.GetDataItem <HelloWordDataItem>()); }
public DkmStackWalkFrame[] FilterNextFrame(DkmStackContext stackContext, DkmStackWalkFrame nativeFrame) { var nativeModuleInstance = nativeFrame.ModuleInstance; if (nativeModuleInstance == _pyrtInfo.DLLs.DebuggerHelper) { return DebuggerOptions.ShowNativePythonFrames ? new[] { nativeFrame } : new DkmStackWalkFrame[0]; } var result = new List<DkmStackWalkFrame>(); var stackWalkData = stackContext.GetDataItem<StackWalkContextData>(); if (stackWalkData == null) { stackWalkData = new StackWalkContextData(); stackContext.SetDataItem(DkmDataCreationDisposition.CreateNew, stackWalkData); } bool? wasLastFrameNative = stackWalkData.IsLastFrameNative; if (nativeModuleInstance != _pyrtInfo.DLLs.Python && nativeModuleInstance != _pyrtInfo.DLLs.CTypes) { stackWalkData.IsLastFrameNative = true; if (wasLastFrameNative == false) { result.Add(DkmStackWalkFrame.Create(nativeFrame.Thread, null, nativeFrame.FrameBase, nativeFrame.FrameSize, DkmStackWalkFrameFlags.NonuserCode, "[Native to Python Transition]", null, null)); } else { stackWalkData.IsLastFrameNative = true; } result.Add(nativeFrame); return result.ToArray(); } else { stackWalkData.IsLastFrameNative = false; if (wasLastFrameNative == true) { result.Add(DkmStackWalkFrame.Create(nativeFrame.Thread, null, nativeFrame.FrameBase, nativeFrame.FrameSize, DkmStackWalkFrameFlags.NonuserCode, "[Python to Native Transition]", null, null)); } } var pythonFrame = PyFrameObject.TryCreate(nativeFrame); if (pythonFrame == null) { if (DebuggerOptions.ShowNativePythonFrames) { result.Add(nativeFrame); } return result.ToArray(); } PyCodeObject code = pythonFrame.f_code.Read(); var loc = new SourceLocation( code.co_filename.Read().ToStringOrNull(), pythonFrame.f_lineno.Read(), code.co_name.Read().ToStringOrNull(), nativeFrame.InstructionAddress as DkmNativeInstructionAddress); var pythonRuntime = _process.GetPythonRuntimeInstance(); var pythonModuleInstances = pythonRuntime.GetModuleInstances().OfType<DkmCustomModuleInstance>(); var pyModuleInstance = pythonModuleInstances.Where(m => m.FullName == loc.FileName).FirstOrDefault(); if (pyModuleInstance == null) { pyModuleInstance = pythonModuleInstances.Single(m => m.Module.Id.Mvid == Guids.UnknownPythonModuleGuid); } var encodedLocation = loc.Encode(); var instrAddr = DkmCustomInstructionAddress.Create(pythonRuntime, pyModuleInstance, encodedLocation, 0, encodedLocation, null); var frame = DkmStackWalkFrame.Create( nativeFrame.Thread, instrAddr, nativeFrame.FrameBase, nativeFrame.FrameSize, DkmStackWalkFrameFlags.None, null, nativeFrame.Registers, nativeFrame.Annotations); result.Add(frame); if (DebuggerOptions.ShowNativePythonFrames) { result.Add(nativeFrame); } return result.ToArray(); }
DkmStackWalkFrame[] IDkmCallStackFilter.FilterNextFrame(DkmStackContext stackContext, DkmStackWalkFrame input) { if (input == null) // null input frame indicates the end of the call stack. This sample does nothing on end-of-stack. { var processData = DebugHelpers.GetOrCreateDataItem <NullcStackFilterDataItem>(stackContext.InspectionSession.Process); processData.nullcFramePosition = 1; return(null); } if (input.InstructionAddress == null) { return(new DkmStackWalkFrame[1] { input }); } if (input.InstructionAddress.ModuleInstance != null) { if (input.BasicSymbolInfo != null && input.BasicSymbolInfo.MethodName == "ExecutorRegVm::RunCode") { var processData = DebugHelpers.GetOrCreateDataItem <NullcStackFilterDataItem>(input.Thread.Process); InitNullcDebugFunctions(processData, input.RuntimeInstance); if (processData.nullcIsMissing) { return(new DkmStackWalkFrame[1] { input }); } string vmInstructionStr = ExecuteExpression("instruction - codeBase", stackContext, input, true); string ptrValue = DebugHelpers.Is64Bit(input.Thread.Process) ? "longValue" : "intValue"; string vmDataOffsetStr = ExecuteExpression($"(unsigned long long)regFilePtr[1].{ptrValue} - (unsigned long long)rvm->dataStack.data", stackContext, input, true); if (vmInstructionStr != null && vmDataOffsetStr != null) { ulong vmInstruction = ulong.Parse(vmInstructionStr); string stackFrameDesc = ExecuteExpression($"((char*(*)(unsigned, unsigned)){processData.nullcDebugGetVmAddressLocation})({vmInstruction}, 0),sb", stackContext, input, false); var nullcCustomRuntime = input.Thread.Process.GetRuntimeInstances().OfType <DkmCustomRuntimeInstance>().FirstOrDefault(el => el.Id.RuntimeType == DebugHelpers.NullcVmRuntimeGuid); if (stackFrameDesc != null && nullcCustomRuntime != null) { var flags = input.Flags; flags = flags & ~(DkmStackWalkFrameFlags.NonuserCode | DkmStackWalkFrameFlags.UserStatusNotDetermined); flags = flags | DkmStackWalkFrameFlags.InlineOptimized; DkmCustomModuleInstance nullcModuleInstance = nullcCustomRuntime.GetModuleInstances().OfType <DkmCustomModuleInstance>().FirstOrDefault(el => el.Module != null && el.Module.CompilerId.VendorId == DebugHelpers.NullcCompilerGuid); if (nullcModuleInstance != null) { DkmInstructionAddress instructionAddress = DkmCustomInstructionAddress.Create(nullcCustomRuntime, nullcModuleInstance, null, vmInstruction, null, null); var rawAnnotations = new List <DkmStackWalkFrameAnnotation>(); // Additional unique request id rawAnnotations.Add(DkmStackWalkFrameAnnotation.Create(DebugHelpers.NullcCallStackDataBaseGuid, ulong.Parse(vmDataOffsetStr))); var annotations = new ReadOnlyCollection <DkmStackWalkFrameAnnotation>(rawAnnotations); DkmStackWalkFrame frame = DkmStackWalkFrame.Create(stackContext.Thread, instructionAddress, input.FrameBase, input.FrameSize, flags, stackFrameDesc, input.Registers, annotations, nullcModuleInstance, null, null); return(new DkmStackWalkFrame[2] { frame, input }); } } } } return(new DkmStackWalkFrame[1] { input }); } // Currently we want to provide info only for JiT frames if (!input.Flags.HasFlag(DkmStackWalkFrameFlags.UserStatusNotDetermined)) { return(new DkmStackWalkFrame[1] { input }); } try { var processData = DebugHelpers.GetOrCreateDataItem <NullcStackFilterDataItem>(input.Thread.Process); InitNullcDebugFunctions(processData, input.RuntimeInstance); if (processData.nullcIsMissing) { return new DkmStackWalkFrame[1] { input } } ; string stackFrameDesc = ExecuteExpression($"((char*(*)(void*, unsigned)){processData.nullcDebugGetNativeAddressLocation})((void*)0x{input.InstructionAddress.CPUInstructionPart.InstructionPointer:X}, 0),sb", stackContext, input, false); if (stackFrameDesc != null) { var flags = input.Flags; flags = flags & ~(DkmStackWalkFrameFlags.NonuserCode | DkmStackWalkFrameFlags.UserStatusNotDetermined); if (stackFrameDesc == "[Transition to nullc]") { return(new DkmStackWalkFrame[1] { DkmStackWalkFrame.Create(stackContext.Thread, input.InstructionAddress, input.FrameBase, input.FrameSize, flags, stackFrameDesc, input.Registers, input.Annotations) }); } DkmStackWalkFrame frame = null; var nullcCustomRuntime = input.Thread.Process.GetRuntimeInstances().OfType <DkmCustomRuntimeInstance>().FirstOrDefault(el => el.Id.RuntimeType == DebugHelpers.NullcRuntimeGuid); var nullcNativeRuntime = DebugHelpers.useDefaultRuntimeInstance ? input.Thread.Process.GetNativeRuntimeInstance() : input.Thread.Process.GetRuntimeInstances().OfType <DkmNativeRuntimeInstance>().FirstOrDefault(el => el.Id.RuntimeType == DebugHelpers.NullcRuntimeGuid); if (DebugHelpers.useNativeInterfaces ? nullcNativeRuntime != null : nullcCustomRuntime != null) { DkmModuleInstance nullcModuleInstance; if (DebugHelpers.useNativeInterfaces) { nullcModuleInstance = nullcNativeRuntime.GetModuleInstances().OfType <DkmNativeModuleInstance>().FirstOrDefault(el => el.Module != null && el.Module.CompilerId.VendorId == DebugHelpers.NullcCompilerGuid); } else { nullcModuleInstance = nullcCustomRuntime.GetModuleInstances().OfType <DkmCustomModuleInstance>().FirstOrDefault(el => el.Module != null && el.Module.CompilerId.VendorId == DebugHelpers.NullcCompilerGuid); } if (nullcModuleInstance != null) { // If the top of the call stack is a nullc frame, nullc call stack wont have an entry for it and we start from 0, otherwise we start from default value of 1 if (input.Flags.HasFlag(DkmStackWalkFrameFlags.TopFrame)) { processData.nullcFramePosition = 0; } string stackFrameBase = ExecuteExpression($"((unsigned(*)(unsigned)){processData.nullcDebugGetReversedStackDataBase})({processData.nullcFramePosition})", stackContext, input, true); processData.nullcFramePosition++; if (int.TryParse(stackFrameBase, out int stackFrameBaseValue)) { DkmInstructionAddress instructionAddress; if (DebugHelpers.useNativeInterfaces) { var rva = (uint)(input.InstructionAddress.CPUInstructionPart.InstructionPointer - nullcModuleInstance.BaseAddress); instructionAddress = DkmNativeInstructionAddress.Create(nullcNativeRuntime, nullcModuleInstance as DkmNativeModuleInstance, rva, input.InstructionAddress.CPUInstructionPart); } else { instructionAddress = DkmCustomInstructionAddress.Create(nullcCustomRuntime, nullcModuleInstance as DkmCustomModuleInstance, null, input.InstructionAddress.CPUInstructionPart.InstructionPointer, null, input.InstructionAddress.CPUInstructionPart); } var rawAnnotations = new List <DkmStackWalkFrameAnnotation>(); // Additional unique request id rawAnnotations.Add(DkmStackWalkFrameAnnotation.Create(DebugHelpers.NullcCallStackDataBaseGuid, (ulong)(stackFrameBaseValue))); var annotations = new ReadOnlyCollection <DkmStackWalkFrameAnnotation>(rawAnnotations); frame = DkmStackWalkFrame.Create(stackContext.Thread, instructionAddress, input.FrameBase, input.FrameSize, flags, stackFrameDesc, input.Registers, annotations, nullcModuleInstance, null, null); } } } if (frame == null) { frame = DkmStackWalkFrame.Create(stackContext.Thread, input.InstructionAddress, input.FrameBase, input.FrameSize, flags, stackFrameDesc, input.Registers, input.Annotations); } return(new DkmStackWalkFrame[1] { frame }); } } catch (Exception ex) { Console.WriteLine("Failed to evaluate: " + ex.ToString()); } return(new DkmStackWalkFrame[1] { input }); }
public void OnBeginStepOut(DkmThread thread) { // When we're stepping out while in Python code, there are two possibilities. Either the stack looks like this: // // PythonFrame1 // PythonFrame2 // // or else it looks like this: // // PythonFrame // [Native to Python transition] // NativeFrame // // In both cases, we use native breakpoints on the return address to catch the end of step-out operation. // For Python-to-native step-out, this is the only option. For Python-to-Python, it would seem that TraceFunc // can detect it via PyTrace_RETURN, but it doesn't actually know whether the return is to Python or to // native at the point where it's reported - and, in any case, we need to let PyEval_EvalFrameEx to return // before reporting the completion of that step-out (otherwise we will show the returning frame in call stack). // Find the destination for step-out by walking the call stack and finding either the first native frame // outside of Python and helper DLLs, or the second Python frame. var inspectionSession = DkmInspectionSession.Create(_process, null); var frameFormatOptions = new DkmFrameFormatOptions(DkmVariableInfoFlags.None, DkmFrameNameFormatOptions.None, DkmEvaluationFlags.None, 10000, 10); var stackContext = DkmStackContext.Create(inspectionSession, thread, DkmCallStackFilterOptions.None, frameFormatOptions, null, null); DkmStackFrame frame = null; for (int pyFrameCount = 0; pyFrameCount != 2;) { DkmStackFrame[] frames = null; var workList = DkmWorkList.Create(null); stackContext.GetNextFrames(workList, 1, (result) => { frames = result.Frames; }); workList.Execute(); if (frames == null || frames.Length != 1) { return; } frame = frames[0]; var frameModuleInstance = frame.ModuleInstance; if (frameModuleInstance is DkmNativeModuleInstance && frameModuleInstance != _pyrtInfo.DLLs.Python && frameModuleInstance != _pyrtInfo.DLLs.DebuggerHelper && frameModuleInstance != _pyrtInfo.DLLs.CTypes) { break; } else if (frame.RuntimeInstance != null && frame.RuntimeInstance.Id.RuntimeType == Guids.PythonRuntimeTypeGuid) { ++pyFrameCount; } } var nativeAddr = frame.InstructionAddress as DkmNativeInstructionAddress; if (nativeAddr == null) { var customAddr = frame.InstructionAddress as DkmCustomInstructionAddress; if (customAddr == null) { return; } var loc = new SourceLocation(customAddr.AdditionalData, thread.Process); nativeAddr = loc.NativeAddress; if (nativeAddr == null) { return; } } var bp = DkmRuntimeInstructionBreakpoint.Create(Guids.PythonStepTargetSourceGuid, thread, nativeAddr, false, null); bp.Enable(); _stepOutTargetBreakpoints.Add(bp); }