private void OnBreakpointHit(DkmThread thread) { CurrentSourceLocation cbp = _currentSourceLocation.Read(); DebuggerString fileNameDS; _process.ReadMemory(cbp.fileName, DkmReadMemoryFlags.None, &fileNameDS, sizeof(DebuggerString)); char *fileNameBuf = stackalloc char[fileNameDS.length]; ulong dataOffset = (ulong)((byte *)fileNameDS.data - (byte *)&fileNameDS); _process.ReadMemory(cbp.fileName + dataOffset, DkmReadMemoryFlags.None, fileNameBuf, fileNameDS.length * 2); string fileName = new string(fileNameBuf, 0, fileNameDS.length); SourceLocation loc = new SourceLocation(fileName, cbp.lineNumber); if (!_breakpoints.TryGetValue(loc, out List <DkmRuntimeBreakpoint> bps)) { Debug.Fail("TraceFunc signalled a breakpoint at a location that BreakpointManager does not know about."); return; } foreach (var bp in bps) { bp.OnHit(thread, false); } }
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); }