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); }
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); } } }