public static TextPositionTuple GetTextPositionOfFrame(PathConverter converter, IDebugStackFrame2 frame) { IDebugDocumentContext2 documentContext; if (frame.GetDocumentContext(out documentContext) == 0 && documentContext != null) { TEXT_POSITION[] beginPosition = new TEXT_POSITION[1]; TEXT_POSITION[] 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); Source source = new Source() { Path = convertedFilePath, Name = Path.GetFileName(convertedFilePath) }; int line = converter.ConvertDebuggerLineToClient((int)beginPosition[0].dwLine); int column = unchecked ((int)(beginPosition[0].dwColumn + 1)); return(new TextPositionTuple(source, line, column)); } return(null); }
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)); }