コード例 #1
0
        private static Compilation GetCompilation(Type type)
        {
            lock (decompiledTypes)
            {
                if (!decompiledTypes.TryGetValue(type, out Compilation compilation))
                {
                    EntityHandle handle       = MetadataTokenHelpers.TryAsEntityHandle(type.MetadataToken) ?? throw new InvalidOperationException();
                    string       assemblyPath = type.Assembly.Location;

                    if (!decompilers.TryGetValue(assemblyPath, out CSharpDecompiler decompiler))
                    {
                        decompiler = CreateDecompiler(assemblyPath);
                        decompilers.Add(assemblyPath, decompiler);
                    }

                    string sourceCode = decompiler.DecompileAsString(handle);

                    sourceCode = ClosureTypeDeclarationRegex.Replace(sourceCode, ShaderGenerator.DelegateTypeName);
                    sourceCode = LambdaMethodDeclarationRegex.Replace(sourceCode, $"internal void {ShaderGenerator.DelegateEntryPointName}");

                    SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(sourceCode, CSharpParseOptions.Default.WithLanguageVersion(Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp8));
                    compilation = globalCompilation.AddSyntaxTrees(syntaxTree);

                    decompiledTypes.Add(type, compilation);
                }

                return(compilation);
            }
        }
コード例 #2
0
        bool ScanMethodBody(ITypeDefinition analyzedEntity, IMethod method, MethodBodyBlock methodBody)
        {
            bool found          = false;
            var  blob           = methodBody.GetILReader();
            var  module         = (MetadataModule)method.ParentModule;
            var  genericContext = new Decompiler.TypeSystem.GenericContext();            // type parameters don't matter for this analyzer

            while (!found && blob.RemainingBytes > 0)
            {
                var opCode = blob.DecodeOpCode();
                if (!CanBeReference(opCode))
                {
                    blob.SkipOperand(opCode);
                    continue;
                }
                EntityHandle methodHandle = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32());
                if (!methodHandle.Kind.IsMemberKind())
                {
                    continue;
                }
                var ctor = module.ResolveMethod(methodHandle, genericContext);
                if (ctor == null || !ctor.IsConstructor)
                {
                    continue;
                }

                if (ctor.DeclaringTypeDefinition?.MetadataToken == analyzedEntity.MetadataToken &&
                    ctor.ParentModule.PEFile == analyzedEntity.ParentModule.PEFile)
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #3
0
        private static Compilation GetCompilation(Type type)
        {
            lock (decompiledTypes)
            {
                if (!decompiledTypes.TryGetValue(type, out Compilation compilation))
                {
                    EntityHandle handle       = MetadataTokenHelpers.TryAsEntityHandle(type.MetadataToken) ?? throw new InvalidOperationException();
                    string       assemblyPath = type.Assembly.Location;

                    if (!decompilers.TryGetValue(assemblyPath, out CSharpDecompiler decompiler))
                    {
                        decompiler = CreateDecompiler(assemblyPath);
                        decompilers.Add(assemblyPath, decompiler);
                    }

                    string sourceCode = decompiler.DecompileAsString(handle);

                    sourceCode = AnonymousMethodDeclaringTypeDeclarationRegex.Replace(sourceCode, ShaderGenerator.AnonymousMethodDeclaringTypeName);
                    sourceCode = AnonymousMethodDeclarationRegex.Replace(sourceCode, $"internal void {ShaderGenerator.AnonymousMethodEntryPointName}");

                    SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(sourceCode);

                    IList <MetadataReference> metadataReferences = GetMetadataReferences(type.Assembly, type.Assembly.GetName(), typeof(object).Assembly.GetName());

                    compilation = CSharpCompilation.Create("ShaderAssembly", new[] { syntaxTree }, metadataReferences);

                    decompiledTypes.Add(type, compilation);
                }

                return(compilation);
            }
        }
コード例 #4
0
 public MetadataTokenSearchStrategy(Language language, ApiVisibility apiVisibility, IProducerConsumerCollection <SearchResult> resultQueue, params string[] terms)
     : base(language, apiVisibility, resultQueue, terms)
 {
     if (terms.Length == 1)
     {
         int.TryParse(terms[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var token);
         searchTermToken = MetadataTokenHelpers.EntityHandleOrNil(token);
     }
 }
コード例 #5
0
 public MetadataTokenSearchStrategy(Language language, Action <SearchResult> addResult, params string[] terms)
     : base(language, addResult, terms)
 {
     if (terms.Length == 1)
     {
         int.TryParse(terms[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var token);
         searchTermToken = MetadataTokenHelpers.EntityHandleOrNil(token);
     }
 }
コード例 #6
0
        bool ScanMethodBody(IField analyzedField, IMethod method, MethodBodyBlock methodBody)
        {
            if (methodBody == null)
            {
                return(false);
            }

            var mainModule     = (MetadataModule)method.ParentModule;
            var blob           = methodBody.GetILReader();
            var genericContext = new Decompiler.TypeSystem.GenericContext();             // type parameters don't matter for this analyzer

            while (blob.RemainingBytes > 0)
            {
                ILOpCode opCode;
                try
                {
                    opCode = blob.DecodeOpCode();
                    if (!CanBeReference(opCode))
                    {
                        blob.SkipOperand(opCode);
                        continue;
                    }
                }
                catch (BadImageFormatException)
                {
                    return(false);
                }
                EntityHandle fieldHandle = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32());
                if (!fieldHandle.Kind.IsMemberKind())
                {
                    continue;
                }
                IField field;
                try
                {
                    field = mainModule.ResolveEntity(fieldHandle, genericContext) as IField;
                }
                catch (BadImageFormatException)
                {
                    continue;
                }
                if (field == null)
                {
                    continue;
                }

                if (field.MetadataToken == analyzedField.MetadataToken &&
                    field.ParentModule.PEFile == analyzedField.ParentModule.PEFile)
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #7
0
        /// <summary>
        /// Decompiles a target method and returns its <see cref="SyntaxTree"/> and <see cref="SemanticModel"/> info
        /// </summary>
        /// <param name="methodInfo">The input <see cref="MethodInfo"/> to inspect</param>
        /// <param name="rootNode">The root node for the syntax tree of the input method</param>
        /// <param name="semanticModel">The semantic model for the input method</param>
        public void GetSyntaxTree(MethodInfo methodInfo, out MethodDeclarationSyntax rootNode, out SemanticModel semanticModel)
        {
            lock (Lock)
            {
                // Get the handle of the containing type method
                string       assemblyPath = methodInfo.DeclaringType?.Assembly.Location ?? throw new InvalidOperationException();
                EntityHandle typeHandle   = MetadataTokenHelpers.TryAsEntityHandle(methodInfo.DeclaringType.MetadataToken) ?? throw new InvalidOperationException();

                // Get or create a decompiler for the target assembly, and decompile the type
                if (!Decompilers.TryGetValue(assemblyPath, out CSharpDecompiler decompiler))
                {
                    decompiler = CreateDecompiler(assemblyPath);
                    Decompilers.Add(assemblyPath, decompiler);
                }

                // Decompile the method source and fix the method declaration for local methods converted to lambdas
                string
                    sourceCode      = decompiler.DecompileAsString(typeHandle),
                    typeFixedCode   = ClosureTypeDeclarationRegex.Replace(sourceCode, "Shader"),
                    methodFixedCode = LambdaMethodDeclarationRegex.Replace(typeFixedCode, m => $"// {m.Value}{Environment.NewLine}    internal void Main");

                // Workaround for some local methods not being decompiled correctly
                if (!methodFixedCode.Contains("internal void Main"))
                {
                    EntityHandle methodHandle = MetadataTokenHelpers.TryAsEntityHandle(methodInfo.MetadataToken) ?? throw new InvalidOperationException();
                    string
                        methodOnlySourceCode         = decompiler.DecompileAsString(methodHandle),
                        methodOnlyFixedSourceCode    = LambdaMethodDeclarationRegex.Replace(methodOnlySourceCode, m => $"// {m.Value}{Environment.NewLine}    internal void Main"),
                        methodOnlyIndentedSourceCode = $"    {methodOnlyFixedSourceCode.Replace(Environment.NewLine, $"{Environment.NewLine}    ")}";

                    int lastClosedBracketsIndex = methodFixedCode.LastIndexOf('}');
                    methodFixedCode = methodFixedCode.Insert(lastClosedBracketsIndex, methodOnlyIndentedSourceCode);
                }

                // Unwrap the nested fields
                string unwrappedSourceCode = UnwrapSyntaxTree(methodFixedCode);

                // Remove the in keyword from the source
                string inFixedSourceCode = Regex.Replace(unwrappedSourceCode, @"(?<!\w)in ", string.Empty);

                // Tweak the out declarations
                string outFixedSourceCode = RefactorInlineOutDeclarations(inFixedSourceCode, methodInfo.Name);

                // Load the type syntax tree
                SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(outFixedSourceCode);

                // Get the root node to return
                rootNode = syntaxTree.GetRoot().DescendantNodes().OfType <MethodDeclarationSyntax>().First(node => node.GetLeadingTrivia().ToFullString().Contains(methodInfo.Name));

                // Update the incremental compilation and retrieve the syntax tree for the method
                _Compilation  = _Compilation.AddSyntaxTrees(syntaxTree);
                semanticModel = _Compilation.GetSemanticModel(syntaxTree);
            }
        }
コード例 #8
0
        public MetadataTokenSearchStrategy(ILanguage language, ApiVisibility apiVisibility, SearchRequest request,
                                           IProducerConsumerCollection <SearchResult> resultQueue)
            : base(language, apiVisibility, request, resultQueue)
        {
            var terms = request.Keywords;

            if (terms.Length == 1)
            {
                int.TryParse(terms[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var token);
                searchTermToken = MetadataTokenHelpers.EntityHandleOrNil(token);
            }
        }
コード例 #9
0
        public DecompilationResult Decompile <TRes>(Func <ICursor, RedisValue[], RedisKey[], TRes> action)
            where TRes : RedResult
        {
            var token  = action.Method.MetadataToken;
            var method = MetadataTokenHelpers.TryAsEntityHandle(token);

            var ast = _decompiler.Decompile(new List <EntityHandle>()
            {
                method.Value
            });

            return(ExtractTreeAndMetadata(ast));
        }
コード例 #10
0
        private string DecompileMethodOrDeclaringType(MethodInfo methodInfo, bool methodOnly = false)
        {
            // Get the handle of the containing type method
            string       assemblyPath  = methodInfo.DeclaringType?.Assembly.Location ?? throw new InvalidOperationException();
            int          metadataToken = methodInfo.IsStatic || methodOnly ? methodInfo.MetadataToken : methodInfo.DeclaringType.MetadataToken;
            EntityHandle typeHandle    = MetadataTokenHelpers.TryAsEntityHandle(metadataToken) ?? throw new InvalidOperationException();

            // Get or create a decompiler for the target assembly, and decompile the type
            if (!Decompilers.TryGetValue(assemblyPath, out CSharpDecompiler decompiler))
            {
                decompiler = CreateDecompiler(assemblyPath);
                Decompilers.Add(assemblyPath, decompiler);
            }

            return(decompiler.DecompileAsString(typeHandle));
        }
コード例 #11
0
        public SyntaxTree Read(Delegate @delegate)
        {
            Contract.Assert(@delegate?.Method?.DeclaringType != null);

            var asm = @delegate.Method.DeclaringType.Assembly;

            _assemblyProvider.Prepare(asm);
            var decompiler = new CSharpDecompiler(asm.Location, _assemblyProvider, new DecompilerSettings()
            {
                ExtensionMethods = false,
                NamedArguments   = false
            });
            var token  = @delegate.Method.MetadataToken;
            var method = MetadataTokenHelpers.TryAsEntityHandle(token);
            var ast    = decompiler.Decompile(new List <EntityHandle>()
            {
                method.Value
            });

            return(ast);
        }
コード例 #12
0
ファイル: CSharpLanguage.cs プロジェクト: zarumaru/ILSpy
        public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)
        {
            var module = assembly.GetPEFileOrNull();

            if (module == null)
            {
                return(null);
            }
            if (options.FullDecompilation && options.SaveAsProjectDirectory != null)
            {
                if (!WholeProjectDecompiler.CanUseSdkStyleProjectFormat(module))
                {
                    options.DecompilerSettings.UseSdkStyleProjectFormat = false;
                }
                var decompiler = new ILSpyWholeProjectDecompiler(assembly, options);
                return(decompiler.DecompileProject(module, options.SaveAsProjectDirectory, new TextOutputWriter(output), options.CancellationToken));
            }
            else
            {
                AddReferenceAssemblyWarningMessage(module, output);
                AddReferenceWarningMessage(module, output);
                output.WriteLine();
                base.DecompileAssembly(assembly, output, options);

                // don't automatically load additional assemblies when an assembly node is selected in the tree view
                IAssemblyResolver assemblyResolver = assembly.GetAssemblyResolver(loadOnDemand: options.FullDecompilation);
                var typeSystem = new DecompilerTypeSystem(module, assemblyResolver, options.DecompilerSettings);
                var globalType = typeSystem.MainModule.TypeDefinitions.FirstOrDefault();
                if (globalType != null)
                {
                    output.Write("// Global type: ");
                    output.WriteReference(globalType, globalType.FullName);
                    output.WriteLine();
                }
                var metadata         = module.Metadata;
                var corHeader        = module.Reader.PEHeaders.CorHeader;
                var entrypointHandle = MetadataTokenHelpers.EntityHandleOrNil(corHeader.EntryPointTokenOrRelativeVirtualAddress);
                if (!entrypointHandle.IsNil && entrypointHandle.Kind == HandleKind.MethodDefinition)
                {
                    var entrypoint = typeSystem.MainModule.ResolveMethod(entrypointHandle, new Decompiler.TypeSystem.GenericContext());
                    if (entrypoint != null)
                    {
                        output.Write("// Entry point: ");
                        output.WriteReference(entrypoint, entrypoint.DeclaringType.FullName + "." + entrypoint.Name);
                        output.WriteLine();
                    }
                }
                output.WriteLine("// Architecture: " + GetPlatformDisplayName(module));
                if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.ILOnly) == 0)
                {
                    output.WriteLine("// This assembly contains unmanaged code.");
                }
                string runtimeName = GetRuntimeDisplayName(module);
                if (runtimeName != null)
                {
                    output.WriteLine("// Runtime: " + runtimeName);
                }
                if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.StrongNameSigned) != 0)
                {
                    output.WriteLine("// This assembly is signed with a strong name key.");
                }
                if (module.Reader.ReadDebugDirectory().Any(d => d.Type == DebugDirectoryEntryType.Reproducible))
                {
                    output.WriteLine("// This assembly was compiled using the /deterministic option.");
                }
                if (metadata.IsAssembly)
                {
                    var asm = metadata.GetAssemblyDefinition();
                    if (asm.HashAlgorithm != AssemblyHashAlgorithm.None)
                    {
                        output.WriteLine("// Hash algorithm: " + asm.HashAlgorithm.ToString().ToUpper());
                    }
                    if (!asm.PublicKey.IsNil)
                    {
                        output.Write("// Public key: ");
                        var reader = metadata.GetBlobReader(asm.PublicKey);
                        while (reader.RemainingBytes > 0)
                        {
                            output.Write(reader.ReadByte().ToString("x2"));
                        }
                        output.WriteLine();
                    }
                }
                var debugInfo = assembly.GetDebugInfoOrNull();
                if (debugInfo != null)
                {
                    output.WriteLine("// Debug info: " + debugInfo.Description);
                }
                output.WriteLine();

                CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, options.DecompilerSettings);
                decompiler.CancellationToken = options.CancellationToken;
                if (options.EscapeInvalidIdentifiers)
                {
                    decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers());
                }
                SyntaxTree st;
                if (options.FullDecompilation)
                {
                    st = decompiler.DecompileWholeModuleAsSingleFile();
                }
                else
                {
                    st = decompiler.DecompileModuleAndAssemblyAttributes();
                }
                WriteCode(output, options.DecompilerSettings, st, decompiler.TypeSystem);
                return(null);
            }
        }
コード例 #13
0
        void ScanMethodBody(TypeDefinitionUsedVisitor visitor, IMethod method, MethodBodyBlock methodBody, AnalyzerContext context)
        {
            if (methodBody == null)
            {
                return;
            }

            var module         = (MetadataModule)method.ParentModule;
            var genericContext = new Decompiler.TypeSystem.GenericContext();             // type parameters don't matter for this analyzer

            if (!methodBody.LocalSignature.IsNil)
            {
                ImmutableArray <IType> localSignature;
                try
                {
                    localSignature = module.DecodeLocalSignature(methodBody.LocalSignature, genericContext);
                }
                catch (BadImageFormatException)
                {
                    // Issue #2197: ignore invalid local signatures
                    localSignature = ImmutableArray <IType> .Empty;
                }
                foreach (var type in localSignature)
                {
                    type.AcceptVisitor(visitor);

                    if (visitor.Found)
                    {
                        return;
                    }
                }
            }

            var blob = methodBody.GetILReader();

            while (!visitor.Found && blob.RemainingBytes > 0)
            {
                var opCode = blob.DecodeOpCode();
                switch (opCode.GetOperandType())
                {
                case OperandType.Field:
                case OperandType.Method:
                case OperandType.Sig:
                case OperandType.Tok:
                case OperandType.Type:
                    var member = MetadataTokenHelpers.EntityHandleOrNil(blob.ReadInt32());
                    if (member.IsNil)
                    {
                        continue;
                    }
                    switch (member.Kind)
                    {
                    case HandleKind.TypeReference:
                    case HandleKind.TypeSpecification:
                    case HandleKind.TypeDefinition:
                        module.ResolveType(member, genericContext).AcceptVisitor(visitor);
                        if (visitor.Found)
                        {
                            return;
                        }
                        break;

                    case HandleKind.FieldDefinition:
                    case HandleKind.MethodDefinition:
                    case HandleKind.MemberReference:
                    case HandleKind.MethodSpecification:
                        VisitMember(visitor, module.ResolveEntity(member, genericContext) as IMember, context);

                        if (visitor.Found)
                        {
                            return;
                        }
                        break;

                    case HandleKind.StandaloneSignature:
                        var(_, fpt) = module.DecodeMethodSignature((StandaloneSignatureHandle)member, genericContext);
                        fpt.AcceptVisitor(visitor);

                        if (visitor.Found)
                        {
                            return;
                        }
                        break;

                    default:
                        break;
                    }
                    break;

                default:
                    blob.SkipOperand(opCode);
                    break;
                }
            }
        }
コード例 #14
0
        void CollectNamespacesFromMethodBody(MethodBodyBlock method, MetadataModule module)
        {
            var metadata     = module.metadata;
            var instructions = method.GetILReader();

            if (!method.LocalSignature.IsNil)
            {
                ImmutableArray <IType> localSignature;
                try {
                    localSignature = module.DecodeLocalSignature(method.LocalSignature, genericContext);
                } catch (BadImageFormatException) {
                    // Issue #1211: ignore invalid local signatures
                    localSignature = ImmutableArray <IType> .Empty;
                }
                foreach (var type in localSignature)
                {
                    CollectNamespacesForTypeReference(type);
                }
            }

            foreach (var region in method.ExceptionRegions)
            {
                if (region.CatchType.IsNil)
                {
                    continue;
                }
                IType ty;
                try {
                    ty = module.ResolveType(region.CatchType, genericContext);
                } catch (BadImageFormatException) {
                    continue;
                }
                CollectNamespacesForTypeReference(ty);
            }

            while (instructions.RemainingBytes > 0)
            {
                ILOpCode opCode;
                try {
                    opCode = instructions.DecodeOpCode();
                } catch (BadImageFormatException) {
                    return;
                }
                switch (opCode.GetOperandType())
                {
                case OperandType.Field:
                case OperandType.Method:
                case OperandType.Sig:
                case OperandType.Tok:
                case OperandType.Type:
                    var handle = MetadataTokenHelpers.EntityHandleOrNil(instructions.ReadInt32());
                    if (handle.IsNil)
                    {
                        break;
                    }
                    switch (handle.Kind)
                    {
                    case HandleKind.TypeDefinition:
                    case HandleKind.TypeReference:
                    case HandleKind.TypeSpecification:
                        IType type;
                        try {
                            type = module.ResolveType(handle, genericContext);
                        } catch (BadImageFormatException) {
                            break;
                        }
                        CollectNamespacesForTypeReference(type);
                        break;

                    case HandleKind.FieldDefinition:
                    case HandleKind.MethodDefinition:
                    case HandleKind.MethodSpecification:
                    case HandleKind.MemberReference:
                        IMember member;
                        try {
                            member = module.ResolveEntity(handle, genericContext) as IMember;
                        } catch (BadImageFormatException) {
                            break;
                        }
                        CollectNamespacesForMemberReference(member);
                        break;

                    case HandleKind.StandaloneSignature:
                        StandaloneSignature sig;
                        try {
                            sig = metadata.GetStandaloneSignature((StandaloneSignatureHandle)handle);
                        } catch (BadImageFormatException) {
                            break;
                        }
                        if (sig.GetKind() == StandaloneSignatureKind.Method)
                        {
                            MethodSignature <IType> methodSig;
                            try {
                                methodSig = module.DecodeMethodSignature((StandaloneSignatureHandle)handle, genericContext);
                            } catch (BadImageFormatException) {
                                break;
                            }
                            CollectNamespacesForTypeReference(methodSig.ReturnType);
                            foreach (var paramType in methodSig.ParameterTypes)
                            {
                                CollectNamespacesForTypeReference(paramType);
                            }
                        }
                        break;
                    }
                    break;

                default:
                    try {
                        instructions.SkipOperand(opCode);
                    } catch (BadImageFormatException) {
                        return;
                    }
                    break;
                }
            }
        }
コード例 #15
0
        protected virtual void WriteInstruction(ITextOutput output, MetadataReader metadata, MethodDefinitionHandle methodDefinition, ref BlobReader blob)
        {
            int offset = blob.Offset;

            if (ShowSequencePoints && nextSequencePointIndex < sequencePoints?.Count)
            {
                var sp = sequencePoints[nextSequencePointIndex];
                if (sp.Offset <= offset)
                {
                    output.Write("// sequence point: ");
                    if (sp.Offset != offset)
                    {
                        output.Write("!! at " + DisassemblerHelpers.OffsetToString(sp.Offset) + " !!");
                    }
                    if (sp.IsHidden)
                    {
                        output.WriteLine("hidden");
                    }
                    else
                    {
                        output.WriteLine($"(line {sp.StartLine}, col {sp.StartColumn}) to (line {sp.EndLine}, col {sp.EndColumn}) in {sp.DocumentUrl}");
                    }
                    nextSequencePointIndex++;
                }
            }
            ILOpCode opCode = ILParser.DecodeOpCode(ref blob);

            output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset), offset, isDefinition: true);
            output.Write(": ");
            if (opCode.IsDefined())
            {
                output.WriteReference(new OpCodeInfo(opCode, opCode.GetDisplayName()));
                switch (opCode.GetOperandType())
                {
                case OperandType.BrTarget:
                case OperandType.ShortBrTarget:
                    output.Write(' ');
                    int targetOffset = ILParser.DecodeBranchTarget(ref blob, opCode);
                    output.WriteLocalReference($"IL_{targetOffset:x4}", targetOffset);
                    break;

                case OperandType.Field:
                case OperandType.Method:
                case OperandType.Sig:
                case OperandType.Type:
                    output.Write(' ');
                    int          metadataToken = blob.ReadInt32();
                    EntityHandle?handle        = MetadataTokenHelpers.TryAsEntityHandle(metadataToken);
                    try {
                        handle?.WriteTo(module, output, genericContext);
                    } catch (BadImageFormatException) {
                        handle = null;
                    }
                    WriteMetadataToken(handle, metadataToken, spaceBefore: true);
                    break;

                case OperandType.Tok:
                    output.Write(' ');
                    metadataToken = blob.ReadInt32();
                    handle        = MetadataTokenHelpers.TryAsEntityHandle(metadataToken);
                    switch (handle?.Kind)
                    {
                    case HandleKind.MemberReference:
                        switch (metadata.GetMemberReference((MemberReferenceHandle)handle).GetKind())
                        {
                        case MemberReferenceKind.Method:
                            output.Write("method ");
                            break;

                        case MemberReferenceKind.Field:
                            output.Write("field ");
                            break;
                        }
                        break;

                    case HandleKind.FieldDefinition:
                        output.Write("field ");
                        break;

                    case HandleKind.MethodDefinition:
                        output.Write("method ");
                        break;
                    }
                    try {
                        handle?.WriteTo(module, output, genericContext);
                    } catch (BadImageFormatException) {
                        handle = null;
                    }
                    WriteMetadataToken(handle, metadataToken, spaceBefore: true);
                    break;

                case OperandType.ShortI:
                    output.Write(' ');
                    DisassemblerHelpers.WriteOperand(output, blob.ReadSByte());
                    break;

                case OperandType.I:
                    output.Write(' ');
                    DisassemblerHelpers.WriteOperand(output, blob.ReadInt32());
                    break;

                case OperandType.I8:
                    output.Write(' ');
                    DisassemblerHelpers.WriteOperand(output, blob.ReadInt64());
                    break;

                case OperandType.ShortR:
                    output.Write(' ');
                    DisassemblerHelpers.WriteOperand(output, blob.ReadSingle());
                    break;

                case OperandType.R:
                    output.Write(' ');
                    DisassemblerHelpers.WriteOperand(output, blob.ReadDouble());
                    break;

                case OperandType.String:
                    metadataToken = blob.ReadInt32();
                    output.Write(' ');
                    UserStringHandle?userString;
                    string           text;
                    try {
                        userString = MetadataTokens.UserStringHandle(metadataToken);
                        text       = metadata.GetUserString(userString.Value);
                    } catch (BadImageFormatException) {
                        userString = null;
                        text       = null;
                    }
                    if (userString != null)
                    {
                        DisassemblerHelpers.WriteOperand(output, text);
                    }
                    WriteMetadataToken(userString, metadataToken, spaceBefore: true);
                    break;

                case OperandType.Switch:
                    int[] targets = ILParser.DecodeSwitchTargets(ref blob);
                    output.Write(" (");
                    for (int i = 0; i < targets.Length; i++)
                    {
                        if (i > 0)
                        {
                            output.Write(", ");
                        }
                        output.WriteLocalReference($"IL_{targets[i]:x4}", targets[i]);
                    }
                    output.Write(")");
                    break;

                case OperandType.Variable:
                    output.Write(' ');
                    int index = blob.ReadUInt16();
                    if (opCode == ILOpCode.Ldloc || opCode == ILOpCode.Ldloca || opCode == ILOpCode.Stloc)
                    {
                        DisassemblerHelpers.WriteVariableReference(output, metadata, methodDefinition, index);
                    }
                    else
                    {
                        DisassemblerHelpers.WriteParameterReference(output, metadata, methodDefinition, index);
                    }
                    break;

                case OperandType.ShortVariable:
                    output.Write(' ');
                    index = blob.ReadByte();
                    if (opCode == ILOpCode.Ldloc_s || opCode == ILOpCode.Ldloca_s || opCode == ILOpCode.Stloc_s)
                    {
                        DisassemblerHelpers.WriteVariableReference(output, metadata, methodDefinition, index);
                    }
                    else
                    {
                        DisassemblerHelpers.WriteParameterReference(output, metadata, methodDefinition, index);
                    }
                    break;
                }
            }
            else
            {
                ushort opCodeValue = (ushort)opCode;
                if (opCodeValue > 0xFF)
                {
                    // split 16-bit value into two emitbyte directives
                    output.WriteLine($".emitbyte 0x{(byte)(opCodeValue >> 8):x}");
                    // add label
                    output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset + 1), offset + 1, isDefinition: true);
                    output.Write(": ");
                    output.Write($".emitbyte 0x{(byte)(opCodeValue & 0xFF):x}");
                }
                else
                {
                    output.Write($".emitbyte 0x{(byte)opCodeValue:x}");
                }
            }
            output.WriteLine();
        }
コード例 #16
0
ファイル: CSharpLanguage.cs プロジェクト: zyonet/ILSpy
        public override void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)
        {
            var module = assembly.GetPEFileOrNull();

            if (options.FullDecompilation && options.SaveAsProjectDirectory != null)
            {
                var decompiler = new ILSpyWholeProjectDecompiler(assembly, options);
                decompiler.DecompileProject(module, options.SaveAsProjectDirectory, new TextOutputWriter(output), options.CancellationToken);
            }
            else
            {
                AddReferenceAssemblyWarningMessage(module, output);
                AddReferenceWarningMessage(module, output);
                output.WriteLine();
                base.DecompileAssembly(assembly, output, options);

                // don't automatically load additional assemblies when an assembly node is selected in the tree view
                using (options.FullDecompilation ? null : LoadedAssembly.DisableAssemblyLoad()) {
                    IAssemblyResolver assemblyResolver = assembly.GetAssemblyResolver();
                    var typeSystem = new DecompilerTypeSystem(module, assemblyResolver, options.DecompilerSettings);
                    var globalType = typeSystem.MainModule.TypeDefinitions.FirstOrDefault();
                    if (globalType != null)
                    {
                        output.Write("// Global type: ");
                        output.WriteReference(globalType, globalType.FullName);
                        output.WriteLine();
                    }
                    var metadata         = module.Metadata;
                    var corHeader        = module.Reader.PEHeaders.CorHeader;
                    var entrypointHandle = MetadataTokenHelpers.EntityHandleOrNil(corHeader.EntryPointTokenOrRelativeVirtualAddress);
                    if (!entrypointHandle.IsNil && entrypointHandle.Kind == HandleKind.MethodDefinition)
                    {
                        var entrypoint = typeSystem.MainModule.ResolveMethod(entrypointHandle, new Decompiler.TypeSystem.GenericContext());
                        if (entrypoint != null)
                        {
                            output.Write("// Entry point: ");
                            output.WriteReference(entrypoint, entrypoint.DeclaringType.FullName + "." + entrypoint.Name);
                            output.WriteLine();
                        }
                    }
                    output.WriteLine("// Architecture: " + GetPlatformDisplayName(module));
                    if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.ILOnly) == 0)
                    {
                        output.WriteLine("// This assembly contains unmanaged code.");
                    }
                    string runtimeName = GetRuntimeDisplayName(module);
                    if (runtimeName != null)
                    {
                        output.WriteLine("// Runtime: " + runtimeName);
                    }
                    var debugInfo = assembly.GetDebugInfoOrNull();
                    if (debugInfo != null)
                    {
                        output.WriteLine("// Debug info: " + debugInfo.Description);
                    }
                    output.WriteLine();

                    CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, options.DecompilerSettings);
                    decompiler.CancellationToken = options.CancellationToken;
                    SyntaxTree st;
                    if (options.FullDecompilation)
                    {
                        st = decompiler.DecompileWholeModuleAsSingleFile();
                    }
                    else
                    {
                        st = decompiler.DecompileModuleAndAssemblyAttributes();
                    }
                    WriteCode(output, options.DecompilerSettings, st, decompiler.TypeSystem);
                }
            }
        }
コード例 #17
0
        private string GetAssemblyCode(string assemblyPath, CSharpDecompiler decompiler)
        {
            using (var output = new StringWriter())
            {
                WriteCommentLine(output, assemblyPath);
                var module   = decompiler.TypeSystem.MainModule.PEFile;
                var metadata = module.Metadata;
                if (metadata.IsAssembly)
                {
                    var name = metadata.GetAssemblyDefinition();
                    if ((name.Flags & System.Reflection.AssemblyFlags.WindowsRuntime) != 0)
                    {
                        WriteCommentLine(output, metadata.GetString(name.Name) + " [WinRT]");
                    }
                    else
                    {
                        WriteCommentLine(output, metadata.GetFullAssemblyName());
                    }
                }
                else
                {
                    WriteCommentLine(output, module.Name);
                }

                var mainModule = decompiler.TypeSystem.MainModule;
                var globalType = mainModule.TypeDefinitions.FirstOrDefault();
                if (globalType != null)
                {
                    output.Write("// Global type: ");
                    output.Write(globalType.FullName);
                    output.WriteLine();
                }
                var corHeader        = module.Reader.PEHeaders.CorHeader;
                var entrypointHandle = MetadataTokenHelpers.EntityHandleOrNil(corHeader.EntryPointTokenOrRelativeVirtualAddress);
                if (!entrypointHandle.IsNil && entrypointHandle.Kind == HandleKind.MethodDefinition)
                {
                    var entrypoint = mainModule.ResolveMethod(entrypointHandle, new ICSharpCode.Decompiler.TypeSystem.GenericContext());
                    if (entrypoint != null)
                    {
                        output.Write("// Entry point: ");
                        output.Write(entrypoint.DeclaringType.FullName + "." + entrypoint.Name);
                        output.WriteLine();
                    }
                }
                output.WriteLine("// Architecture: " + module.GetPlatformDisplayName());
                if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.ILOnly) == 0)
                {
                    output.WriteLine("// This assembly contains unmanaged code.");
                }
                string runtimeName = module.GetRuntimeDisplayName();
                if (runtimeName != null)
                {
                    output.WriteLine("// Runtime: " + runtimeName);
                }
                output.WriteLine();

                output.Write(decompiler.DecompileModuleAndAssemblyAttributesToString());

                output.WriteLine();

                return(output.ToString());
            }
        }
コード例 #18
0
        /// <summary>
        /// Saves this object as an Inno Setup formatted script
        /// </summary>
        /// <param name="textWriter"><see cref="TextWriter"/> with which script is written</param>
        public virtual void Save(TextWriter textWriter)
        {
            var thisType    = typeof(Installation);
            var derivedType = GetType();

            var entriesBuilder = new ParameterizedEntriesBuilder(textWriter);

            // list of methods referenced by constants
            var constReferencedMethods = new HashSet <InstallationMethod>();

            _constantReferencedMethod = methodInfo => constReferencedMethods.Add(new InstallationMethod(methodInfo));

            try
            {
                using (new Section(textWriter, "Setup"))
                {
                    var setupProperties = thisType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                          .Where(p => p.GetCustomAttribute <SetupDirectiveAttribute>() != null)
                                          .Select(p =>
                                                  new
                    {
                        Alias         = p.GetCustomAttribute <AliasAttribute>()?.Name,
                        Property      = derivedType.GetProperty(p.Name),
                        TypeConverter = p.GetCustomAttribute <TypeConverterAttribute>()
                    })
                                          .Where(p => p.Property.DeclaringType != thisType)
                                          .Select(p =>
                                                  new
                    {
                        p.Property,
                        Name = p.Alias ?? p.Property.Name,
                        p.TypeConverter
                    })
                                          .OrderBy(p => p.Name)
                                          .ToList();

                    WriteDirectives(textWriter, setupProperties.Select(p => (p.Name, p.Property, p.TypeConverter)));
                }

                var langOptionsProperties = thisType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                            .Where(p => p.GetCustomAttribute <LanguageDirectiveAttribute>() != null)
                                            .Select(p =>
                                                    new
                {
                    Alias         = p.GetCustomAttribute <AliasAttribute>()?.Name,
                    Property      = derivedType.GetProperty(p.Name),
                    TypeConverter = p.GetCustomAttribute <TypeConverterAttribute>()
                })
                                            .Where(p => derivedType.GetProperty(p.Property.Name).DeclaringType != thisType)
                                            .Select(p =>
                                                    new
                {
                    p.Property,
                    Name = p.Alias ?? p.Property.Name,
                    p.TypeConverter
                })
                                            .OrderBy(p => p.Name)
                                            .ToList();

                if (langOptionsProperties.Count > 0)
                {
                    using (new Section(textWriter, "LanguageOptions"))
                    {
                        WriteDirectives(textWriter, langOptionsProperties.Select(p => (p.Name, p.Property, p.TypeConverter)));
                    }
                }

                ParameterizedEntriesBuilderHandler?.Invoke(entriesBuilder);
            }
            finally
            {
                _constantReferencedMethod = null;
            }

            using (new Section(textWriter, "Code"))
            {
                textWriter.WriteLine("const");
                textWriter.WriteLine("   MB_ICONWARNING = $30;");
                textWriter.WriteLine("   MB_ICONINFORMATION = $40;");
                textWriter.WriteLine("   MB_ICONQUESTION = $20;");
                textWriter.WriteLine("   MB_ICONERROR = $10;");
                textWriter.WriteBlankLine();

                var decompilers = new Dictionary <string, CSharpDecompiler>();

                SyntaxTree GetSyntaxTree(string assemblyLocation, int metadataToken)
                {
                    var settings = new DecompilerSettings
                    {
                        UseDebugSymbols   = true,
                        NamedArguments    = false,
                        SwitchExpressions = false,
                        OutVariables      = false,
                        SeparateLocalVariableDeclarations = true,
                        LoadInMemory         = true,
                        ShowXmlDocumentation = false,
                        Discards             = false
                    };

                    var assemblyName = assemblyLocation;

                    var peFile = new PEFile(
                        assemblyName,
                        new FileStream(assemblyName, FileMode.Open, FileAccess.Read),
                        streamOptions: settings.LoadInMemory ? PEStreamOptions.PrefetchEntireImage : PEStreamOptions.Default,
                        metadataOptions: settings.ApplyWindowsRuntimeProjections ? MetadataReaderOptions.ApplyWindowsRuntimeProjections : MetadataReaderOptions.None
                        );

                    var resolver = new UniversalAssemblyResolver(assemblyName, settings.ThrowOnAssemblyResolveErrors,
                                                                 peFile.DetectTargetFrameworkId(),
                                                                 settings.LoadInMemory ? PEStreamOptions.PrefetchMetadata : PEStreamOptions.Default,
                                                                 settings.ApplyWindowsRuntimeProjections ? MetadataReaderOptions.ApplyWindowsRuntimeProjections : MetadataReaderOptions.None);

                    var typeSystem = new DecompilerTypeSystem(peFile, resolver);

                    var decompiler = decompilers.Set(
                        assemblyName,
                        new CSharpDecompiler(typeSystem, settings)
                    {
                        DebugInfoProvider = new MetadataDebugInfoProvider(assemblyName)
                    }
                        );
                    var method = MetadataTokenHelpers.TryAsEntityHandle(metadataToken);

                    return(decompiler.Decompile(new List <EntityHandle>()
                    {
                        method.Value
                    }));
                }

                var eventHandlers = thisType.GetMethods(BindingFlags.Instance | BindingFlags.Public).Where(m => m.GetCustomAttribute <EventHandlerAttribute>() != null)
                                    .Select(m => new
                {
                    DerivedMethod   = derivedType.GetMethod(m.Name, BindingFlags.Public | BindingFlags.Instance),
                    InterfaceMethod = m
                })
                                    .Select(m =>
                {
                    if (m.DerivedMethod.DeclaringType != typeof(Installation))
                    {
                        return(new InstallationMethod(m.DerivedMethod, m.InterfaceMethod));
                    }

                    return(null);
                })
                                    .Where(m => m != null)
                                    .ToList();

                var allMethods = entriesBuilder.Methods
                                 .Concat(eventHandlers)
                                 .Concat(constReferencedMethods)
                                 .ToList();

                var aliasFactory = new Func <string, string>(name =>
                {
                    var method = allMethods.Single(m => m.Name == name);
                    return(method.GetAttribute <AliasAttribute>()?.Name);
                });

                bool encounteredInitializeSetup     = false;
                bool encounteredInitializeUninstall = false;
                var  referencedGlobalVariables      = new Dictionary <FieldInfo, string>();
                var  definedMethods  = new HashSet <string>();
                var  declaredMembers = new HashSet <MemberInfo>();
                var  namespaces      = new HashSet <string>();
                using var typeDefinitions = new Snippet();

                var type = derivedType;
                while (type != null && type != typeof(Installation))
                {
                    namespaces.Add(type.Namespace);
                    type = type.BaseType;
                }

                using (var snippet = new Snippet())
                {
                    foreach (var installationMethod in allMethods)
                    {
                        switch (installationMethod.Name)
                        {
                        case nameof(Installation.InitializeSetup):
                            encounteredInitializeSetup = true;
                            break;

                        case nameof(Installation.InitializeUninstall):
                            encounteredInitializeUninstall = true;
                            break;
                        }

                        if (!definedMethods.Add(installationMethod.UniqueId))
                        {
                            // already defined, probably via recursion when one method called another
                            continue;
                        }

                        var ast = GetSyntaxTree(installationMethod.AssemblyLocation, installationMethod.MetadataToken);

                        //ast.VisitChildren(new DiagnosticVisitor(Console.Out));

                        var methodDecl = ast.Children.OfType <MethodDeclaration>().Single();

                        using (var masterWriter = new TextCodeWriter(snippet, null, true))
                        {
                            var codeWriterFactory = new NestedCodeWriterFactory(masterWriter);

                            using (var methodWriter = codeWriterFactory.New())
                            {
                                var context = new PascalScriptVisitorContext(
                                    this,
                                    methodWriter,
                                    null,
                                    namespaces,
                                    mi => GetSyntaxTree(mi.DeclaringType.Assembly.Location, mi.MetadataToken),
                                    referencedGlobalVariables,
                                    aliasFactory,
                                    new TextCodeWriter(typeDefinitions, null, false),
                                    declaredMembers,
                                    () => codeWriterFactory.New(),
                                    derivedType.BaseType,
                                    definedMethods);

                                ast.VisitChildren(new PascalScriptVisitor(context));

                                methodWriter.WriteBlankLine();
                            }
                        }
                    }

                    using (var codeWriter = new TextCodeWriter(textWriter, null, true))
                    {
                        typeDefinitions.CopyTo(codeWriter);

                        var usedSwitches           = new HashSet <string>();
                        var variableInitialization = new List <(string name, string rhs)>();

                        // write global variables
                        if (referencedGlobalVariables.Count > 0)
                        {
                            codeWriter.WriteLine("var");

                            using (codeWriter.Indent())
                            {
                                foreach (var globalVariable in referencedGlobalVariables)
                                {
                                    codeWriter.WriteLine($"{globalVariable.Value}: {globalVariable.Key.FieldType.ToPascal()};");

                                    var defaultValue          = globalVariable.Key.GetValue(this);
                                    var formattedDefaultValue = defaultValue == null || globalVariable.Key.FieldType.IsStruct() ? null : PascalScriptVisitor.FormatPrimitive(defaultValue);
                                    var cmdLineAttr           = (globalVariable.Key.GetCustomAttribute <CommandLineParameterAttribute>());

                                    if (cmdLineAttr != null)
                                    {
                                        var name           = cmdLineAttr.SwitchName ?? globalVariable.Key.Name;
                                        var initialization = $"ExpandConstant('{{param:{name.ToLower()}";

                                        if (defaultValue != null)
                                        {
                                            defaultValue = defaultValue.GetType() == typeof(bool) ?
                                                           ((bool)defaultValue ? "1" : "0") :
                                                           formattedDefaultValue;

                                            initialization += $"|{defaultValue}";
                                        }

                                        initialization += "}')";

                                        if (globalVariable.Key.FieldType == typeof(bool))
                                        {
                                            initialization = $"({initialization} = '1')";
                                        }

                                        if (!usedSwitches.Add(name))
                                        {
                                            throw new NotSupportedException($"The command line parameter name {name} can be used only once");
                                        }

                                        variableInitialization.Add((globalVariable.Key.Name, initialization));
                                    }
                                    else if (formattedDefaultValue != null)
                                    {
                                        // FormatPrimitive() won't single quote the string
                                        if (defaultValue is string)
                                        {
                                            formattedDefaultValue = $"'{formattedDefaultValue}'";
                                        }

                                        variableInitialization.Add((globalVariable.Key.Name, formattedDefaultValue));
                                    }
                                }
                            }
                        }

                        codeWriter.WriteBlankLine();

                        // write body of code
                        snippet.CopyTo(codeWriter);

                        using (var globalVariableSnippet = new Snippet())
                        {
                            using (var globalVariableWriter = new TextCodeWriter(globalVariableSnippet, null, true))
                            {
                                variableInitialization.ForEach(init => globalVariableWriter.WriteLine($"{init.name} := {init.rhs};"));
                            }

                            if (encounteredInitializeSetup || variableInitialization.Count > 0)
                            {
                                // write InitializeSetup
                                codeWriter.WriteLine($"function {nameof(Installation.InitializeSetup)}: Boolean;");
                                codeWriter.WriteBegin();

                                using (codeWriter.Indent())
                                {
                                    // write variable initialization
                                    globalVariableSnippet.CopyTo(codeWriter);

                                    codeWriter.WriteBlankLine();
                                    codeWriter.WriteLine(encounteredInitializeSetup ? "Result := this_InitializeSetup();" : "Result := True;");
                                }

                                codeWriter.WriteEnd();
                            }

                            if (encounteredInitializeUninstall || variableInitialization.Count > 0)
                            {
                                // write InitializeSetup
                                codeWriter.WriteLine($"function {nameof(Installation.InitializeUninstall)}: Boolean;");
                                codeWriter.WriteBegin();

                                using (codeWriter.Indent())
                                {
                                    // write variable initialization
                                    globalVariableSnippet.CopyTo(codeWriter);

                                    codeWriter.WriteBlankLine();
                                    codeWriter.WriteLine(encounteredInitializeUninstall ? "Result := this_InitializeUninstall();" : "Result := True;");
                                }

                                codeWriter.WriteEnd();
                            }
                        }
                    }
                }
            }
        }
コード例 #19
0
        private string UnwrapSyntaxTree(string source)
        {
            List <FieldDeclarationSyntax> parsedFields = new List <FieldDeclarationSyntax>();

            // Local function to recursively extract all the nested fields
            void ParseNestedFields(string typeSource)
            {
                // Find the field declarations
                Match match = NestedClosureFieldRegex.Match(typeSource);

                if (!match.Success)
                {
                    return;
                }

                // Load the nested closure type
                string fullname = match.Groups[1].Value.Replace(".<>", "+<>"); // Fullname of a nested type
                Type   type     = AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetType(fullname)).First(t => t != null);

                // Decompile the type and get a readable source code
                EntityHandle     typeHandle = MetadataTokenHelpers.TryAsEntityHandle(type.MetadataToken) ?? throw new InvalidOperationException();
                CSharpDecompiler decompiler = Decompilers[type.Assembly.Location];
                string
                    sourceCode    = decompiler.DecompileAsString(typeHandle),
                    typeFixedCode = ClosureTypeDeclarationRegex.Replace(sourceCode, "Scope");

                // Load the syntax tree and retrieve the list of fields
                SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(typeFixedCode);

                FieldDeclarationSyntax[] fields = syntaxTree.GetRoot().DescendantNodes().OfType <ClassDeclarationSyntax>().First().ChildNodes().OfType <FieldDeclarationSyntax>().ToArray();

                // Add the captured fields
                foreach (FieldDeclarationSyntax field in fields)
                {
                    if (!field.Declaration.Variables.ToFullString().StartsWith("CS$<>"))
                    {
                        parsedFields.Add(field);
                    }
                }

                // Explore the new decompiled type
                ParseNestedFields(typeFixedCode);
            }

            ParseNestedFields(source);

            if (parsedFields.Count > 0)
            {
                // Build the aggregated string with all the captured fields
                StringBuilder builder = new StringBuilder();
                foreach (FieldDeclarationSyntax field in parsedFields)
                {
                    builder.AppendLine(field.ToFullString());
                }
                string fields = builder.ToString().TrimEnd(' ', '\r', '\n');

                // Replace the field declarations
                Match match = NestedClosureFieldRegex.Match(source);
                source = source.Remove(match.Index - 11, match.Length + 12); // leading "    public " and trailing ";"
                source = source.Insert(match.Index - 11, fields);

                // Adjust the method body to remove references to compiler generated fields
                source = CompilerGeneratedFieldRegex.Replace(source, string.Empty);
            }

            return(source);
        }