Esempio n. 1
0
        /// <summary>
        /// Provides default binding for performing a call on the specified meta objects.
        /// </summary>
        /// <param name="signature">The signature describing the call</param>
        /// <param name="target">The meta object to be called.</param>
        /// <param name="args">
        /// Additional meta objects are the parameters for the call as specified by the CallSignature in the CallAction.
        /// </param>
        /// <param name="resolverFactory">Overload resolver factory.</param>
        /// <param name="errorSuggestion">The result should the object be uncallable.</param>
        /// <returns>A MetaObject representing the call or the error.</returns>
        public DynamicMetaObject Call(CallSignature signature, DynamicMetaObject errorSuggestion, OverloadResolverFactory resolverFactory,ClrMethod method, DynamicMetaObject target, params DynamicMetaObject[] args)
        {
            ContractUtils.RequiresNotNullItems(args, "args");
            ContractUtils.RequiresNotNull(resolverFactory, "resolverFactory");

            TargetInfo targetInfo = GetTargetInfo(method, target, args);

            if (targetInfo != null)
            {
                // we're calling a well-known MethodBase
                DynamicMetaObject res = MakeMetaMethodCall(signature, resolverFactory, targetInfo);
                if (res.Expression.Type.IsValueType)
                {
                    if (res.Expression.Type == Types.Void)
                        res = new DynamicMetaObject(
                            Expression.Block(Types.Object[0],
                                res.Expression,
                                Expression.Constant(null)),
                            res.Restrictions
                        );
                    else
                        res = new DynamicMetaObject(
                            Expression.Convert(res.Expression, typeof(object)),
                            res.Restrictions
                    );
                }

                return res;
            }
            else
            {
                // we can't call this object
                return errorSuggestion ?? MakeCannotCallRule(target, target.GetLimitType());
            }
        }
Esempio n. 2
0
        public override SourceLocation GetSourceInformation(ClrMethod method, int ilOffset)
        {
            if (method == null)
                throw new ArgumentNullException("method");

            if (method.Type != null && method.Type.Module != this)
                throw new InvalidOperationException("Method not in this module.");

            return GetSourceInformation(method.MetadataToken, ilOffset);
        }
Esempio n. 3
0
        /// <summary>
        /// Gets a TargetInfo object for performing a call on this object.  
        /// </summary>
        private TargetInfo GetTargetInfo(ClrMethod method, DynamicMetaObject target, DynamicMetaObject[] args)
        {
            Debug.NotNull(method);
            Debug.Assert(target.HasValue);
            object objTarget = target.Value;

            List<MethodBase> foundTargets = new List<MethodBase>(method.Overloads.Count);

            foreach (PHP.Core.Reflection.ClrMethod.Overload overload in method.Overloads)
            {
                foundTargets.Add(overload.Method);
            }

            return new TargetInfo(target, args, target.Restrictions, foundTargets.ToArray()); 


        }
Esempio n. 4
0
		/// <summary>
		/// Used by full-reflect (<see cref="DTypeDesc"/>).
		/// </summary>
		internal static ClrMethod/*!*/ CreateConstructor(ClrTypeDesc/*!*/ declaringType)
		{
			ClrMethod result;

			if (declaringType is ClrDelegateDesc)
			{
				// the real constructor should not be accessible from PHP code
				result = new ClrMethod(Name.ClrCtorName, declaringType, PhpMemberAttributes.Constructor, 1, false);
				result.ClrMethodDesc.ArglessStub = new RoutineDelegate(declaringType._NoConstructorErrorStub);
			}
			else
			{
				ConstructorInfo[] realOverloads = declaringType.RealType.GetConstructors(
				BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

				//// TODO (less restrictive?):
				PhpMemberAttributes attrs = PhpMemberAttributes.Constructor;

				int visible_count = 0;
				for (int i = 0; i < realOverloads.Length; i++)
				{
					if (ClrTypeDesc.IsMethodVisible(realOverloads[i]))
						visible_count++;
				}

                if (declaringType.RealType.IsValueType) // add an empty .ctor
                    visible_count++;


				if (visible_count > 0)
				{
					result = new ClrMethod(Name.ClrCtorName, declaringType, attrs, visible_count, false);

					foreach (MethodBase real_overload in realOverloads)
					{
						if (ClrTypeDesc.IsMethodVisible(real_overload))
						{
							Overload overload;
							result.AddOverload(real_overload, out overload);
						}
					}

                    if (declaringType.RealType.IsValueType) // add an empty .ctor
                    {
                        Overload overload;
                        result.AddOverload(BuildDefaultValueCtor(declaringType.RealType), out overload);
                    }
				}
				else
				{
					result = new ClrMethod(Name.ClrCtorName, declaringType, PhpMemberAttributes.Constructor, 1, false);
					result.ClrMethodDesc.ArglessStub = new RoutineDelegate(declaringType._NoConstructorErrorStub);
				}
			}

			return result;
		}
Esempio n. 5
0
 public DesktopStackFrame(DesktopRuntimeBase runtime, ulong sp, string method, ClrMethod innerMethod)
 {
     _runtime = runtime;
     _sp = sp;
     _frameName = method ?? "Unknown";
     _type = ClrStackFrameType.Runtime;
     _method = innerMethod;
 }
        private static void TryTranslateAddressToName(Instruction instruction, State state, int depth, ClrMethod currentMethod)
        {
            var runtime = state.Runtime;

            if (!TryGetReferencedAddress(instruction, (uint)runtime.PointerSize, out ulong address))
            {
                return;
            }

            if (state.AddressToNameMapping.ContainsKey(address))
            {
                return;
            }

            var jitHelperFunctionName = runtime.GetJitHelperFunctionName(address);

            if (!string.IsNullOrEmpty(jitHelperFunctionName))
            {
                state.AddressToNameMapping.Add(address, jitHelperFunctionName);
                return;
            }

            var methodTableName = runtime.GetMethodTableName(address);

            if (!string.IsNullOrEmpty(methodTableName))
            {
                state.AddressToNameMapping.Add(address, $"MT_{methodTableName}");
                return;
            }

            var methodDescriptor = runtime.GetMethodByHandle(address);

            if (!(methodDescriptor is null))
            {
                state.AddressToNameMapping.Add(address, $"MD_{methodDescriptor.GetFullSignature()}");
                return;
            }

            var method = runtime.GetMethodByAddress(address);

            if (method is null && (address & ((uint)runtime.PointerSize - 1)) == 0)
            {
                if (runtime.ReadPointer(address, out ulong newAddress) && newAddress > ushort.MaxValue)
                {
                    method = runtime.GetMethodByAddress(newAddress);
                }
            }

            if (method is null)
            {
                return;
            }

            if (method.NativeCode == currentMethod.NativeCode && method.GetFullSignature() == currentMethod.GetFullSignature())
            {
                return; // in case of a call which is just a jump within the method or a recursive call
            }
            if (!state.HandledMethods.Contains(method))
            {
                state.Todo.Enqueue(new MethodInfo(method, depth + 1));
            }

            var methodName = method.GetFullSignature();

            if (!methodName.Any(c => c == '.')) // the method name does not contain namespace and type name
            {
                methodName = $"{method.Type.Name}.{method.GetFullSignature()}";
            }
            state.AddressToNameMapping.Add(address, methodName);
        }
Esempio n. 7
0
 public override SourceLocation GetSourceInformation(ClrMethod method, int ilOffset)
 {
     return(null);
 }
Esempio n. 8
0
 extern private static Delegate CreateBlankDelegate
     (Type type, ClrMethod method);
Esempio n. 9
0
 /// <summary>
 /// If the adapted method is a generic method definition with the supplied number and
 /// type of parameters, closes the method with the supplied arguments
 /// </summary>
 /// <param name="args"></param>
 /// <returns></returns>
 public Option <ClrMethod> CloseGenericMethod(params ClrType[] args)
 => Try(() => ClrMethod.Get(ReflectedElement.MakeGenericMethod(array(args, a => a.ReflectedElement))));
Esempio n. 10
0
        /// <summary>
        /// Provides default binding for performing a call on the specified meta objects.
        /// </summary>
        /// <param name="signature">The signature describing the call</param>
        /// <param name="target">The meta object to be called.</param>
        /// <param name="args">
        /// Additional meta objects are the parameters for the call as specified by the CallSignature in the CallAction.
        /// </param>
        /// <param name="resolverFactory">Overload resolver factory.</param>
        /// <param name="errorSuggestion">The result should the object be uncallable.</param>
        /// <returns>A MetaObject representing the call or the error.</returns>
        public DynamicMetaObject Call(CallSignature signature, DynamicMetaObject errorSuggestion, OverloadResolverFactory resolverFactory, ClrMethod method, DynamicMetaObject target, params DynamicMetaObject[] args)
        {
            ContractUtils.RequiresNotNullItems(args, "args");
            ContractUtils.RequiresNotNull(resolverFactory, "resolverFactory");

            TargetInfo targetInfo = GetTargetInfo(method, target, args);

            if (targetInfo != null)
            {
                // we're calling a well-known MethodBase
                DynamicMetaObject res = MakeMetaMethodCall(signature, resolverFactory, targetInfo);
                if (res.Expression.Type.IsValueType)
                {
                    if (res.Expression.Type == Types.Void)
                    {
                        res = new DynamicMetaObject(
                            Expression.Block(Types.Object[0],
                                             res.Expression,
                                             Expression.Constant(null)),
                            res.Restrictions
                            );
                    }
                    else
                    {
                        res = new DynamicMetaObject(
                            Expression.Convert(res.Expression, typeof(object)),
                            res.Restrictions
                            );
                    }
                }

                return(res);
            }
            else
            {
                // we can't call this object
                return(errorSuggestion ?? MakeCannotCallRule(target, target.GetLimitType()));
            }
        }
 public DelegateTargetInformation(ulong address, ClrDumpType clrDumpType, ClrMethod methInfo) : this(address, clrDumpType)
 {
     this.methInfo = methInfo;
 }
Esempio n. 12
0
 /// <summary>
 /// Defines a method signature based on relected metadata
 /// </summary>
 /// <param name="method">The reflected method</param>
 /// <returns></returns>
 public static MethodSignature SpecifyMethodSignature(this ClrMethod method)
 => new MethodSignature(method.Name,
                        method.ReturnType.ValueOrDefault().SpecifyClrTypeReference(),
                        map(method.Parameters, p => p.Specify())
                        );
Esempio n. 13
0
        public DynamicMetaObject CallClrMethod(ClrMethod method, DynamicMetaObject target, DynamicMetaObject[] args)
        {
            CallSignature signature = new CallSignature(args.Length);

            return(Call(signature, null, new DefaultOverloadResolverFactory(this), method, target, args));
        }
Esempio n. 14
0
        private static void PrintILToNativeOffsets(ClrMethod method, ulong startAddress, IList<string> lines)
        {
            Console.WriteLine("IL -> Native Offsets:");
            Console.WriteLine("\t" + String.Join("\n\t", @method.ILOffsetMap));
            foreach (ILToNativeMap il in @method.ILOffsetMap)
            {
                SourceLocation sourceLocation = null;
                try
                {
                    Console.WriteLine(
                        "\nPrintILToNativeOffsets, il.Offset: {0,10} ({1,3:N0}), il.StartAddress: {2} ({2,8:X8})",
                        "0x" + il.ILOffset.ToString("X2"), il.ILOffset, il.StartAddress);
                    if (il.ILOffset < 0) // FFFF FFFX is 4,294,967,280
                        continue;
                    sourceLocation = @method.GetSourceLocationForOffset(il.StartAddress);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    continue;
                }

                var sourceInfo = "<UNKNOWN>";
                if (sourceLocation != null)
                {
                    if (sourceLocation.LineNumber == sourceLocation.LineNumberEnd)
                    {
                        sourceInfo = String.Format("{0}:{1} (Columns {2}->{3})",
                                                   Path.GetFileName(sourceLocation.FilePath),
                                                   sourceLocation.LineNumber, sourceLocation.ColStart,
                                                   sourceLocation.ColEnd);
                    }
                    else
                    {
                        sourceInfo = String.Format("{0}: {1}->{2} ({3}->{4})",
                                                   Path.GetFileName(sourceLocation.FilePath),
                                                   sourceLocation.LineNumber, sourceLocation.LineNumberEnd,
                                                   sourceLocation.ColStart, sourceLocation.ColEnd);
                    }
                }

                Console.WriteLine("{0,10} ({1,3:N0}) - [{2:X8}-{3:X8} ({4:X8}-{5:X8})] {6}",
                                  "0x" + il.ILOffset.ToString("X2"), il.ILOffset,
                                  il.StartAddress - startAddress, il.EndAddress - startAddress,
                                  il.StartAddress, il.EndAddress, sourceInfo);
                if (sourceLocation != null && il.ILOffset >= 0)
                {
                    var indent = 7;
                    Console.WriteLine("{0,6}:{1}", sourceLocation.LineNumber, lines[sourceLocation.LineNumber - 1]);
                    Console.WriteLine(new string(' ', sourceLocation.ColStart - 1 + indent) +
                                      new string('*', sourceLocation.ColEnd - sourceLocation.ColStart));
                }
            }
        }
Esempio n. 15
0
        private static void PrintILToNativeOffsetAlternative(ClrMethod method, IList<string> lines)
        {
            DesktopModule module = (DesktopModule) @method.Type.Module;
            if (!module.IsPdbLoaded)
            {
                // Have to load the Pdb, if it's not already loaded!!
                string val = module.TryDownloadPdb(null);
                if (val != null)
                    module.LoadPdb(val);
            }

            foreach (var location in module.GetSourceLocationsForMethod(@method.MetadataToken))
            {
                ILOffsetSourceLocation ILLocation = location;
                var ilMaps = @method.ILOffsetMap.Where(il => il.ILOffset == ILLocation.ILOffset);
                Console.WriteLine("{0:X8} -> {1}:{2}",
                                  location.ILOffset,
                                  Path.GetFileName(location.SourceLocation.FilePath),
                                  location.SourceLocation.LineNumber);
                Console.WriteLine("  " + String.Join("\n  ",
                                                     ilMaps.Select(
                                                         ilMap =>
                                                         String.Format("[{0:X8}-{1:X8} ({2:X8}-{3:X8})] ILOffset: {4:X2}",
                                                                       ilMap.StartAddress - @method.NativeCode,
                                                                       ilMap.EndAddress - @method.NativeCode,
                                                                       ilMap.StartAddress, ilMap.EndAddress, ilMap.ILOffset))));
                var indent = 7;
                Console.WriteLine("{0,6}:{1}", location.SourceLocation.LineNumber, lines[location.SourceLocation.LineNumber - 1]);
                Console.WriteLine(new string(' ', location.SourceLocation.ColStart - 1 + indent) +
                                  new string('*', location.SourceLocation.ColEnd - location.SourceLocation.ColStart));
            }
            Console.WriteLine();
        }
Esempio n. 16
0
        // Sample based on https://github.com/Microsoft/dotnetsamples/blob/master/Microsoft.Diagnostics.Runtime/CLRMD/docs/MachineCode.md
        // All the common code was copied from the MemStats project "dotnetsamples-master\Microsoft.Diagnostics.Runtime\CLRMD\MemStats\Program.cs"
        static void Main(string[] args)
        {
            string dump, dac;

            if (!TryParseArgs(args, out dump, out dac))
            {
                Usage();
                Environment.Exit(1);
            }

            try
            {
                // Create a ClrRuntime instance from the dump and dac location.  The ClrRuntime
                // object represents a version of CLR loaded in the process.  It contains data
                // such as the managed threads in the process, the AppDomains in the process,
                // the managed heap, and so on.
                //ClrRuntime runtime = CreateRuntime(dump, dac);

                // 1. Get the ClrType object for the type the method is on
                // 2. Get the ClrMethod object for the method
                // 3. Get the offset of the native code
                // 4. Compute the end address by mapping the IL instruction to addresses
                // 5. Disassemble the native code contained in that range (not provided by CLRMD)

                using (DataTarget dt = DataTarget.LoadCrashDump(dump))
                {
                    // Boilerplate.
                    //ClrRuntime runtime = dt.CreateRuntime(dt.ClrVersions.Single().TryDownloadDac());
                    var version = dt.ClrVersions.Single();
                    //{v4.0.30319.18444}
                    //version.Version = new VersionInfo { Major = 4, Minor = 0, Patch = 30319, Revision = 18444 };
                    Console.WriteLine("CLR Version: {0} ({1}), Dac: {2}", version.Version, version.Flavor, version.DacInfo);
                    var dacFileName = version.TryDownloadDac();
                    Console.WriteLine("DacFile: " + Path.GetFileName(dacFileName));
                    Console.WriteLine("DacPath: " + Path.GetDirectoryName(dacFileName));
                    ClrRuntime runtime = dt.CreateRuntime(dacFileName);
                    ClrHeap    heap    = runtime.GetHeap();

                    PrintDiagnosticInfo(dt, runtime, heap);
                    Console.WriteLine();

                    // Note heap.GetTypeByName doesn't always get you the type, even if it exists, due to
                    // limitations in the dac private apis that ClrMD is written on.  If you have the ClrType
                    // already via other means (heap walking, stack walking, etc), then that's better than
                    // using GetTypeByName:
                    var     classNameWithNamespace = "JITterOptimisations.Program";
                    ClrType @class = heap.GetTypeByName(classNameWithNamespace);

                    // Get the method you are looking for.
                    var       signature = "JITterOptimisations.Program.Log(System.ConsoleColor, System.String)";
                    ClrMethod @method   = @class.Methods.Single(m => m.GetFullSignature() == signature);

                    // This is the first instruction of the JIT'ed (or NGEN'ed) machine code.
                    ulong startAddress = @method.NativeCode;

                    // Unfortunately there's not a great way to get the size of the code, or the end address.
                    // This is partly due to the fact that we don't *have* to put all the JIT'ed code into one
                    // contiguous chunk, though I think an implementation detail is that we actually do.
                    // 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 = @method.ILOffsetMap.Select(entry => entry.EndAddress).Max();

                    var lines =
                        File.ReadAllLines(
                            @"C:\Users\warma11\Documents\Visual Studio 2013\Projects\JITterOptimisations\JITterOptimisations\Program.cs");

                    PrintILToNativeOffsetAlternative(method, lines);

                    // This doesn't seem to work as expected, using alternative method (above)
                    //PrintILToNativeOffsets(method, startAddress, lines);

                    // So the assembly code for the function is is in the range [startAddress, endAddress] inclusive.
                    var count = (int)endAddress + runtime.PointerSize - (int)startAddress;
                    Console.WriteLine("\nCode startAddress 0x{0:X} -> endAddress 0x{1:X} (inclusive), will read {2} bytes", startAddress, endAddress, count);

                    var bytes = new byte[count];
                    int bytesRead;
                    runtime.ReadMemory(startAddress, bytes, count, out bytesRead);
                    if (count != bytesRead)
                    {
                        Console.WriteLine("Expected to read {0} bytes, but only read {1}\n", count, bytesRead);
                    }
                    else
                    {
                        Console.WriteLine("Read read {0} bytes, as expected\n", bytesRead);
                    }
                    var fileName = string.Format("result-{0}bit.bin", runtime.PointerSize == 8 ? 64 : 32);
                    if (File.Exists(fileName))
                    {
                        File.Delete(fileName);
                    }
                    File.WriteAllBytes(fileName, bytes);

                    var filename =
                        @"C:\Users\warma11\Downloads\__GitHub__\dotnetsamples\Microsoft.Diagnostics.Runtime\CLRMD\MachineCode\nasm-2.11.05-win32\ndisasm.exe";
                    var currentFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                    var arguments     = "-b32 " + Path.Combine(currentFolder, fileName); // +" -o " + startAddress;
                    var disassembly   = Disassembler.GetDisassembly(filename, arguments, timeoutMsecs: 250);

                    var assemblyData = Disassembler.ProcessDisassembly(disassembly);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Unhandled exception:");
                Console.WriteLine(ex);
            }
        }
Esempio n. 17
0
        private static void TryTranslateAddressToName(Instruction instruction, State state, int depth, ClrMethod currentMethod)
        {
            var runtime = state.Runtime;

            if (!TryGetReferencedAddress(instruction, (uint)runtime.DataTarget.DataReader.PointerSize, out ulong address))
            {
                return;
            }

            if (state.AddressToNameMapping.ContainsKey(address))
            {
                return;
            }

            var jitHelperFunctionName = runtime.GetJitHelperFunctionName(address);

            if (!string.IsNullOrEmpty(jitHelperFunctionName))
            {
                state.AddressToNameMapping.Add(address, jitHelperFunctionName);
                return;
            }

            var methodTableName = runtime.DacLibrary.SOSDacInterface.GetMethodTableName(address);

            if (!string.IsNullOrEmpty(methodTableName))
            {
                state.AddressToNameMapping.Add(address, $"MT_{methodTableName}");
                return;
            }

            var methodDescriptor = runtime.GetMethodByHandle(address);

            if (!(methodDescriptor is null))
            {
                state.AddressToNameMapping.Add(address, $"MD_{methodDescriptor.Signature}");
                return;
            }

            var method = runtime.GetMethodByInstructionPointer(address);

            if (method is null && (address & ((uint)runtime.DataTarget.DataReader.PointerSize - 1)) == 0)
            {
                if (runtime.DataTarget.DataReader.ReadPointer(address, out ulong newAddress) && newAddress > ushort.MaxValue)
                {
                    method = runtime.GetMethodByInstructionPointer(newAddress);

                    method = WorkaroundGetMethodByInstructionPointerBug(runtime, method, newAddress);
                }
            }
Esempio n. 18
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 >= 0 // prolog is -2, epilog -3
                               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
            var prologue = method.ILOffsetMap[0];

            if (prologue.ILOffset == -2) // -2 is a magic number for prologue
            {
                DisassembleNative(prologue);
            }

            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)
                    {
                        var sourceLine = ReadSourceLine(sourceLocation.FilePath, line);

                        if (sourceLine != null)
                        {
                            _context.WriteLine(sourceLine);
                            _context.WriteLine(new string(' ', sourceLocation.ColStart - 1) + new string('^', sourceLocation.ColEnd - sourceLocation.ColStart));
                        }
                    }
                }
                PrintInstructions(instructions);
                DisassembleNative(map);
            }

            var epilogue = method.ILOffsetMap[method.ILOffsetMap.Length - 1];

            if (epilogue.ILOffset == -3) // -3 is a magic number for epilog
            {
                DisassembleNative(epilogue);
            }
        }
Esempio n. 19
0
 public override SourceLocation GetSourceInformation(ClrMethod method, int ilOffset)
 {
     return null;
 }
Esempio n. 20
0
 public static Option <ClrMethod> method(Type declaringType, string name, params Type[] argTypes)
 => declaringType.MatchMethod(name, argTypes).Map(x => ClrMethod.Get(x));
Esempio n. 21
0
        private void SetThreadWaiters()
        {
            HashSet <string>      eventTypes = null;
            List <BlockingObject> blobjs     = new List <BlockingObject>();

            foreach (DesktopThread thread in _runtime.Threads)
            {
                int max = thread.StackTrace.Count;
                if (max > 10)
                {
                    max = 10;
                }

                blobjs.Clear();
                for (int i = 0; i < max; ++i)
                {
                    DesktopBlockingObject blockingObj = null;
                    ClrMethod             method      = thread.StackTrace[i].Method;
                    if (method == null)
                    {
                        continue;
                    }

                    ClrType type = method.Type;
                    if (type == null)
                    {
                        continue;
                    }

                    switch (method.Name)
                    {
                    case "AcquireWriterLockInternal":
                    case "FCallUpgradeToWriterLock":
                    case "UpgradeToWriterLock":
                    case "AcquireReaderLockInternal":
                    case "AcquireReaderLock":
                        if (type.Name == "System.Threading.ReaderWriterLock")
                        {
                            blockingObj = FindLocks(thread.StackLimit, thread.StackTrace[i].StackPointer, IsReaderWriterLock);
                            if (blockingObj == null)
                            {
                                blockingObj = FindLocks(thread.StackTrace[i].StackPointer, thread.StackBase, IsReaderWriterLock);
                            }

                            if (blockingObj != null && (blockingObj.Reason == BlockingReason.Unknown || blockingObj.Reason == BlockingReason.None))
                            {
                                // This should have already been set correctly when the BlockingObject was created.  This is just a best-guess.
                                if (method.Name == "AcquireReaderLockInternal" || method.Name == "AcquireReaderLock")
                                {
                                    blockingObj.Reason = BlockingReason.WriterAcquired;
                                }
                                else
                                {
                                    blockingObj.Reason = BlockingReason.ReaderAcquired;
                                }
                            }
                        }
                        break;

                    case "TryEnterReadLockCore":
                    case "TryEnterReadLock":
                    case "TryEnterUpgradeableReadLock":
                    case "TryEnterUpgradeableReadLockCore":
                    case "TryEnterWriteLock":
                    case "TryEnterWriteLockCore":
                        if (type.Name == "System.Threading.ReaderWriterLockSlim")
                        {
                            blockingObj = FindLocks(thread.StackLimit, thread.StackTrace[i].StackPointer, IsReaderWriterSlim);
                            if (blockingObj == null)
                            {
                                blockingObj = FindLocks(thread.StackTrace[i].StackPointer, thread.StackBase, IsReaderWriterSlim);
                            }


                            if (blockingObj != null && (blockingObj.Reason == BlockingReason.Unknown || blockingObj.Reason == BlockingReason.None))
                            {
                                // This should have already been set correctly when the BlockingObject was created.  This is just a best-guess.
                                if (method.Name == "TryEnterWriteLock" || method.Name == "TryEnterWriteLockCore")
                                {
                                    blockingObj.Reason = BlockingReason.ReaderAcquired;
                                }
                                else
                                {
                                    blockingObj.Reason = BlockingReason.WriterAcquired;
                                }
                            }
                        }

                        break;

                    case "JoinInternal":
                    case "Join":
                        if (type.Name == "System.Threading.Thread")
                        {
                            if (FindThread(thread.StackLimit, thread.StackTrace[i].StackPointer, out ulong threadAddr, out ClrThread target) ||
                                FindThread(thread.StackTrace[i].StackPointer, thread.StackBase, out threadAddr, out target))
                            {
                                if (!_joinLocks.TryGetValue(target, out blockingObj))
                                {
                                    _joinLocks[target] = blockingObj = new DesktopBlockingObject(threadAddr, true, 0, target, BlockingReason.ThreadJoin);
                                }
                            }
                        }
                        break;

                    case "Wait":
                    case "ObjWait":
                        if (type.Name == "System.Threading.Monitor")
                        {
                            blockingObj = FindMonitor(thread.StackLimit, thread.StackTrace[i].StackPointer);
                            if (blockingObj == null)
                            {
                                blockingObj = FindMonitor(thread.StackTrace[i].StackPointer, thread.StackBase);
                            }

                            blockingObj.Reason = BlockingReason.MonitorWait;
                        }
                        break;

                    case "WaitAny":
                    case "WaitAll":
                        if (type.Name == "System.Threading.WaitHandle")
                        {
                            ulong obj = FindWaitObjects(thread.StackLimit, thread.StackTrace[i].StackPointer, "System.Threading.WaitHandle[]");
                            if (obj == 0)
                            {
                                obj = FindWaitObjects(thread.StackTrace[i].StackPointer, thread.StackBase, "System.Threading.WaitHandle[]");
                            }

                            if (obj != 0)
                            {
                                BlockingReason reason = method.Name == "WaitAny" ? BlockingReason.WaitAny : BlockingReason.WaitAll;
                                if (!_waitLocks.TryGetValue(obj, out blockingObj))
                                {
                                    _waitLocks[obj] = blockingObj = new DesktopBlockingObject(obj, true, 0, null, reason);
                                }
                            }
                        }
                        break;

                    case "WaitOne":
                    case "InternalWaitOne":
                    case "WaitOneNative":
                        if (type.Name == "System.Threading.WaitHandle")
                        {
                            if (eventTypes == null)
                            {
                                eventTypes = new HashSet <string>
                                {
                                    "System.Threading.Mutex",
                                    "System.Threading.Semaphore",
                                    "System.Threading.ManualResetEvent",
                                    "System.Threading.AutoResetEvent",
                                    "System.Threading.WaitHandle",
                                    "Microsoft.Win32.SafeHandles.SafeWaitHandle"
                                };
                            }

                            ulong obj = FindWaitHandle(thread.StackLimit, thread.StackTrace[i].StackPointer, eventTypes);
                            if (obj == 0)
                            {
                                obj = FindWaitHandle(thread.StackTrace[i].StackPointer, thread.StackBase, eventTypes);
                            }

                            if (obj != 0)
                            {
                                if (_waitLocks == null)
                                {
                                    _waitLocks = new Dictionary <ulong, DesktopBlockingObject>();
                                }

                                if (!_waitLocks.TryGetValue(obj, out blockingObj))
                                {
                                    _waitLocks[obj] = blockingObj = new DesktopBlockingObject(obj, true, 0, null, BlockingReason.WaitOne);
                                }
                            }
                        }
                        break;


                    case "TryEnter":
                    case "ReliableEnterTimeout":
                    case "TryEnterTimeout":
                    case "ReliableEnter":
                    case "Enter":
                        if (type.Name == "System.Threading.Monitor")
                        {
                            blockingObj = FindMonitor(thread.StackLimit, thread.StackTrace[i].StackPointer);
                            if (blockingObj != null)
                            {
                                blockingObj.Reason = BlockingReason.Monitor;
                            }
                        }
                        break;
                    }


                    if (blockingObj != null)
                    {
                        bool alreadyEncountered = false;
                        foreach (var blobj in blobjs)
                        {
                            if (blobj.Object == blockingObj.Object)
                            {
                                alreadyEncountered = true;
                                break;
                            }
                        }

                        if (!alreadyEncountered)
                        {
                            blobjs.Add(blockingObj);
                        }
                    }
                }

                foreach (DesktopBlockingObject blobj in blobjs)
                {
                    blobj.AddWaiter(thread);
                }
                thread.SetBlockingObjects(blobjs.ToArray());
            }
        }
Esempio n. 22
0
        static string TryEnqueueCalledMethod(string textRepresentation, State state, int depth, ClrMethod currentMethod)
        {
            if (!TryGetHexAdress(textRepresentation, out ulong address))
            {
                return(null); // call    qword ptr [rax+20h] // needs further research
            }
            var method = state.Runtime.GetMethodByAddress(address);

            if (method == null) // not managed method
            {
                return(Errors.NotManagedMethod);
            }

            if (method.NativeCode == currentMethod.NativeCode && method.GetFullSignature() == currentMethod.GetFullSignature())
            {
                return(null); // in case of call which is just a jump within the method
            }
            if (!state.HandledMetadataTokens.Contains(method.MetadataToken))
            {
                state.Todo.Enqueue(new MethodInfo(method, depth + 1));
            }

            return(method.GetFullSignature());
        }
Esempio n. 23
0
 public DesktopStackFrame(DesktopRuntimeBase runtime, DesktopThread thread, ulong sp, string method, ClrMethod innerMethod)
 {
     _runtime   = runtime;
     _thread    = thread;
     _sp        = sp;
     _frameName = method ?? "Unknown";
     _type      = ClrStackFrameType.Runtime;
     _method    = innerMethod;
 }
Esempio n. 24
0
 internal MethodInfo(ClrMethod method, int depth)
 {
     Method = method;
     Depth  = depth;
 }
        private static IEnumerable <Asm> Decode(ulong startAddress, uint size, State state, int depth, ClrMethod currentMethod)
        {
            byte[] code = new byte[size];
            if (!state.Runtime.DataTarget.ReadProcessMemory(startAddress, code, code.Length, out int bytesRead) || bytesRead == 0)
            {
                yield break;
            }

            var reader  = new ByteArrayCodeReader(code, 0, bytesRead);
            var decoder = Decoder.Create(state.Runtime.PointerSize * 8, reader);

            decoder.IP = startAddress;

            while (reader.CanReadByte)
            {
                decoder.Decode(out var instruction);

                TryTranslateAddressToName(instruction, state, depth, currentMethod);

                yield return(new Asm
                {
                    InstructionPointer = instruction.IP,
                    Instruction = instruction
                });
            }
        }
Esempio n. 26
0
 public DynamicMetaObject CallClrMethod(ClrMethod method, DynamicMetaObject target, DynamicMetaObject[] args)
 {
     CallSignature signature = new CallSignature(args.Length);
     return Call(signature,null,new DefaultOverloadResolverFactory(this), method, target, args);
 }
 private static DisassembledMethod CreateEmpty(ClrMethod method, string reason)
 => DisassembledMethod.Empty(method.GetFullSignature(), method.NativeCode, reason);
Esempio n. 28
0
 private static bool CanBeDisassembled(ClrMethod method) => method.ILOffsetMap.Length > 0 && method.NativeCode > 0;
Esempio n. 29
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);
                }

                // The GetSourceInformation method doesn't attempt to load symbols.
                if (!module.IsPdbLoaded)
                {
                    string pdb = module.TryDownloadPdb(null);
                    if (pdb != null)
                    {
                        module.LoadPdb(pdb);
                    }
                }
                var sourceLocation = module.GetSourceInformation(method, 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
        }
Esempio n. 30
0
		private void AddCompatibleOverloads(ClrMethod/*!*/ constructedMethod, ClrMethod/*!*/ genericMethod,
			DTypeDescs/*!*/ typeArgs, bool exactMatch)
		{
			foreach (ClrMethod.Overload overload in genericMethod.Overloads)
			{
				// add the overloads that are compatible with typeArgs
				int gen_count = overload.GenericParamCount;
				if (exactMatch ? gen_count == typeArgs.Count : gen_count > typeArgs.Count)
				{
					bool compatible = true;

					for (int i = 0; i < gen_count; i++)
					{
						DTypeDesc desc = (i < typeArgs.Count ? typeArgs[i] : PrimitiveTypeDesc.SystemObjectTypeDesc);
						if (!desc.IsCompatibleWithGenericParameter(overload.GenericParameters[i]))
						{
							compatible = false;
							break;
						}
					}

					if (compatible)
					{
						// make generic method
						Type[] real_type_args;
						if (exactMatch) real_type_args = typeArgs.GetRealTypes();
						else
						{
							real_type_args = new Type[gen_count];

							typeArgs.GetRealTypes(real_type_args, 0);
							for (int i = typeArgs.Count; i < gen_count; i++) real_type_args[i] = Types.Object[0];
						}
						MethodInfo info = ((MethodInfo)overload.Method).MakeGenericMethod(real_type_args);

						ClrMethod.Overload constructed_overload;
						constructedMethod.AddOverload(info, out constructed_overload);
					}
				}
			}
		}
Esempio n. 31
0
 public DesktopStackFrame(DesktopRuntimeBase runtime, ulong sp, string method, ClrMethod innerMethod)
 {
     m_sp = sp;
     m_frameName = method;
     m_type = ClrStackFrameType.Runtime;
     m_method = innerMethod;
     m_runtime = runtime;
 }
Esempio n. 32
0
        internal static void ReflectFunction(DTypeDesc declaringType, MethodInfo real_function, Dictionary<string, DRoutineDesc> functions)
        {
            if (!real_function.IsSpecialName)
            {
                QualifiedName qualified_name = QualifiedName.FromClrNotation(real_function.Name, true);
                string full_name = qualified_name.ToString();

                ClrMethod clr_function = null;

                DRoutineDesc existing;
                if (functions.TryGetValue(full_name, out existing))
                {
                    if (existing.DeclaringType.Equals(declaringType))
                    {
                        Debug.Assert(existing is ClrMethodDesc, "CLR module should contain CLR methods only");

                        // an overload of existing CLR function:
                        clr_function = existing.ClrMethod;
                    }
                    else
                    {
                        // ambiguous:
                        clr_function = null;
                        existing.MemberAttributes |= PhpMemberAttributes.Ambiguous;
                    }
                }
                else
                {
                    // new entry:
                    clr_function = new ClrMethod(qualified_name.Name, declaringType, Enums.GetMemberAttributes(real_function), 1,
                            real_function.ContainsGenericParameters);

                    functions.Add(full_name, clr_function.ClrMethodDesc);
                }

                if (clr_function != null)
                {
                    ClrMethod.Overload overload;
                    clr_function.AddOverload(real_function, out overload);
                }
            }
        }
Esempio n. 33
0
		/// <summary>
		/// Creates a constructed method desc for the given type arguments.
		/// </summary>
		private ClrMethodDesc ConstructMethodDesc(DTypeDescs/*!*/ typeArgs)
		{
			ClrMethod generic_method = ClrMethod;
			ClrMethod constructed_method = new ClrMethod(generic_method.Name, declaringType, memberAttributes, 1, false);

			// add overloads which have an exact match
			AddCompatibleOverloads(constructed_method, generic_method, typeArgs, true);

			if (constructed_method.Overloads.Count == 0)
			{
				// now try overloads whose additional type parameters can by substituted by System.Object
				AddCompatibleOverloads(constructed_method, generic_method, typeArgs, false);

				if (constructed_method.Overloads.Count == 0)
				{
					// sorry, bad luck
					PhpException.NoSuitableOverload(generic_method.DeclaringType.FullName, generic_method.FullName);
					return null;
				}
			}

			return constructed_method.ClrMethodDesc;
		}
Esempio n. 34
0
        private static IEnumerable <Asm> Decode(ILToNativeMap map, State state, int depth, ClrMethod currentMethod)
        {
            ulong startAddress = map.StartAddress;
            uint  size         = (uint)(map.EndAddress - map.StartAddress);

            byte[] code = new byte[size];

            int totalBytesRead = 0;

            do
            {
                int bytesRead = state.Runtime.DataTarget.DataReader.Read(startAddress + (ulong)totalBytesRead, new Span <byte>(code, totalBytesRead, (int)size - totalBytesRead));
                if (bytesRead <= 0)
                {
                    throw new EndOfStreamException($"Tried to read {size} bytes for {currentMethod.Signature}, got only {totalBytesRead}");
                }
                totalBytesRead += bytesRead;
            } while (totalBytesRead != size);

            var reader  = new ByteArrayCodeReader(code, 0, (int)size);
            var decoder = Decoder.Create(state.Runtime.DataTarget.DataReader.PointerSize * 8, reader);

            decoder.IP = startAddress;

            while (reader.CanReadByte)
            {
                decoder.Decode(out var instruction);

                TryTranslateAddressToName(instruction, state, depth, currentMethod);

                yield return(new Asm
                {
                    InstructionPointer = instruction.IP,
                    Instruction = instruction
                });
            }
        }
Esempio n. 35
0
 public override SourceLocation GetSourceInformation(ClrMethod method, int ilOffset)
 {
     throw new NotImplementedException();
 }
Esempio n. 36
0
        /// <summary>
        /// Code from http://stackoverflow.com/questions/2057781/is-there-a-way-to-get-the-stacktraces-for-all-threads-in-c-like-java-lang-thre/24315960#24315960
        /// also see http://stackoverflow.com/questions/31633541/clrmd-throws-exception-when-creating-runtime/31745689#31745689
        /// </summary>
        internal IList <OutputLine> PrintCodeForMethod(Benchmark benchmark, Process process, bool printAssembly, bool printIL, bool printDiagnostics)
        {
            this.process = process;
            logger.Clear();

            //Method name format: "BenchmarkDotNet.Samples.Infra.RunFast()" (NOTE: WITHOUT the return type)
            var methodInfo = benchmark.Target.Method;

            fullTypeName = methodInfo.DeclaringType.FullName;

            var methodParams = string.Join(", ", methodInfo.GetParameters().Select(p => p.ParameterType.FullName));

            fullMethodName = $"{fullTypeName}.{methodInfo.Name}({methodParams})";

            logger?.WriteLine($"\nPrinting Code for Method: {fullMethodName}");
            logger?.WriteLine($"\nPrintAssembly={printAssembly}, PrintIL={printIL}");
            logger?.WriteLine($"Attaching to process {Path.GetFileName(process.MainModule.FileName)}, Pid={process.Id}");
            logger?.WriteLine($"Path {process.MainModule.FileName}");
            using (var dataTarget = DataTarget.AttachToProcess(process.Id, 5000, AttachFlag.NonInvasive))
            {
                var runtime = SetupClrRuntime(dataTarget);
                if (printDiagnostics)
                {
                    PrintRuntimeDiagnosticInfo(dataTarget, runtime);
                }

                if (printAssembly == false && printIL == false)
                {
                    return(logger.CapturedOutput);
                }

                ClrType       @class  = runtime.GetHeap().GetTypeByName(fullTypeName);
                ClrMethod     @method = @class.Methods.Single(m => m.GetFullSignature() == fullMethodName);
                DesktopModule module  = (DesktopModule)@method.Type.Module;
                if (!module.IsPdbLoaded)
                {
                    string pdbLocation = module.TryDownloadPdb(null);
                    if (pdbLocation != null)
                    {
                        module.LoadPdb(pdbLocation);
                    }
                }

                logger?.WriteLine($"Module: {Path.GetFileName(module.Name)}");
                logger?.WriteLine($"Type: {method.Type.Name}");
                logger?.WriteLine($"Method: {method.Name}");

                // TODO work out why this returns locations inside OTHER methods, it's like it doesn't have an upper bound and just keeps going!?
                var ilOffsetLocations = module.GetSourceLocationsForMethod(@method.MetadataToken);

                string   filePath = null;
                string[] lines    = null;
                logger?.WriteLine();
                for (int i = 0; i < ilOffsetLocations.Count; i++)
                {
                    var location = ilOffsetLocations[i];
                    var ilMaps   = @method.ILOffsetMap.Where(il => il.ILOffset == location.ILOffset).ToList();
                    if (ilMaps.Any() == false)
                    {
                        continue;
                    }

                    if (lines == null || location.SourceLocation.FilePath != filePath)
                    {
                        filePath = location.SourceLocation.FilePath;
                        lines    = File.ReadAllLines(filePath);
                        logger?.WriteLine($"Parsing file {Path.GetFileName(location.SourceLocation.FilePath)}");
                    }

                    PrintLocationAndILMapInfo(@method, location, ilMaps);
                    PrintSourceCode(lines, location);

                    if (printAssembly)
                    {
                        var debugControl = dataTarget.DebuggerInterface as IDebugControl;
                        PrintAssemblyCode(@method, ilMaps, runtime, debugControl);
                    }
                }

                return(logger.CapturedOutput);
            }
        }
Esempio n. 37
0
		public ClrOverloadBuilder(ILEmitter/*!*/ il, ClrMethod/*!*/ method, ConstructedType constructedType,
			IPlace/*!*/ stack, IPlace/*!*/ instance, bool emitParentCtorCall,
			ParameterLoader/*!*/ loadValueArg, ParameterLoader/*!*/ loadReferenceArg)
		{
			this.il = il;
			this.method = method;
			this.constructedType = constructedType;
			this.stack = stack;
			this.instance = instance;
			this.loadValueArg = loadValueArg;
			this.loadReferenceArg = loadReferenceArg;
			this.emitParentCtorCall = emitParentCtorCall;

			this.overloads = new List<Overload>(method.Overloads);
			SortOverloads(this.overloads);
		}
Esempio n. 38
0
 private string GenerateMethodInfo(ClrMethod method)
 {
     return($"{method.Type.Name}.{method.Name}");
 }
Esempio n. 39
0
 public override SourceLocation GetSourceInformation(ClrMethod method, int ilOffset)
 {
     throw new NotImplementedException();
 }
Esempio n. 40
0
 public HackMethod(QHackContext context, ClrMethod method)
 {
     Context           = context;
     InternalClrMethod = method;
 }