/// <summary>
 ///     Initializes a new instance of the <see cref="ClrMethodAdapter" /> class.
 /// </summary>
 /// <param name="method">The method.</param>
 /// <exception cref="ArgumentNullException">method</exception>
 /// <inheritdoc />
 public ClrMethodAdapter(IConverter converter, ClrMd.ClrMethod method) : base(converter)
 {
     Method             = method ?? throw new ArgumentNullException(nameof(method));
     GCInfo             = Method.GCInfo;
     IsAbstract         = Method.IsAbstract;
     IsClassConstructor = Method.IsClassConstructor;
     IsConstructor      = Method.IsConstructor;
     IsFinal            = Method.IsFinal;
     IsInternal         = Method.IsInternal;
     IsPInvoke          = Method.IsPInvoke;
     IsPrivate          = Method.IsPrivate;
     IsProtected        = Method.IsProtected;
     IsPublic           = Method.IsPublic;
     IsRTSpecialName    = Method.IsRTSpecialName;
     IsSpecialName      = Method.IsSpecialName;
     IsStatic           = Method.IsStatic;
     IsVirtual          = Method.IsVirtual;
     MetadataToken      = Method.MetadataToken;
     try
     {
         MethodDesc = Method.MethodDesc;
     }
     catch (Exception)
     {
         ; // CLRMd bug
     }
     Name       = Method.Name;
     NativeCode = Method.NativeCode;
 }
 public LoneTargetInformation(ClrDump clrDump, ClrObject target, ClrMethod methInfo, ClrObject owner)
 {
     this.clrDump = clrDump;
     this.target = target;
     this.methInfo = methInfo;
     this.owner = owner;
 }
Exemple #3
0
        /// <summary>
        ///     Converts the specified method.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <returns>IClrMethod.</returns>
        public IClrMethod Convert(ClrMd.ClrMethod method)
        {
            if (method == null)
            {
                return(null);
            }
            var item = new ClrMethodAdapter(this, method);

            return(Cache.GetOrAdd <IClrMethod>(method, () => item, () => item.Setup()));
        }
Exemple #4
0
        /// <summary>
        /// Finds the IL offset for the specified frame.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <param name="instructionPointer">The instruction pointer.</param>
        internal static uint FindIlOffset(Microsoft.Diagnostics.Runtime.ClrMethod method, ulong instructionPointer)
        {
            ulong ip   = instructionPointer;
            uint  last = uint.MaxValue;

            foreach (var item in method.ILOffsetMap)
            {
                if (item.StartAddress > ip)
                {
                    return(last);
                }
                if (ip <= item.EndAddress)
                {
                    return((uint)item.ILOffset);
                }
                last = (uint)item.ILOffset;
            }

            return(last);
        }
Exemple #5
0
        private void DecompileMethods(ClrMethod[] methods)
        {
            string moduleFileName = methods[0].Type.Module.FileName;
            string typeName = methods[0].Type.Name;

            var assemblyDef = AssemblyDefinition.ReadAssembly(moduleFileName);
            var typeDef = TypeDefFromAssemblyDef(typeName, assemblyDef);

            AstBuilder decompiler = new AstBuilder(
                new DecompilerContext(typeDef.Module) { CurrentType = typeDef });
            foreach (var method in methods)
            {
                var methodDef = typeDef.Methods.Single(
                    m => m.MetadataToken.ToUInt32() == method.MetadataToken);
                decompiler.AddMethod(methodDef);
            }

            GenerateCode(decompiler);
        }
		public ClrMethodDecorator(ClrMethod clrMethod, ThreadDispatcher threadDispatcher)
		{
			_clrMethod = clrMethod;
			_threadDispatcher = threadDispatcher;
		}
        /// <summary>
        /// See https://github.com/goldshtn/msos/commit/705d3758d15835d2520b31fcf3028353bdbca73b#commitcomment-12499813
        /// and https://github.com/Microsoft/dotnetsamples/blob/master/Microsoft.Diagnostics.Runtime/CLRMD/ClrMemDiag/Debugger/IDebugControl.cs#L126-L156
        /// </summary>
        private void PrintAssemblyCode(ClrMethod method, IList<ILToNativeMap> ilMaps, ClrRuntime runtime, IDebugControl debugControl)
        {
            // This is the first instruction of the JIT'ed (or NGEN'ed) machine code.
            ulong startAddress = ilMaps.Select(entry => entry.StartAddress).Min();

            // Unfortunately there's not a great way to get the size of the code, or the end address.
            // You are supposed to do code flow analysis like "uf" in windbg to find the size, but
            // in practice you can use the IL to native mapping:
            ulong endAddress = ilMaps.Select(entry => entry.EndAddress).Max();

            var bufferSize = 500; // per-line
            var lineOfAssembly = new StringBuilder(bufferSize);
            ulong startOffset = startAddress, endOffset;
            uint disassemblySize;
            do
            {
                var flags = DEBUG_DISASM.EFFECTIVE_ADDRESS;
                var result = debugControl.Disassemble(startOffset, flags, lineOfAssembly, bufferSize, out disassemblySize, out endOffset);
                startOffset = endOffset;
                logger?.Write(lineOfAssembly.ToString());

                if (lineOfAssembly.ToString().Contains(" call ") == false)
                    continue;

                var methodCallInfo = GetCalledMethodFromAssemblyOutput(runtime, lineOfAssembly.ToString());
                if (string.IsNullOrWhiteSpace(methodCallInfo) == false)
                    logger?.WriteLine(LogKind.Info, $"  {methodCallInfo}");
            } while (disassemblySize > 0 && endOffset <= endAddress);
            logger?.WriteLine();
        }
 private void PrintLocationAndILMapInfo(ClrMethod method, ILOffsetSourceLocation location, IList<ILToNativeMap> ilMaps)
 {
     try
     {
         var ilMapsInfo = ilMaps.Select(ilMap =>
                                 string.Format("IL_{0:X4} [{1:X8}-{2:X8} ({3:X8}-{4:X8})] ",
                                     ilMap.ILOffset,
                                     ilMap.StartAddress,
                                     ilMap.EndAddress,
                                     ilMap.StartAddress - @method.NativeCode,
                                     ilMap.EndAddress - @method.NativeCode));
         logger?.WriteLine(LogKind.Statistic, string.Join("\n  ", ilMapsInfo));
     }
     catch (Exception ex)
     {
         logger?.WriteLine(LogKind.Error, ex.ToString());
     }
 }
Exemple #9
0
        private static PdbReader GetReaderForMethod(ClrMethod method)
        {
            ClrModule module = method?.Type?.Module;
            PdbInfo info = module?.Pdb;

            PdbReader reader = null;
            if (info != null)
            {
                if (!s_pdbReaders.TryGetValue(info, out reader))
                {
                    SymbolLocator locator = GetSymbolLocator(module);
                    string pdbPath = locator.FindPdb(info);
                    if (pdbPath != null)
                    {
                        try
                        {
                            reader = new PdbReader(pdbPath);
                        }
                        catch (IOException)
                        {
                            // This will typically happen when trying to load information
                            // from public symbols, or symbol files generated by some weird
                            // compiler. We can ignore this, but there's no need to load
                            // this PDB anymore, so we will put null in the dictionary and
                            // be done with it.
                            reader = null;
                        }
                    }

                    s_pdbReaders[info] = reader;
                }
            }

            return reader;
        }
Exemple #10
0
        private void DisassembleMethod(ClrMethod method)
        {
            var module = method.Type.Module;
            string fileName = module.FileName;

            AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(fileName);
            TypeDefinition type = assembly.MainModule.GetType(method.Type.Name);

            MethodDefinition methodDef = type.Methods.Single(
                m => m.MetadataToken.ToUInt32() == method.MetadataToken);

            _context.WriteLine("{0}", method.GetFullSignature());

            if (method.ILOffsetMap == null)
                return;

            var mapByOffset = (from map in method.ILOffsetMap
                               where map.ILOffset != -2
                               where map.StartAddress <= map.EndAddress
                               orderby map.ILOffset
                               select map).ToArray();
            if (mapByOffset.Length == 0)
            {
                // The method doesn't have an offset map. Just print the whole thing.
                PrintInstructions(methodDef.Body.Instructions);
            }

            // This is the prologue, looks like it's always there, but it could
            // also be the only thing that's in the method
            DisassembleNative(method.ILOffsetMap.Single(e => e.ILOffset == -2));

            for (int i = 0; i < mapByOffset.Length; ++i)
            {
                var map = mapByOffset[i];
                IEnumerable<Instruction> instructions;
                if (i == mapByOffset.Length - 1)
                {
                    instructions = methodDef.Body.Instructions.Where(
                        instr => instr.Offset >= map.ILOffset);
                }
                else
                {
                    instructions = methodDef.Body.Instructions.Where(
                        instr => instr.Offset >= map.ILOffset &&
                            instr.Offset < mapByOffset[i + 1].ILOffset);
                }

                var sourceLocation = method.GetSourceLocation(map.ILOffset);
                if (sourceLocation != null)
                {
                    _context.WriteLine("{0} {1}-{2}:{3}-{4}", sourceLocation.FilePath,
                        sourceLocation.LineNumber, sourceLocation.LineNumberEnd,
                        sourceLocation.ColStart, sourceLocation.ColEnd);
                    for (int line = sourceLocation.LineNumber; line <= sourceLocation.LineNumberEnd; ++line)
                    {
                        _context.WriteLine(ReadSourceLine(sourceLocation.FilePath, line));
                        _context.WriteLine(new string(' ', sourceLocation.ColStart - 1) + new string('^', sourceLocation.ColEnd - sourceLocation.ColStart));
                    }
                }
                PrintInstructions(instructions);
                DisassembleNative(map);
            }

            // TODO We are still not printing the epilogue while sosex does
        }
Exemple #11
0
        /// <summary>
        /// Reads the CLR source file name, line number and displacement.
        /// </summary>
        /// <param name="pdbName">The name of pdb.</param>
        /// <param name="method">The method.</param>
        /// <param name="address">The address.</param>
        internal static Tuple <string, uint, ulong> ReadClrSourceFileNameAndLine(String pdbName, Microsoft.Diagnostics.Runtime.ClrMethod method, ulong address)
        {
            Microsoft.Diagnostics.Runtime.Utilities.Pdb.PdbReader   pdbReader = new Microsoft.Diagnostics.Runtime.Utilities.Pdb.PdbReader(pdbName);
            Microsoft.Diagnostics.Runtime.Utilities.Pdb.PdbFunction function  = pdbReader.GetFunctionFromToken(method.MetadataToken);
            uint ilOffset = FindIlOffset(method, address);

            ulong  distance       = ulong.MaxValue;
            string sourceFileName = "";
            uint   sourceFileLine = uint.MaxValue;

            if (function != null && function.SequencePoints != null)
            {
                foreach (Microsoft.Diagnostics.Runtime.Utilities.Pdb.PdbSequencePointCollection sequenceCollection in function.SequencePoints)
                {
                    foreach (Microsoft.Diagnostics.Runtime.Utilities.Pdb.PdbSequencePoint point in sequenceCollection.Lines)
                    {
                        if (point.Offset <= ilOffset)
                        {
                            ulong dist = ilOffset - point.Offset;

                            if (dist < distance)
                            {
                                sourceFileName = sequenceCollection.File.Name;
                                sourceFileLine = point.LineBegin;
                                distance       = dist;
                            }
                        }
                    }
                }

                return(Tuple.Create(sourceFileName, sourceFileLine, distance));
            }
            else
            {
                return(Tuple.Create("", (uint)0, (ulong)0));
            }
        }
Exemple #12
0
 /// <summary>
 /// Gets the source location of a given metadata token for a function and offset.
 /// </summary>
 /// <param name="method">The method to look up the source information.</param>
 /// <param name="ilOffset">The il offset to look up the source information.</param>
 /// <returns>The SourceLocation for the given IL offset, or null if no mapping exists.</returns>
 public abstract SourceLocation GetSourceInformation(ClrMethod method, int ilOffset);
Exemple #13
0
 public virtual SourceLocation GetSourceInformation(ClrMethod method, int ilOffset) { return null; }
 public MethodInformation(ClrDumpType dumpType, ClrMethod clrMethod)
 {
     this.dumpType = dumpType;
     this.clrMethod = clrMethod;
 }
 public DelegateTargetInformation(ulong address, ClrDumpType clrDumpType, ClrMethod methInfo) : this(address, clrDumpType)
 {
     this.methInfo = methInfo;
 }