/// <summary>Remaps the specified line number, if a remapping has been created that applies to it.</summary> /// <param name="line">On entry, a real line number. On exit, a remapped line number</param> /// <param name="fileName">This is changed to the user-specified file name /// string, if and only if a file-name remapping exists and applies here.</param> /// <returns>true if a remapping exists and was applied, false if not.</returns> public bool Remap(ref int line, ref string fileName) { int i = _map.FindUpperBound(line) - 1; if (i == -1) { return(false); } var kvp = ((AListBase <int, KeyValuePair <int, Pair <int, string> > >)_map)[i]; if (kvp.Value.B != null) { fileName = kvp.Value.B; } else if (kvp.Key == kvp.Value.A) { return(false); // remap ended } int realLine = kvp.Key; int reportLine = kvp.Value.A; Debug.Assert(line >= realLine); line = reportLine + (line - realLine); return(true); }
public static TextPositionTuple GetTextPositionOfFrame(PathConverter converter, IDebugStackFrame2 frame) { IDebugDocumentContext2 documentContext; var source = new Source(); if (frame.GetDocumentContext(out documentContext) == 0 && documentContext != null) { var beginPosition = new TEXT_POSITION[1]; var endPosition = new TEXT_POSITION[1]; documentContext.GetStatementRange(beginPosition, endPosition); string filePath; documentContext.GetName(enum_GETNAME_TYPE.GN_FILENAME, out filePath); string convertedFilePath = converter.ConvertDebuggerPathToClient(filePath); // save the filename as we need it in any case source.Name = Path.GetFileName(convertedFilePath); // we have debug info but do we actually have the source code? if (File.Exists(convertedFilePath)) { source.Path = convertedFilePath; int srcline = converter.ConvertDebuggerLineToClient((int)beginPosition[0].dwLine); int srccolumn = unchecked ((int)(beginPosition[0].dwColumn + 1)); return(new TextPositionTuple(source, srcline, srccolumn)); } } // this frame is lacking source code source.Name = Path.ChangeExtension(source.Name, ".s") ?? "???"; source.Path = null; source.Origin = "disassembly"; ulong startAddress; IDebugCodeContext2 codeContext; if (frame.GetCodeContext(out codeContext) != HRConstants.S_OK) { return(null); // we couldn't even find the current instruction, something's really wrong } var cinfos = new CONTEXT_INFO[1]; codeContext.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ALLFIELDS, cinfos); DisassembledRange disRange; startAddress = (ulong)Convert.ToInt64(cinfos[0].bstrAddress, 16); int idx = DisasmRangesDict.FindUpperBound(startAddress); bool foundIt = false; int column = 0; int line = 0; if (idx > 0) { var kv = DisasmRangesDict.TryGet(idx - 1).Value; if (startAddress >= kv.Key && startAddress <= kv.Value.endAddress) { disRange = kv.Value; source.SourceReference = disRange.sourceReference; line = kv.Value.dasmData.FirstIndexWhere(d => (ulong)Convert.ToInt64(d.bstrAddress, 16) >= startAddress) ?? 0; ++line; column = 0; foundIt = true; } } if (!foundIt) { IDebugThread2 thread; frame.GetThread(out thread); IDebugProgram2 program; thread.GetProgram(out program); IDebugDisassemblyStream2 disasmStream; program.GetDisassemblyStream(enum_DISASSEMBLY_STREAM_SCOPE.DSS_FUNCTION, codeContext, out disasmStream); uint instructionsRead; var dasmData = new DisassemblyData[100]; if (disasmStream.Read(100, enum_DISASSEMBLY_STREAM_FIELDS.DSF_ALL, out instructionsRead, dasmData) == HRConstants.S_OK) { System.Array.Resize(ref dasmData, (int)instructionsRead); source.SourceReference = ++lastSourceReference; DisasmRangesDict.Add(startAddress, new DisassembledRange() { sourceReference = lastSourceReference, endAddress = (ulong)Convert.ToInt64(dasmData.Last().bstrAddress, 16), dasmData = dasmData }); line = 1; column = 0; } } return(new TextPositionTuple(source, line, column)); }