/// <summary> /// Obtain the original source code file and line number for the given /// IL offset in a method identified by a unique metadata token. /// </summary> /// <param name="methodMetadataToken"></param> /// <param name="ilOffset"></param> /// <returns></returns> /// <remarks> /// Metadata token is stored in the PDB file for each method. Additionally /// it can always be retrieved from MethodInfo via reflection. Exception /// report saves a meatdata token for each method in the stack trace. /// </remarks> public SourceLocation GetSourceLoc(int methodMetadataToken, int ilOffset) { IDiaSymbol symMethod; _session.findSymbolByToken((uint)methodMetadataToken, SymTagEnum.SymTagFunction, out symMethod); var rvaMethod = symMethod.relativeVirtualAddress; rvaMethod += (uint)ilOffset; IDiaEnumLineNumbers lineNumbers; _session.findLinesByRVA(rvaMethod, 1, out lineNumbers); foreach (IDiaLineNumber ln in lineNumbers) { var sourceFile = ln.sourceFile; return(new SourceLocation() { LineNumber = ln.lineNumber, SourceFile = (sourceFile == null) ? null : sourceFile.fileName }); } return(null); }
/// <summary> /// Gets the source file name and line for the specified stack frame. /// </summary> /// <param name="address">The address.</param> /// <param name="sourceFileName">Name of the source file.</param> /// <param name="sourceFileLine">The source file line.</param> /// <param name="displacement">The displacement.</param> /// <exception cref="System.Exception">Address not found</exception> /// <exception cref="Exception">Address not found</exception> public void GetSourceFileNameAndLine(uint address, out string sourceFileName, out uint sourceFileLine, out ulong displacement) { IDiaSymbol function = session.findSymbolByRVA(address, SymTagEnum.Function); IDiaEnumLineNumbers lineNumbers = session.findLinesByRVA(address, (uint)function.length); foreach (IDiaLineNumber lineNumber in lineNumbers.Enum()) { if (address >= lineNumber.relativeVirtualAddress) { sourceFileName = lineNumber.sourceFile.fileName; sourceFileLine = lineNumber.lineNumber; displacement = address - lineNumber.relativeVirtualAddress; return; } } throw new Exception("Address not found"); }
public static string GetMethodName(IDiaSession pdbSession, uint rva) { IDiaSymbol funcSym; pdbSession.findSymbolByRVA(rva, SymTagEnum.SymTagFunction, out funcSym); if (funcSym == null) { pdbSession.findSymbolByRVA(rva, SymTagEnum.SymTagPublicSymbol, out funcSym); } if (funcSym == null) { return(null); } StringBuilder methodNameStr = new StringBuilder(); // Append the method-name methodNameStr.Append(funcSym.GetUndecoratedNameEx(UndName.DebuggerInternal)); // Append the offset of current instruction inside method methodNameStr.Append("+0x"); methodNameStr.Append(Convert.ToString(rva - funcSym.GetRelativeVirtualAddress(), 16)); // Append the source line IDiaEnumLineNumbers lines = null; IDiaSourceFile sourceFile = null; pdbSession.findLinesByRVA(rva, 1, out lines); int i; if (lines != null && lines.count == 1) { IDiaLineNumber line = lines.Item(0); if (line != null) { sourceFile = line.SourceFile; methodNameStr.Append(" ("); methodNameStr.Append(sourceFile.FileName); methodNameStr.Append(", line "); methodNameStr.Append(line.LineNumber); methodNameStr.Append(")"); i = Marshal.ReleaseComObject(line); if (i != 0) { Console.WriteLine("RefCount(funcSym) == {0}", i); } } } i = Marshal.ReleaseComObject(funcSym); if (i != 0) { Console.WriteLine("RefCount(funcSym) == {0}", i); } if (lines != null) { if (sourceFile != null) { i = Marshal.ReleaseComObject(sourceFile); if (i != 0) { Console.WriteLine("RefCount(sourceFile) == {0}", i); } } // line? i = Marshal.ReleaseComObject(lines); if (i != 0) { Console.WriteLine("RefCount(lines) == {0}", i); } } //return funcSym.GetName(); return(methodNameStr.ToString()); }