Пример #1
0
        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();
        }
Пример #2
0
        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();
            }
        }
Пример #3
0
            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);
            }
Пример #4
0
        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();
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #9
0
        public static DkmRuntimeInstructionBreakpoint CreateBreakpoint(this DkmProcess process, Guid sourceId, ulong address)
        {
            var iaddr = process.CreateNativeInstructionAddress(address);

            return(DkmRuntimeInstructionBreakpoint.Create(sourceId, null, iaddr, false, null));
        }