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;
        }
예제 #3
0
        /// <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;
        }
예제 #4
0
        /// <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;
        }