public UnifiedStackFrame ConvertToUnified(ClrStackFrame frame, SourceLocation sourceLocation, ThreadInfo info) { var result = new UnifiedStackFrame(frame, sourceLocation); result.ThreadContext = info.ContextStruct; return result; }
public UnifiedStackFrame(ClrStackFrame frame, SourceLocation sourceLocation) { if (frame.Kind == ClrStackFrameType.ManagedMethod) Type = UnifiedStackFrameType.Managed; if (frame.Kind == ClrStackFrameType.Runtime) Type = UnifiedStackFrameType.Special; InstructionPointer = frame.InstructionPointer; StackPointer = frame.StackPointer; if (frame.Method == null) return; Method = frame.Method.GetFullSignature(); if (frame.Method.Type != null) Module = Path.GetFileNameWithoutExtension(frame.Method.Type.Module.Name); OffsetInMethod = InstructionPointer - frame.Method.NativeCode; if (sourceLocation == null) return; SourceFileName = sourceLocation.FilePath; SourceLineNumber = (uint)sourceLocation.LineNumber; SourceLineNumberEnd = (uint)sourceLocation.LineNumberEnd; SourceColumnNumber = (uint)sourceLocation.ColStart; SourceColumnNumberEnd = (uint)sourceLocation.ColEnd; }
/// <summary> /// Managed code is shipped as IL, so RVA to NATIVE mapping can't be placed in the PDB. Instead /// what is placed in the PDB is a mapping from a method's meta-data token and IL offset to source /// line number. Thus if you have a metadata token and IL offset, you can again get a source location /// </summary> public SourceLocation SourceLocationForManagedCode(uint methodMetaDataToken, int ilOffset) { _reader._log.WriteLine("SourceLocationForManagedCode: Looking up method token {0:x} ilOffset {1:x}", methodMetaDataToken, ilOffset); IDiaSymbol methodSym; _session.findSymbolByToken(methodMetaDataToken, SymTagEnum.SymTagFunction, out methodSym); if (methodSym == null) { _reader._log.WriteLine("SourceLocationForManagedCode: No symbol for token {0:x} ilOffset {1:x}", methodMetaDataToken, ilOffset); return null; } uint fetchCount; IDiaEnumLineNumbers sourceLocs; IDiaLineNumber sourceLoc; // TODO FIX NOW, this code here is for debugging only turn if off when we are happy. //m_session.findLinesByRVA(methodSym.relativeVirtualAddress, (uint)(ilOffset + 256), out sourceLocs); //for (int i = 0; ; i++) //{ // sourceLocs.Next(1, out sourceLoc, out fetchCount); // if (fetchCount == 0) // break; // if (i == 0) // m_reader.m_log.WriteLine("SourceLocationForManagedCode: source file: {0}", sourceLoc.sourceFile.fileName); // m_reader.m_log.WriteLine("SourceLocationForManagedCode: ILOffset {0:x} -> line {1}", // sourceLoc.relativeVirtualAddress - methodSym.relativeVirtualAddress, sourceLoc.lineNumber); //} // End TODO FIX NOW debugging code // For managed code, the 'RVA' is a 'cumulative IL offset' (amount of IL bytes before this in the module) // Thus you find the line number of a particular IL offset by adding the offset within the method to // the cumulative IL offset of the start of the method. _session.findLinesByRVA(methodSym.relativeVirtualAddress + (uint)ilOffset, 256, out sourceLocs); sourceLocs.Next(1, out sourceLoc, out fetchCount); if (fetchCount == 0) { _reader._log.WriteLine("SourceLocationForManagedCode: No lines for token {0:x} ilOffset {1:x}", methodMetaDataToken, ilOffset); return null; } int lineNum; // FEEFEE is some sort of illegal line number that is returned some time, It is better to ignore it. // and take the next valid line for (;;) { lineNum = (int)sourceLoc.lineNumber; if (lineNum != 0xFEEFEE) break; sourceLocs.Next(1, out sourceLoc, out fetchCount); if (fetchCount == 0) break; } var sourceLocation = new SourceLocation(sourceLoc); return sourceLocation; }
/// <summary> /// Fetches the source location (line number and file), given the relative virtual address (RVA) /// of the location in the executable. /// </summary> public SourceLocation SourceLocationForRva(uint rva) { _reader._log.WriteLine("SourceLocationForRva: looking up RVA {0:x} ", rva); uint fetchCount; IDiaEnumLineNumbers sourceLocs; _session.findLinesByRVA(rva, 0, out sourceLocs); IDiaLineNumber sourceLoc; sourceLocs.Next(1, out sourceLoc, out fetchCount); if (fetchCount == 0) { _reader._log.WriteLine("SourceLocationForRva: No lines for RVA {0:x} ", rva); return null; } var buildTimeSourcePath = sourceLoc.sourceFile.fileName; var lineNum = (int)sourceLoc.lineNumber; var sourceLocation = new SourceLocation(sourceLoc); return sourceLocation; }