internal static Guid?CreateTargetFunctionBreakpointAtDebugEnd(DkmProcess process, DkmNativeModuleInstance moduleWithLoadedLua, string name, string desc, out ulong breakAddress) { var address = TryGetFunctionAddressAtDebugEnd(moduleWithLoadedLua, name, out string error); if (address != null) { LocalComponent.log.Debug($"Hooking Lua '{desc}' ({name}) function (address 0x{address.Value:x})"); var nativeAddress = process.CreateNativeInstructionAddress(address.Value); var breakpoint = DkmRuntimeInstructionBreakpoint.Create(Guids.luaSupportBreakpointGuid, null, nativeAddress, false, null); breakpoint.Enable(); breakAddress = address.Value; return(breakpoint.UniqueId); } else { LocalComponent.log.Warning($"Failed to create breakpoint in '{name}' with {error}"); } breakAddress = 0; return(null); }
public TraceManager(DkmProcess process) { _process = process; _pyrtInfo = process.GetPythonRuntimeInfo(); _breakpointData = _pyrtInfo.DLLs.DebuggerHelper.GetExportedStaticVariable <ArrayProxy <CliStructProxy <BreakpointData> > >("breakpointData"); _currentBreakpointData = _pyrtInfo.DLLs.DebuggerHelper.GetExportedStaticVariable <ByteProxy>("currentBreakpointData"); _breakpointDataInUseByTraceFunc = _pyrtInfo.DLLs.DebuggerHelper.GetExportedStaticVariable <ByteProxy>("breakpointDataInUseByTraceFunc"); _currentSourceLocation = _pyrtInfo.DLLs.DebuggerHelper.GetExportedStaticVariable <CliStructProxy <CurrentSourceLocation> >("currentSourceLocation"); _stepKind = _pyrtInfo.DLLs.DebuggerHelper.GetExportedStaticVariable <Int32Proxy>("stepKind"); _stepThreadId = _pyrtInfo.DLLs.DebuggerHelper.GetExportedStaticVariable <UInt64Proxy>("stepThreadId"); _steppingStackDepth = _pyrtInfo.DLLs.DebuggerHelper.GetExportedStaticVariable <Int32Proxy>("steppingStackDepth"); var onBreakpointHit = _pyrtInfo.DLLs.DebuggerHelper.FindExportName("OnBreakpointHit", true); _onBreakpointHitBP = DkmRuntimeInstructionBreakpoint.Create(Guids.PythonTraceManagerSourceGuid, null, onBreakpointHit, false, null); _onBreakpointHitBP.Enable(); var onStepComplete = _pyrtInfo.DLLs.DebuggerHelper.FindExportName("OnStepComplete", true); _onStepCompleteBP = DkmRuntimeInstructionBreakpoint.Create(Guids.PythonTraceManagerSourceGuid, null, onStepComplete, false, null); _onStepCompleteBP.Enable(); var onStepFallThrough = _pyrtInfo.DLLs.DebuggerHelper.FindExportName("OnStepFallThrough", true); _onStepFallThroughBP = DkmRuntimeInstructionBreakpoint.Create(Guids.PythonTraceManagerSourceGuid, null, onStepFallThrough, false, null); _onStepFallThroughBP.Enable(); WriteBreakpoints(); }
private static void ClearBreakpoint(DkmProcess process, DkmRuntimeInstructionBreakpoint breakpoint) { var runtimeBreakpoints = process.GetOrCreateDataItem(() => new RuntimeDllBreakpoints()); runtimeBreakpoints.Handlers.Remove(breakpoint.UniqueId); breakpoint.Close(); }
void IFunctionTracer.OnEntryBreakpointHit(DkmRuntimeBreakpoint bp, DkmThread thread, bool hasException) { // The function was just entered. Install the exit breakpoint on the calling thread at the // return address, and notify any listeners. DkmStackWalkFrame frame = thread.GetTopStackWalkFrame(bp.RuntimeInstance); bool suppressExitBreakpoint = false; if (OnFunctionEntered != null) { OnFunctionEntered(frame, frameAnalyzer, out suppressExitBreakpoint); } if (!suppressExitBreakpoint) { ulong ret = frame.VscxGetReturnAddress(); DkmInstructionAddress retAddr = thread.Process.CreateNativeInstructionAddress(ret); DkmRuntimeInstructionBreakpoint exitBp = DkmRuntimeInstructionBreakpoint.Create( Guids.Source.FunctionTraceExit, thread, retAddr, false, null); // Capture the value of every argument now, since when the exit breakpoint gets hit, the // target function will have already returned and its frame will be cleaned up. exitBp.SetDataItem(DkmDataCreationDisposition.CreateAlways, new FunctionTraceEntryDataItem { EntryArgumentValues = frameAnalyzer.GetAllArgumentValues(frame) }); exitBp.SetDataItem(DkmDataCreationDisposition.CreateAlways, new FunctionTraceDataItem { Tracer = this }); exitBp.Enable(); } }
public void Enable() { DkmNativeModuleInstance module = entryAddress.ModuleInstance; FunctionTraceDataItem traceDataItem = new FunctionTraceDataItem { Tracer = this }; entryBp = DkmRuntimeInstructionBreakpoint.Create( Guids.Source.FunctionTraceEnter, null, entryAddress, false, null); entryBp.SetDataItem(DkmDataCreationDisposition.CreateAlways, traceDataItem); entryBp.Enable(); }
DkmRuntimeInstructionBreakpoint PlaceBreakpointAtAddress(NullcRemoteProcessDataItem processData, DkmThread thread, ulong instructionAddress) { var dkmInstruction = DkmNativeInstructionAddress.Create(processData.nativeRuntimeInstance, processData.nativeModuleInstance, (uint)(instructionAddress - processData.nativeModuleInstance.BaseAddress), new DkmInstructionAddress.CPUInstruction(instructionAddress)); var stepBreakpoint = DkmRuntimeInstructionBreakpoint.Create(DebugHelpers.NullcStepperBreakpointSourceId, thread, dkmInstruction, false, null); stepBreakpoint.Enable(); return(stepBreakpoint); }
internal static Guid?CreateTargetFunctionBreakpointAtDebugStart(DkmProcess process, DkmNativeModuleInstance moduleWithLoadedLua, string name, string desc, out ulong breakAddress) { DkmRuntimeInstructionBreakpoint breakpoint = CreateTargetFunctionBreakpointObjectAtDebugStart(process, moduleWithLoadedLua, name, desc, out breakAddress, true); if (breakpoint != null) { return(breakpoint.UniqueId); } return(null); }
public void Enable() { DkmNativeModuleInstance module = entryAddress.ModuleInstance; FunctionTraceDataItem traceDataItem = new FunctionTraceDataItem { Tracer = this }; entryBp = DkmRuntimeInstructionBreakpoint.Create( Guids.Source.FunctionTraceEnter, null, entryAddress, false, null); entryBp.SetDataItem(DkmDataCreationDisposition.CreateAlways, traceDataItem); entryBp.Enable(); }
public static DkmRuntimeBreakpoint CreateRuntimeDllExportedFunctionBreakpoint(DkmNativeModuleInstance moduleInstance, string funcName, RuntimeDllBreakpointHandler handler, bool enable = false) { var process = moduleInstance.Process; var runtimeBreakpoints = process.GetOrCreateDataItem(() => new RuntimeDllBreakpoints()); var addr = moduleInstance.GetExportedFunctionAddress(funcName); var bp = DkmRuntimeInstructionBreakpoint.Create(Guids.LocalComponentGuid, null, addr, false, null); if (enable) { bp.Enable(); } runtimeBreakpoints.Handlers.Add(bp.UniqueId, handler); return(bp); }
internal static Guid?CreateTargetFunctionBreakpointAtAddress(DkmProcess process, DkmNativeModuleInstance moduleWithLoadedLua, string name, string desc, ulong address) { if (address != 0) { LocalComponent.log.Debug($"Hooking Lua '{desc}' ({name}) function (address 0x{address:x})"); var nativeAddress = process.CreateNativeInstructionAddress(address); var breakpoint = DkmRuntimeInstructionBreakpoint.Create(Guids.luaSupportBreakpointGuid, null, nativeAddress, false, null); breakpoint.Enable(); return(breakpoint.UniqueId); } else { LocalComponent.log.Warning($"Failed to create breakpoint in '{name}' with missing address"); } return(null); }
internal static Guid?CreateHelperFunctionBreakpoint(DkmNativeModuleInstance nativeModuleInstance, string functionName) { var functionAddress = TryGetFunctionAddressAtDebugStart(nativeModuleInstance, functionName, out string error); if (functionAddress != null) { LocalComponent.log.Debug($"Creating breakpoint in '{functionName}'"); var nativeAddress = nativeModuleInstance.Process.CreateNativeInstructionAddress(functionAddress.Value); var breakpoint = DkmRuntimeInstructionBreakpoint.Create(Guids.luaSupportBreakpointGuid, null, nativeAddress, false, null); breakpoint.Enable(); return(breakpoint.UniqueId); } else { var nativeFunctionAddress = FindFunctionAddress(nativeModuleInstance, functionName); if (nativeFunctionAddress != 0) { LocalComponent.log.Debug($"Creating 'native' breakpoint in '{functionName}'"); var nativeAddress = nativeModuleInstance.Process.CreateNativeInstructionAddress(nativeFunctionAddress); var breakpoint = DkmRuntimeInstructionBreakpoint.Create(Guids.luaSupportBreakpointGuid, null, nativeAddress, false, null); breakpoint.Enable(); return(breakpoint.UniqueId); } else { LocalComponent.log.Warning($"Failed to create breakpoint in '{functionName}' with {error}"); } } return(null); }
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); }
public static DkmRuntimeInstructionBreakpoint CreateBreakpoint(this DkmProcess process, Guid sourceId, ulong address) { var iaddr = process.CreateNativeInstructionAddress(address); return(DkmRuntimeInstructionBreakpoint.Create(sourceId, null, iaddr, false, null)); }
public void Handle(DkmThread thread, ulong frameBase, ulong frame, ulong returnAddress) { _bp = CreateBreakpoint(thread.Process, returnAddress, HandleStepOut, true); }