Ejemplo n.º 1
0
        private void DisassembleAndWriteMembers(JitWriteContext context, TypeInfo type, ImmutableArray <Type>?genericArgumentTypes = null)
        {
            if (type.IsGenericTypeDefinition)
            {
                if (TryDisassembleAndWriteMembersOfGeneric(context, type, genericArgumentTypes))
                {
                    return;
                }
            }

            foreach (var constructor in type.DeclaredConstructors)
            {
                DisassembleAndWriteMethod(context, constructor);
            }

            foreach (var method in type.DeclaredMethods)
            {
                if (method.IsAbstract)
                {
                    continue;
                }
                DisassembleAndWriteMethod(context, method);
            }

            foreach (var nested in type.DeclaredNestedTypes)
            {
                DisassembleAndWriteMembers(context, nested, genericArgumentTypes);
            }
        }
Ejemplo n.º 2
0
        private bool TryDisassembleAndWriteMembersOfGeneric(JitWriteContext context, TypeInfo type, ImmutableArray <Type>?parentArgumentTypes = null)
        {
            var hadAttribute = false;

            foreach (var attribute in type.GetCustomAttributes <JitGenericAttribute>(false))
            {
                hadAttribute = true;

                var fullArgumentTypes = (parentArgumentTypes ?? ImmutableArray <Type> .Empty)
                                        .AddRange(attribute.ArgumentTypes);
                var genericInstance = type.MakeGenericType(fullArgumentTypes.ToArray());
                DisassembleAndWriteMembers(context, genericInstance.GetTypeInfo(), fullArgumentTypes);
            }
            if (hadAttribute)
            {
                return(true);
            }

            if (parentArgumentTypes != null)
            {
                var genericInstance = type.MakeGenericType(parentArgumentTypes.Value.ToArray());
                DisassembleAndWriteMembers(context, genericInstance.GetTypeInfo(), parentArgumentTypes);
                return(true);
            }

            return(false);
        }
Ejemplo n.º 3
0
        public void Decompile(CompilationStreamPair streams, TextWriter codeWriter)
        {
            Argument.NotNull(nameof(streams), streams);
            Argument.NotNull(nameof(codeWriter), codeWriter);

            using (var loadContext = new CustomAssemblyLoadContext(shouldShareAssembly: _ => true)) {
                var assembly = loadContext.LoadFromStream(streams.AssemblyStream);
                ValidateStaticConstructors(assembly);

                using var runtimeLease = _runtimePool.GetOrCreate();
                var runtime = runtimeLease.Object;

                runtime.Flush();
                var context = new JitWriteContext(codeWriter, runtime);

                WriteJitInfo(runtime.ClrInfo, codeWriter);
                WriteProfilerState(codeWriter);

                foreach (var type in assembly.DefinedTypes)
                {
                    if (type.IsNested)
                    {
                        continue; // it's easier to handle nested generic types recursively, so we suppress all nested for consistency
                    }
                    DisassembleAndWriteMembers(context, type);
                }
            }
        }
Ejemplo n.º 4
0
        public void Decompile(CompilationStreamPair streams, TextWriter codeWriter)
        {
            Argument.NotNull(nameof(streams), streams);
            Argument.NotNull(nameof(codeWriter), codeWriter);

            using (var loadContext = new CustomAssemblyLoadContext(shouldShareAssembly: _ => true)) {
                var assembly = loadContext.LoadFromStream(streams.AssemblyStream);
                ValidateStaticConstructors(assembly);

                using var runtimeLease = _runtimePool.GetOrCreate();
                var runtime = runtimeLease.Object;

                runtime.Flush();
                var context = new JitWriteContext(codeWriter, runtime);
                context.Translator = new IntelTranslator {
                    SymbolResolver = (Instruction instruction, long addr, ref long offset) =>
                                     ResolveSymbol(runtime, instruction, addr, context.CurrentMethodAddress)
                };

                WriteJitInfo(runtime.ClrInfo, codeWriter);
                WriteProfilerState(codeWriter);

                var architecture = MapArchitecture(runtime.ClrInfo.DacInfo.TargetArchitecture);
                foreach (var type in assembly.DefinedTypes)
                {
                    if (type.IsNested)
                    {
                        continue; // it's easier to handle nested generic types recursively, so we suppress all nested for consistency
                    }
                    DisassembleAndWriteMembers(context, type);
                }
            }
        }
Ejemplo n.º 5
0
        private static void WriteSignatureFromReflection(JitWriteContext context, MethodBase method)
        {
            context.Writer.WriteLine();

            var md        = (ulong)method.MethodHandle.Value.ToInt64();
            var signature = context.Runtime.DacLibrary.SOSDacInterface.GetMethodDescName(md);

            context.Writer.WriteLine(signature ?? "Unknown Method");
        }
Ejemplo n.º 6
0
        private void WriteIgnoredOpenGeneric(JitWriteContext context, MethodBase method)
        {
            WriteSignatureFromReflection(context, method);
            var writer = context.Writer;

            writer.WriteLine("    ; Open generics cannot be JIT-compiled.");
            writer.WriteLine("    ; However you can use attribute SharpLab.Runtime.JitGeneric to specify argument types.");
            writer.WriteLine("    ; Example: [JitGeneric(typeof(int)), JitGeneric(typeof(string))] void M<T>() { ... }.");
        }
Ejemplo n.º 7
0
        private void DisassembleAndWriteGenericMethod(JitWriteContext context, MethodInfo method)
        {
            var hasAttribute = false;

            foreach (var attribute in method.GetCustomAttributes <JitGenericAttribute>())
            {
                hasAttribute = true;
                var genericInstance = method.MakeGenericMethod(attribute.ArgumentTypes);
                DisassembleAndWriteSimpleMethod(context, genericInstance);
            }
            if (!hasAttribute)
            {
                WriteIgnoredOpenGeneric(context, method);
            }
        }
Ejemplo n.º 8
0
        private void DisassembleAndWriteMethod(JitWriteContext context, MethodBase method)
        {
            if ((method.MethodImplementationFlags & MethodImplAttributes.Runtime) == MethodImplAttributes.Runtime)
            {
                WriteSignatureFromReflection(context, method);
                context.Writer.WriteLine("    ; Cannot produce JIT assembly for runtime-implemented method.");
                return;
            }

            if (method.DeclaringType?.IsGenericTypeDefinition ?? false)
            {
                WriteIgnoredOpenGeneric(context, method);
                return;
            }

            if (method.IsGenericMethodDefinition)
            {
                DisassembleAndWriteGenericMethod(context, (MethodInfo)method);
                return;
            }

            DisassembleAndWriteSimpleMethod(context, method);
        }
Ejemplo n.º 9
0
        private void DisassembleAndWriteSimpleMethod(JitWriteContext context, MethodBase method)
        {
            var handle = method.MethodHandle;

            RuntimeHelpers.PrepareMethod(handle);

            var clrMethod = context.Runtime.GetMethodByHandle((ulong)handle.Value.ToInt64());
            var regions   = FindNonEmptyHotColdInfo(clrMethod);

            if (clrMethod == null || regions == null)
            {
                context.Runtime.Flush();
                clrMethod = context.Runtime.GetMethodByHandle((ulong)handle.Value.ToInt64());
                regions   = FindNonEmptyHotColdInfo(clrMethod);
            }

            if (clrMethod == null || regions == null)
            {
                var address = (ulong)handle.GetFunctionPointer().ToInt64();
                clrMethod = context.Runtime.GetMethodByAddress(address);
                regions   = FindNonEmptyHotColdInfo(clrMethod);
            }

            var writer = context.Writer;

            if (clrMethod != null)
            {
                writer.WriteLine();
                writer.WriteLine(clrMethod.GetFullSignature());
            }
            else
            {
                WriteSignatureFromReflection(context, method);
            }

            if (regions == null)
            {
                if (method.IsGenericMethod || (method.DeclaringType?.IsGenericType ?? false))
                {
                    writer.WriteLine("    ; Failed to find HotColdInfo for generic method (reference types?).");
                    writer.WriteLine("    ; If you know a solution, please comment at https://github.com/ashmind/SharpLab/issues/99.");
                    return;
                }
                writer.WriteLine("    ; Failed to find HotColdRegions — please report at https://github.com/ashmind/SharpLab/issues.");
                return;
            }

            var methodAddress = regions.HotStart;
            var methodLength  = regions.HotSize;

            var reader  = new MemoryCodeReader(new IntPtr(unchecked ((long)methodAddress)), methodLength);
            var decoder = Decoder.Create(MapArchitectureToBitness(context.Runtime.DataTarget.Architecture), reader);

            var instructions = new InstructionList();

            decoder.IP = methodAddress;
            while (decoder.IP < (methodAddress + methodLength))
            {
                decoder.Decode(out instructions.AllocUninitializedElement());
            }

            var resolver  = new JitAsmSymbolResolver(context.Runtime, methodAddress, methodLength);
            var formatter = new IntelFormatter(FormatterOptions, resolver);
            var output    = new StringOutput();

            foreach (ref var instruction in instructions)
            {
                formatter.Format(instruction, output);

                writer.Write("    L");
                writer.Write((instruction.IP - methodAddress).ToString("x4"));
                writer.Write(": ");
                writer.WriteLine(output.ToStringAndReset());
            }
        }
Ejemplo n.º 10
0
        private void DisassembleAndWriteSimpleMethod(JitWriteContext context, MethodBase method)
        {
            var handle = method.MethodHandle;

            RuntimeHelpers.PrepareMethod(handle);

            var clrMethod = context.Runtime.GetMethodByHandle((ulong)handle.Value.ToInt64());
            var regions   = FindNonEmptyHotColdInfo(clrMethod);

            if (clrMethod == null || regions == null)
            {
                context.Runtime.Flush();
                clrMethod = context.Runtime.GetMethodByHandle((ulong)handle.Value.ToInt64());
                regions   = FindNonEmptyHotColdInfo(clrMethod);
            }

            if (clrMethod == null || regions == null)
            {
                var address = (ulong)handle.GetFunctionPointer().ToInt64();
                clrMethod = context.Runtime.GetMethodByAddress(address);
                regions   = FindNonEmptyHotColdInfo(clrMethod);
            }

            var writer = context.Writer;

            if (clrMethod != null)
            {
                writer.WriteLine();
                writer.WriteLine(clrMethod.GetFullSignature());
            }
            else
            {
                WriteSignatureFromReflection(context, method);
            }

            if (regions == null)
            {
                if (method.IsGenericMethod || (method.DeclaringType?.IsGenericType ?? false))
                {
                    writer.WriteLine("    ; Failed to find HotColdInfo for generic method (reference types?).");
                    writer.WriteLine("    ; If you know a solution, please comment at https://github.com/ashmind/SharpLab/issues/99.");
                    return;
                }
                writer.WriteLine("    ; Failed to find HotColdRegions — please report at https://github.com/ashmind/SharpLab/issues.");
                return;
            }

            var methodAddress = regions.HotStart;

            context.CurrentMethodAddress = methodAddress;

            var architecture = MapArchitecture(context.Runtime.DataTarget.Architecture);

            using (var disasm = new Disassembler(new IntPtr(unchecked ((long)methodAddress)), (int)regions.HotSize, architecture, methodAddress)) {
                var translator = context.Translator !;
                foreach (var instruction in disasm.Disassemble())
                {
                    writer.Write("    L");
                    writer.Write((instruction.Offset - methodAddress).ToString("x4"));
                    writer.Write(": ");
                    writer.WriteLine(translator.Translate(instruction));
                }
            }
        }