Пример #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
        private void WriteBreakpoints()
        {
            int maxLineNumber     = _breakpoints.Keys.Select(loc => loc.LineNumber).DefaultIfEmpty().Max();
            var lineNumbersStream = new MemoryStream((maxLineNumber + 1) * sizeof(int));
            var lineNumbersWriter = new BinaryWriter(lineNumbersStream);

            var stringsStream = new MemoryStream();
            var stringsWriter = new BinaryWriter(stringsStream);
            var stringOffsets = new Dictionary <string, int>();

            stringsWriter.Write((int)0);
            foreach (var s in _breakpoints.Keys.Select(loc => loc.FileName).Distinct())
            {
                stringOffsets[s] = (int)stringsStream.Position;
                stringsWriter.Write((int)s.Length);
                foreach (char c in s)
                {
                    stringsWriter.Write((ushort)c);
                }
                stringsWriter.Write((ushort)0);
            }

            var fileNamesOffsetsStream  = new MemoryStream();
            var fileNamesOffsetsWriter  = new BinaryWriter(fileNamesOffsetsStream);
            var fileNamesOffsetsIndices = new Dictionary <int[], int>(new StructuralArrayEqualityComparer <int>());

            fileNamesOffsetsWriter.Write((int)0);
            foreach (var g in _breakpoints.Keys.GroupBy(loc => loc.LineNumber))
            {
                var lineNumber = g.Key;

                var fileNamesOffsets = g.Select(loc => stringOffsets[loc.FileName]).ToArray();
                Array.Sort(fileNamesOffsets);

                if (!fileNamesOffsetsIndices.TryGetValue(fileNamesOffsets, out global::System.Int32 fileNamesOffsetsIndex))
                {
                    fileNamesOffsetsIndex = (int)fileNamesOffsetsStream.Position / sizeof(int);
                    foreach (int offset in fileNamesOffsets)
                    {
                        fileNamesOffsetsWriter.Write(offset);
                    }
                    fileNamesOffsetsWriter.Write((int)0);
                    fileNamesOffsetsIndices.Add(fileNamesOffsets, fileNamesOffsetsIndex);
                }

                lineNumbersStream.Position = lineNumber * sizeof(int);
                lineNumbersWriter.Write(fileNamesOffsetsIndex);
            }

            byte breakpointDataInUseByTraceFunc = _breakpointDataInUseByTraceFunc.Read();
            byte currentBreakpointData          = (breakpointDataInUseByTraceFunc == 0) ? (byte)1 : (byte)0;

            _currentBreakpointData.Write(currentBreakpointData);

            CliStructProxy <BreakpointData> bpDataProxy = _breakpointData[currentBreakpointData];
            BreakpointData bpData = bpDataProxy.Read();

            if (bpData.lineNumbers != 0)
            {
                _process.FreeVirtualMemory(bpData.lineNumbers, 0, NativeMethods.MEM_RELEASE);
            }
            if (bpData.fileNamesOffsets != 0)
            {
                _process.FreeVirtualMemory(bpData.fileNamesOffsets, 0, NativeMethods.MEM_RELEASE);
            }
            if (bpData.strings != 0)
            {
                _process.FreeVirtualMemory(bpData.strings, 0, NativeMethods.MEM_RELEASE);
            }

            bpData.maxLineNumber = maxLineNumber;
            if (lineNumbersStream.Length > 0)
            {
                bpData.lineNumbers = _process.AllocateVirtualMemory(0, (int)lineNumbersStream.Length, NativeMethods.MEM_COMMIT | NativeMethods.MEM_RESERVE, NativeMethods.PAGE_READWRITE);
                _process.WriteMemory(bpData.lineNumbers, lineNumbersStream.ToArray());
            }
            else
            {
                bpData.lineNumbers = 0;
            }

            bpData.fileNamesOffsets = _process.AllocateVirtualMemory(0, (int)fileNamesOffsetsStream.Length, NativeMethods.MEM_COMMIT | NativeMethods.MEM_RESERVE, NativeMethods.PAGE_READWRITE);
            _process.WriteMemory(bpData.fileNamesOffsets, fileNamesOffsetsStream.ToArray());

            bpData.strings = _process.AllocateVirtualMemory(0, (int)stringsStream.Length, NativeMethods.MEM_COMMIT | NativeMethods.MEM_RESERVE, NativeMethods.PAGE_READWRITE);
            _process.WriteMemory(bpData.strings, stringsStream.ToArray());

            bpDataProxy.Write(bpData);
        }
Пример #3
0
        public unsafe TraceManagerLocalHelper(DkmProcess process, Kind kind)
        {
            _process  = process;
            _pyrtInfo = process.GetPythonRuntimeInfo();

            _traceFunc            = _pyrtInfo.DLLs.DebuggerHelper.GetExportedFunctionAddress("TraceFunc");
            _evalFrameFunc        = _pyrtInfo.DLLs.DebuggerHelper.GetExportedFunctionAddress("EvalFrameFunc");
            _defaultEvalFrameFunc = _pyrtInfo.DLLs.DebuggerHelper.GetExportedStaticVariable <PointerProxy>("DefaultEvalFrameFunc");
            _isTracing            = _pyrtInfo.DLLs.DebuggerHelper.GetExportedStaticVariable <ByteProxy>("isTracing");
            _pyTracingPossible    = _pyrtInfo.GetRuntimeState()?.ceval.tracing_possible
                                    ?? _pyrtInfo.DLLs.Python.GetStaticVariable <Int32Proxy>("_Py_TracingPossible");

            if (kind == Kind.StepIn)
            {
                CliStructProxy <FieldOffsets> fieldOffsets = _pyrtInfo.DLLs.DebuggerHelper.GetExportedStaticVariable <CliStructProxy <FieldOffsets> >("fieldOffsets");
                fieldOffsets.Write(new FieldOffsets(process, _pyrtInfo));

                CliStructProxy <Types> types = _pyrtInfo.DLLs.DebuggerHelper.GetExportedStaticVariable <CliStructProxy <Types> >("types");
                types.Write(new Types(process, _pyrtInfo));

                CliStructProxy <FunctionPointers> functionPointers = _pyrtInfo.DLLs.DebuggerHelper.GetExportedStaticVariable <CliStructProxy <FunctionPointers> >("functionPointers");
                functionPointers.Write(new FunctionPointers(process, _pyrtInfo));

                PointerProxy stringEquals = _pyrtInfo.DLLs.DebuggerHelper.GetExportedStaticVariable <PointerProxy>("stringEquals");
                if (_pyrtInfo.LanguageVersion <= PythonLanguageVersion.V27)
                {
                    stringEquals.Write(_pyrtInfo.DLLs.DebuggerHelper.GetExportedFunctionAddress("StringEquals27").GetPointer());
                }
                else
                {
                    stringEquals.Write(_pyrtInfo.DLLs.DebuggerHelper.GetExportedFunctionAddress("StringEquals33").GetPointer());
                }

                foreach (var interp in PyInterpreterState.GetInterpreterStates(process))
                {
                    if (_pyrtInfo.LanguageVersion >= PythonLanguageVersion.V36)
                    {
                        RegisterJITTracing(interp);
                    }
                    foreach (var tstate in interp.GetThreadStates())
                    {
                        RegisterTracing(tstate);
                    }
                }

                _handlers = new PythonDllBreakpointHandlers(this);
                LocalComponent.CreateRuntimeDllFunctionExitBreakpoints(_pyrtInfo.DLLs.Python, "new_threadstate", _handlers.new_threadstate, enable: true);
                LocalComponent.CreateRuntimeDllFunctionExitBreakpoints(_pyrtInfo.DLLs.Python, "PyInterpreterState_New", _handlers.PyInterpreterState_New, enable: true);

                foreach (var methodInfo in _handlers.GetType().GetMethods())
                {
                    StepInGateAttribute stepInAttr = (StepInGateAttribute)Attribute.GetCustomAttribute(methodInfo, typeof(StepInGateAttribute));
                    if (stepInAttr != null &&
                        (stepInAttr.MinVersion == PythonLanguageVersion.None || _pyrtInfo.LanguageVersion >= stepInAttr.MinVersion) &&
                        (stepInAttr.MaxVersion == PythonLanguageVersion.None || _pyrtInfo.LanguageVersion <= stepInAttr.MaxVersion))
                    {
                        StepInGateHandler handler = (StepInGateHandler)Delegate.CreateDelegate(typeof(StepInGateHandler), _handlers, methodInfo);
                        AddStepInGate(handler, _pyrtInfo.DLLs.Python, methodInfo.Name, stepInAttr.HasMultipleExitPoints);
                    }
                }

                if (_pyrtInfo.DLLs.CTypes != null)
                {
                    OnCTypesLoaded(_pyrtInfo.DLLs.CTypes);
                }
            }
        }