Пример #1
0
        private static ReaderParameters GetReaderParameters(string assemblyPath)
        {
            DefaultAssemblyResolver assemblyResolver = new DefaultAssemblyResolver();

            string assemblyLocation = Path.GetDirectoryName(assemblyPath);

            assemblyResolver.AddSearchDirectory(assemblyLocation);

            ReaderParameters readerParameters = new ReaderParameters
            {
                AssemblyResolver = assemblyResolver,
                ReadingMode      = ReadingMode.Immediate
            };

            string pdbName = Path.ChangeExtension(assemblyPath, "pdb");

            if (!File.Exists(pdbName))
            {
                return(readerParameters);
            }
            PdbReaderProvider symbolReaderProvider = new PdbReaderProvider();

            readerParameters.SymbolReaderProvider = symbolReaderProvider;
            readerParameters.ReadSymbols          = true;

            return(readerParameters);
        }
Пример #2
0
        public static AssemblyDefinition GetAssemblyDef(string assemblyPath)
        {
            if (assemblies.ContainsKey(assemblyPath))
            {
                return(assemblies[assemblyPath]);
            }

            var assemblyResolver = new DefaultAssemblyResolver();
            var assemblyLocation = Path.GetDirectoryName(assemblyPath);

            assemblyResolver.AddSearchDirectory(assemblyLocation);

            var readerParameters = new ReaderParameters {
                AssemblyResolver = assemblyResolver
            };

            var pdbName = Path.ChangeExtension(assemblyPath, "pdb");

            if (File.Exists(pdbName))
            {
                var symbolReaderProvider = new PdbReaderProvider();
                readerParameters.SymbolReaderProvider = symbolReaderProvider;
                readerParameters.ReadSymbols          = true;
            }

            var assemblyDef = AssemblyDefinition.ReadAssembly(assemblyPath, readerParameters);

            assemblies.Add(assemblyPath, assemblyDef);

            return(assemblyDef);
        }
Пример #3
0
        private ReaderParameters GetReaderParameters()
        {
            DefaultAssemblyResolver assemblyResolver = new DefaultAssemblyResolver();
            string assemblyLocation = Path.GetDirectoryName(_assemblyLocation);

            assemblyResolver.AddSearchDirectory(assemblyLocation);

            ReaderParameters readerParameters = new ReaderParameters
            {
                AssemblyResolver = assemblyResolver,
#if DEBUG
                InMemory = true,
#endif
                ReadingMode = ReadingMode.Immediate
            };

            if (!File.Exists(PdbName))
            {
                return(readerParameters);
            }

            PdbReaderProvider symbolReaderProvider = new PdbReaderProvider();

            readerParameters.SymbolReaderProvider = symbolReaderProvider;

            return(readerParameters);
        }
Пример #4
0
        private AssemblyDefinition LoadAssembly()
        {
            try
            {
                var assemblyResolver = new DefaultAssemblyResolver();
                assemblyResolver.AddSearchDirectory(Path.GetDirectoryName(assemblyPath));

                var symbolReaderProvider = new PdbReaderProvider();

                logger.Progress($"Loading assembly: '{assemblyPath}'");
                var readerParameters = new ReaderParameters(ReadingMode.Immediate)
                {
                    ReadSymbols          = true,
                    AssemblyResolver     = assemblyResolver,
                    SymbolReaderProvider = symbolReaderProvider
                };

                var assembly = AssemblyDefinition.ReadAssembly(assemblyPath, readerParameters);
                logger.Progress("Loading assembly done");
                return(assembly);
            }
            catch (Exception e)
            {
                throw new InvalidOperationException($"Error while loading assembly '{assemblyPath}'.", e);
            }
        }
Пример #5
0
        private ReaderParameters CreateDefaultReaderParameters(IEnumerable <string> searchDirectories, string pdbPath = null)
        {
            var assemblyResolver = new DefaultAssemblyResolver();

            foreach (var searchDirectory in searchDirectories)
            {
                if (!string.IsNullOrEmpty(searchDirectory))
                {
                    assemblyResolver.AddSearchDirectory(searchDirectory);
                }
            }

            var readerParameters = new ReaderParameters
            {
                AssemblyResolver = assemblyResolver
            };

            if (!string.IsNullOrEmpty(pdbPath))
            {
                var pdbReaderProvider = new PdbReaderProvider();
                readerParameters.SymbolReaderProvider = pdbReaderProvider;
                readerParameters.ReadSymbols          = true;
            }

            return(readerParameters);
        }
Пример #6
0
        //stripped down version of: https://github.com/Keboo/AutoDI/blob/master/AutoDI.Build/AssemblyRewriteTask.cs
        private static Stream GetSymbolInformation(string assemblyFile, out ISymbolReaderProvider symbolReaderProvider,
                                                   out ISymbolWriterProvider symbolWriterProvider)
        {
            string pdbPath = FindPdbPath();

            if (pdbPath != null)
            {
                symbolReaderProvider = new PdbReaderProvider();
                symbolWriterProvider = new PdbWriterProvider();
                string tempPath = pdbPath + ".tmp";
                File.Copy(pdbPath, tempPath, true);
                return(new FileStream(tempPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
            }

            symbolReaderProvider = null;
            symbolWriterProvider = null;
            return(null);

            string FindPdbPath()
            {
                string path = Path.ChangeExtension(assemblyFile, "pdb");

                if (File.Exists(path))
                {
                    return(path);
                }
                return(null);
            }
        }
Пример #7
0
        private ISymbolReader ResolveSymbolReader()
        {
            string symbolLocation          = null;
            string pdbLocation             = Path.ChangeExtension(AssemblyLocation, "pdb");
            string mdbLocation             = AssemblyLocation + ".mdb";
            ISymbolReaderProvider provider = null;

            if (File.Exists(pdbLocation))
            {
                symbolLocation = pdbLocation;
                provider       = new PdbReaderProvider();
            }
            else if (File.Exists(mdbLocation))
            {
                symbolLocation = AssemblyLocation;
                provider       = new MdbReaderProvider();
            }
            if (provider == null)
            {
                return(null);
            }
            var reader = provider.GetSymbolReader(Definition, symbolLocation);

            return(reader);
        }
Пример #8
0
        internal static void Init()
        {
#pragma warning disable 168
            // the only purpose of this instruction is to create a reference to Mono.Cecil.Pdb.
            // Otherwise Visual Studio won't copy that assembly to the output path.
            var readerProvider = new PdbReaderProvider();
#pragma warning restore 168
        }
Пример #9
0
        static ModuleDefinition RoundtripModule(ModuleDefinition module, RoundtripType roundtripType)
        {
            if (roundtripType == RoundtripType.None)
            {
                return(module);
            }

            var file = Path.Combine(Path.GetTempPath(), "TestILProcessor.dll");

            if (File.Exists(file))
            {
                File.Delete(file);
            }

            ISymbolWriterProvider symbolWriterProvider;

            switch (roundtripType)
            {
            case RoundtripType.Pdb when Platform.HasNativePdbSupport:
                symbolWriterProvider = new PdbWriterProvider();
                break;

            case RoundtripType.PortablePdb:
            default:
                symbolWriterProvider = new PortablePdbWriterProvider();
                break;
            }

            module.Write(file, new WriterParameters {
                SymbolWriterProvider = symbolWriterProvider,
            });
            module.Dispose();

            ISymbolReaderProvider symbolReaderProvider;

            switch (roundtripType)
            {
            case RoundtripType.Pdb when Platform.HasNativePdbSupport:
                symbolReaderProvider = new PdbReaderProvider();
                break;

            case RoundtripType.PortablePdb:
            default:
                symbolReaderProvider = new PortablePdbReaderProvider();
                break;
            }

            return(ModuleDefinition.ReadModule(file, new ReaderParameters {
                SymbolReaderProvider = symbolReaderProvider,
                InMemory = true
            }));
        }
Пример #10
0
        public ILAssembly(Stack <ILAssembly> allAssemblies, string binaryPath, bool loadReferences, DefaultAssemblyResolver assemblyResolver)
        {
            allAssemblies.Push(this);

            // check if core lib
            string libName = Path.GetFileNameWithoutExtension(binaryPath);

            isCoreLib =
                libName == "mscorlib" ||
                //libName == "System.Runtime" ||
                libName == "System.Private.CoreLib" ||
                libName == "netstandard" ||
                (TypeSystem.CustomCoreLibName != null && libName == TypeSystem.CustomCoreLibName);

            // create reader parameters desc
            var readerParameters = new ReaderParameters();

            readerParameters.AssemblyResolver = assemblyResolver;

            // check if debug symbol file is avaliable
            var    pdbReaderProvider = new PdbReaderProvider();
            string symbolsPath       = Path.Combine(Path.GetDirectoryName(binaryPath), Path.GetFileNameWithoutExtension(binaryPath) + ".pdb");

            if (File.Exists(symbolsPath))
            {
                readerParameters.SymbolReaderProvider = pdbReaderProvider;
                readerParameters.ReadSymbols          = true;
            }

            // read assembly file
            assemblyDefinition = AssemblyDefinition.ReadAssembly(binaryPath, readerParameters);

            // load assembly modules
            modules = new Stack <ILModule>();
            foreach (var moduleDef in assemblyDefinition.Modules)
            {
                // read debug symbols for module
                ISymbolReader symbolReader = null;
                if (readerParameters.ReadSymbols)
                {
                    symbolReader = pdbReaderProvider.GetSymbolReader(moduleDef, symbolsPath);
                }

                // add module
                var module = new ILModule(allAssemblies, this, loadReferences, moduleDef, symbolReader, assemblyResolver);
                modules.Push(module);
            }
        }
Пример #11
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="assemblyPath"></param>
        /// <param name="currentPath"></param>
        /// <param name="savePath"></param>
        /// <returns></returns>
        public static bool BuildToFile(string assemblyPath, string currentPath, string savePath = null)
        {
            bool setSuccess = false;

            if (string.IsNullOrEmpty(savePath))
            {
                savePath = assemblyPath;
            }
            string            pdbFile        = Path.ChangeExtension(assemblyPath, "pdb");
            PdbReaderProvider readerProvider = null;
            PdbWriterProvider writerProvider = null;
            bool debug = false;

            if (File.Exists(pdbFile))
            {
                debug          = true;
                readerProvider = new PdbReaderProvider();
                writerProvider = new PdbWriterProvider();
            }
            //huhu modify reason: Support for model debugging.
            var ass = AssemblyDefinition.ReadAssembly(assemblyPath, new ReaderParameters
            {
                SymbolReaderProvider = readerProvider,
                ReadSymbols          = debug
            });
            BaseAssemblyResolver resolver = ass.MainModule.AssemblyResolver as BaseAssemblyResolver;

            if (resolver != null)
            {
                resolver.AddSearchDirectory(currentPath);
            }
            foreach (TypeDefinition type in ass.MainModule.GetTypes())
            {
                if (type.IsEnum)
                {
                    continue;
                }
                setSuccess = ProcessEntityType(type, setSuccess, currentPath);
            }
            //modify reason: no model.
            ass.Write(savePath, new WriterParameters
            {
                SymbolWriterProvider = writerProvider,
                WriteSymbols         = debug
            });
            return(true);
        }
Пример #12
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="assemblyPath"></param>
        /// <param name="outputAssembly"></param>
        /// <returns></returns>
        public static bool BuildToStream(string assemblyPath, out Stream outputAssembly)
        {
            bool   setSuccess  = false;
            string currentPath = Path.GetDirectoryName(assemblyPath);

            outputAssembly = new MemoryStream();
            using (Stream stream = ReadAssembly(assemblyPath))
            {
                string            pdbFile        = Path.ChangeExtension(assemblyPath, "pdb");
                PdbReaderProvider readerProvider = null;
                PdbWriterProvider writerProvider = null;
                bool debug = false;
                if (File.Exists(pdbFile))
                {
                    debug          = true;
                    readerProvider = new PdbReaderProvider();
                    writerProvider = new PdbWriterProvider();
                }

                var ass = AssemblyDefinition.ReadAssembly(stream, new ReaderParameters
                {
                    SymbolReaderProvider = readerProvider,
                    ReadSymbols          = debug
                });

                foreach (TypeDefinition type in ass.MainModule.GetTypes())
                {
                    if (type.IsEnum)
                    {
                        continue;
                    }
                    setSuccess = ProcessEntityType(type, setSuccess, currentPath);
                }
                if (setSuccess)
                {
                    ass.Write(outputAssembly, new WriterParameters
                    {
                        SymbolWriterProvider = writerProvider,
                        WriteSymbols         = debug
                    });
                    return(true);
                }
            }
            return(false);
        }
Пример #13
0
        public void LoadPdbOnDemand()
        {
            var assembly = File.ReadAllBytes(GetAssemblyResourcePath("Microsoft.AspNetCore.Components.dll"));
            var pdb      = File.ReadAllBytes(GetAssemblyResourcePath("Microsoft.AspNetCore.Components.pdb"));

            var module = ModuleDefinition.ReadModule(new MemoryStream(assembly), new ReaderParameters(ReadingMode.Immediate));

            var type       = module.GetType("Microsoft.AspNetCore.Components.Rendering.ComponentState");
            var main       = type.GetMethod("RenderIntoBatch");
            var debug_info = main.DebugInformation;

            var pdbReaderProvider = new PdbReaderProvider();
            var symbolReader      = pdbReaderProvider.GetSymbolReader(module, new MemoryStream(pdb));

            module.ReadSymbols(symbolReader);
            type       = module.GetType("Microsoft.AspNetCore.Components.Rendering.ComponentState");
            main       = type.GetMethod("RenderIntoBatch");
            debug_info = main.DebugInformation;
            Assert.AreEqual(9, debug_info.SequencePoints.Count);
        }
Пример #14
0
        /// <summary>
        /// Patches the specified input PDB file.
        /// </summary>
        /// <param name="inputExeFile">The input PDB file.</param>
        /// <param name="outputPdbFile">The output PDB file.</param>
        /// <param name="sourcePathRewriter">The source path modifier.</param>
        /// <exception cref="System.ArgumentNullException">inputExeFile</exception>
        public static void Patch(string inputExeFile, string outputPdbFile, SourcePathRewriterDelegate sourcePathRewriter)
        {
            if (inputExeFile == null)
            {
                throw new ArgumentNullException("inputExeFile");
            }
            if (outputPdbFile == null)
            {
                throw new ArgumentNullException("outputPdbFile");
            }
            if (sourcePathRewriter == null)
            {
                throw new ArgumentNullException("sourcePathRewriter");
            }

            // Copy PDB from input assembly to output assembly if any
            var inputPdbFile = Path.ChangeExtension(inputExeFile, "pdb");

            if (!File.Exists(inputPdbFile))
            {
                ShowMessage(string.Format("Warning file [{0}] does not exist", inputPdbFile), ConsoleColor.Yellow);
                return;
            }

            var symbolReaderProvider = new PdbReaderProvider();
            var readerParameters     = new ReaderParameters
            {
                SymbolReaderProvider = symbolReaderProvider,
                ReadSymbols          = true
            };

            // Read Assembly
            var assembly = AssemblyDefinition.ReadAssembly(inputExeFile, readerParameters);

            // Write back the assembly and pdb
            assembly.Write(inputExeFile, new WriterParameters {
                WriteSymbols = true, SourcePathRewriter = sourcePathRewriter
            });
        }
Пример #15
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="assemblyPath"></param>
        /// <param name="currentPath"></param>
        /// <param name="savePath"></param>
        /// <returns></returns>
        public static bool BuildToFile(string assemblyPath, string currentPath, string savePath = null)
        {
            bool setSuccess = false;

            if (string.IsNullOrEmpty(savePath))
            {
                savePath = assemblyPath;
            }
            string            pdbFile        = Path.ChangeExtension(assemblyPath, "pdb");
            PdbReaderProvider readerProvider = null;
            PdbWriterProvider writerProvider = null;
            bool debug = false;

            if (File.Exists(pdbFile))
            {
                debug          = true;
                readerProvider = new PdbReaderProvider();
                writerProvider = new PdbWriterProvider();
            }
            //huhu modify reason: Support for model debugging.
            var ass = AssemblyDefinition.ReadAssembly(assemblyPath, new ReaderParameters
            {
                SymbolReaderProvider = readerProvider,
                ReadSymbols          = debug
            });
            var types = ass.MainModule.Types.Where(p => !p.IsEnum).ToList();

            foreach (TypeDefinition type in types)
            {
                setSuccess = ProcessEntityType(type, setSuccess, currentPath);
            }
            //modify reason: no model.
            ass.Write(savePath, new WriterParameters
            {
                SymbolWriterProvider = writerProvider,
                WriteSymbols         = debug
            });
            return(true);
        }
Пример #16
0
        /// <summary>
        /// Patches the file.
        /// </summary>
        /// <param name="file">The file.</param>
        public bool PatchFile(string file)
        {
            var fileTime = new FileTime(file);
            //var fileTimeInteropBuilder = new FileTime(Assembly.GetExecutingAssembly().Location);
            string checkFile = Path.GetFullPath(file) + ".check";

            //string checkInteropBuilderFile = "InteropBuild.check";

            // If checkFile and checkInteropBuilderFile up-to-date, then nothing to do
            if (fileTime.CheckFileUpToDate(checkFile))
            {
                Log("Nothing to do. SharpDX patch was already applied for assembly [{0}]", file);
                return(false);
            }

            // Copy PDB from input assembly to output assembly if any
            var readerParameters = new ReaderParameters();
            var writerParameters = new WriterParameters();
            var pdbName          = Path.ChangeExtension(file, "pdb");

            if (File.Exists(pdbName))
            {
                var symbolReaderProvider = new PdbReaderProvider();
                readerParameters.SymbolReaderProvider = symbolReaderProvider;
                readerParameters.ReadSymbols          = true;
                writerParameters.WriteSymbols         = true;
            }

            // Read Assembly
            assembly = AssemblyDefinition.ReadAssembly(file, readerParameters);
            ((BaseAssemblyResolver)assembly.MainModule.AssemblyResolver).AddSearchDirectory(Path.GetDirectoryName(file));

            foreach (var assemblyNameReference in assembly.MainModule.AssemblyReferences)
            {
                if (assemblyNameReference.Name.ToLower() == "mscorlib")
                {
                    mscorlibAssembly = assembly.MainModule.AssemblyResolver.Resolve(assemblyNameReference);
                    break;
                }
            }

            // TODO: Temporary patch to handle correctly 4.5 Core profile
            if (mscorlibAssembly == null)
            {
                foreach (var assemblyNameReference in assembly.MainModule.AssemblyReferences)
                {
                    if (assemblyNameReference.Name == "System.Runtime")
                    {
                        ((BaseAssemblyResolver)assembly.MainModule.AssemblyResolver).AddSearchDirectory(Path.Combine(ProgramFilesx86(), @"Reference Assemblies\Microsoft\Framework\.NETCore\v4.5"));
                        mscorlibAssembly = assembly.MainModule.AssemblyResolver.Resolve(assemblyNameReference);
                        break;
                    }
                }
            }

            if (mscorlibAssembly == null)
            {
                LogError("Missing mscorlib.dll from assembly {0}", file);
                throw new InvalidOperationException("Missing mscorlib.dll from assembly");
            }

            // Import void* and int32 from assembly using mscorlib specific version (2.0 or 4.0 depending on assembly)
            voidType        = mscorlibAssembly.MainModule.GetType("System.Void");
            voidPointerType = new PointerType(assembly.MainModule.Import(voidType));
            intType         = assembly.MainModule.Import(mscorlibAssembly.MainModule.GetType("System.Int32"));

            // Remove CompilationRelaxationsAttribute
            for (int i = 0; i < assembly.CustomAttributes.Count; i++)
            {
                var customAttribute = assembly.CustomAttributes[i];
                if (customAttribute.AttributeType.FullName == typeof(CompilationRelaxationsAttribute).FullName)
                {
                    assembly.CustomAttributes.RemoveAt(i);
                    i--;
                }
            }

            Log("SharpDX interop patch for assembly [{0}]", file);
            foreach (var type in assembly.MainModule.Types)
            {
                PatchType(type);
            }

            // Remove All Interop classes
            foreach (var type in classToRemoveList)
            {
                assembly.MainModule.Types.Remove(type);
            }

            var outputFilePath = file;

            assembly.Write(outputFilePath, writerParameters);

            fileTime = new FileTime(file);
            // Update Check file
            fileTime.UpdateCheckFile(checkFile);
            //fileTimeInteropBuilder.UpdateCheckFile(checkInteropBuilderFile);

            Log("SharpDX patch done for assembly [{0}]", file);
            return(true);
        }
Пример #17
0
        public static void MethodInstrument(string targetAssembly, string src, string dst)
        {
            var inputAssembly = targetAssembly;
            var path          = Path.GetDirectoryName(inputAssembly);

            var assemblyResolver = new DefaultAssemblyResolver();
            var assemblyLocation = Path.GetDirectoryName(inputAssembly);

            assemblyResolver.AddSearchDirectory(assemblyLocation);

            var readerParameters = new ReaderParameters {
                AssemblyResolver = assemblyResolver
            };
            var  writerParameters = new WriterParameters();
            var  origPdb          = Path.ChangeExtension(inputAssembly, "pdb");
            bool existpdb         = false;

            if (File.Exists(origPdb))
            {
                existpdb = true;

                var symbolReaderProvider = new PdbReaderProvider();
                readerParameters.SymbolReaderProvider = symbolReaderProvider;
                readerParameters.ReadSymbols          = true;

                //var symbolWriterProvider = new PdbWriterProvider();
                //writerParameters.SymbolWriterProvider = symbolWriterProvider;
                writerParameters.WriteSymbols = true;
            }
            else
            {
                Console.WriteLine(".pdb file is unavailable.");
            }

            var assemblyDefinition = AssemblyDefinition.ReadAssembly(inputAssembly, readerParameters);
            var module             = assemblyDefinition.MainModule;
            //Mono.Collections.Generic.Collection<ModuleDefinition> modules = assemblyDefinition.Modules;
            //var module2 = ModuleDefinition.ReadModule(inputAssembly, readerParameters);


            //----------------------

            bool isChanged = false;

            //----------------------------

            foreach (var typeDefinition in module.Types)
            {
                if (typeDefinition.IsInterface)
                {
                    continue;
                }

                foreach (var methodDefinition in typeDefinition.Methods)
                {
                    ILProcessor ilprocessor = methodDefinition.Body.GetILProcessor();

                    Mono.Collections.Generic.Collection <Mono.Cecil.Cil.Instruction> allinstructions = methodDefinition.Body.Instructions;
                    int instructioncnt = allinstructions.Count;
                    for (int i = 0; i < instructioncnt; i++)
                    {
                        Mono.Cecil.Cil.Instruction instruction = allinstructions[i];

                        string instructpresent = instruction.ToString();

                        OpCode code        = instruction.OpCode;
                        string codepresent = code.Name;

                        var    operand    = instruction.Operand;
                        string methodname = "";
                        if (operand != null)
                        {
                            methodname = operand.ToString(); //with parameter
                        }

                        if ((code == OpCodes.Callvirt || code == OpCodes.Call) && //codepresent.Contains("call")
                            (isSameMethod(methodname, src)))                   //or (operand as MethodReference == module.Import(src as MethodInfo))
                        {
                            Console.WriteLine(codepresent + " " + methodname); //debug

                            //---------------------- remove --------------------------//
                            /**** remove instruction in case of no replacing method is provided ****/
                            //TODO: 1. I note the stack depth after the call and start removing instructions, beginning with the Code.Call
                            //  and moving backward until I get to that stack depth again.
                            //  2. return value handling

                            ilprocessor.Remove(instruction);
                            instructioncnt--;
                            if (allinstructions[i].OpCode == OpCodes.Pop) //TODO: just for test
                            {
                                ilprocessor.Remove(allinstructions[i]);
                                instructioncnt--;
                            }
                            i--;

                            if (dst == "")
                            {
                                continue;
                            }

                            //---------------------- replace (remove + insert) ------------------------//

                            /**** create new MethodInfo ****/
                            string     m_type = getNamespace(dst);
                            string     m_name = getMethodName(dst);
                            string []  m_para = getParameters(dst);
                            MethodInfo writeLineMethod;

                            //e.g. MethodInfo writeLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
                            if (m_para != null)
                            {
                                int    paraCnt     = m_para.Length;
                                Type[] m_para_type = new Type[paraCnt];
                                for (int k = 0; k < paraCnt; k++)
                                {
                                    m_para_type[k] = Type.GetType(m_para[k]);
                                }
                                writeLineMethod = Type.GetType(m_type).GetMethod(m_name, m_para_type);
                            }
                            else //the method does not have input parameters
                            {
                                writeLineMethod = Type.GetType(m_type).GetMethod(m_name, new Type[] { });
                            }

                            if (writeLineMethod == null)
                            {
                                throw new InvalidFileFormatException("no MethodInfo is created -- possibly a wrong method delaration.");
                            }

                            /*** Import the new (e.g. Console.WriteLine() method) ***/
                            MethodReference writeLine;
                            writeLine = module.Import(writeLineMethod); //convert "MethodInfo/MethodDefinition" to "MethodReference"

                            /*** Creates the CIL instruction for calling the new method (e.g. Console.WriteLine(string value) method) ***/
                            Mono.Cecil.Cil.Instruction callWriteLine;
                            callWriteLine = ilprocessor.Create(OpCodes.Call, writeLine);

                            /*** replace old instruction ***/
                            //TODO: 1. for simple-type parameters, create one instance and push to stack;
                            //  otherwise just a null object?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                            //  2. return value handling

                            ilprocessor.InsertAfter(allinstructions[i], callWriteLine);

                            //----------------------------------------------//

                            isChanged = true;
                        }
                    } //foreach instruction of a method
                }     //foreach method of a type/class
            }         //foreach type/class of loaded assembly

            if (isChanged)
            {
                var temporaryFileName = Path.Combine(path, string.Format("{0}_temp{1}", Path.GetFileNameWithoutExtension(inputAssembly),
                                                                         Path.GetExtension(inputAssembly)));
                var backupFileName = Path.Combine(path, string.Format("{0}_orig{1}", Path.GetFileNameWithoutExtension(inputAssembly),
                                                                      Path.GetExtension(inputAssembly)));

                var tmpPdb    = Path.Combine(path, string.Format("{0}_temp{1}", Path.GetFileNameWithoutExtension(inputAssembly), ".pdb"));
                var backupPdb = Path.Combine(path, string.Format("{0}_orig{1}", Path.GetFileNameWithoutExtension(inputAssembly), ".pdb"));

                //write an assembly with symbol file being rewritten
                //module.Write(temporaryFileName, writerParameters);
                assemblyDefinition.Write(temporaryFileName, writerParameters);

                File.Replace(temporaryFileName, inputAssembly, backupFileName);

                if (existpdb)
                {
                    File.Replace(tmpPdb, origPdb, backupPdb);
                }

                //TODO: add snkfile in configuration file and parse ([email protected])
                // If you have access to the key pair, you can ask Cecil to sign it directly.
                //if (snkFile != "")
                //{
                //sn -R inputAssembly snkFile
                //}
            }
        }
Пример #18
0
        /// <summary>
        /// Patches the file.
        /// </summary>
        /// <param name="file">The file.</param>
        public bool PatchFile(string file)
        {
            file = Path.Combine(Environment.CurrentDirectory, file);

            var fileTime = new FileTime(file);
            //var fileTimeInteropBuilder = new FileTime(Assembly.GetExecutingAssembly().Location);
            string checkFile = Path.GetFullPath(file) + ".check";

            //string checkInteropBuilderFile = "InteropBuild.check";

            // If checkFile and checkInteropBuilderFile up-to-date, then nothing to do
            if (fileTime.CheckFileUpToDate(checkFile))
            {
                Log("Nothing to do. SharpDX patch was already applied for assembly [{0}]", file);
                return(false);
            }

            // Copy PDB from input assembly to output assembly if any
            var readerParameters = new ReaderParameters();
            var resolver         = new DefaultAssemblyResolver();

            readerParameters.AssemblyResolver = resolver;
            var writerParameters = new WriterParameters();
            var pdbName          = Path.ChangeExtension(file, "pdb");

            if (File.Exists(pdbName))
            {
                var symbolReaderProvider = new PdbReaderProvider();
                readerParameters.SymbolReaderProvider = symbolReaderProvider;
                readerParameters.ReadSymbols          = true;
                writerParameters.WriteSymbols         = true;
            }

            // Read Assembly
            assembly = AssemblyDefinition.ReadAssembly(file, readerParameters);
            resolver.AddSearchDirectory(Path.GetDirectoryName(file));

            // Query the target framework in order to resolve correct assemblies and type forwarding
            var targetFrameworkAttr = assembly.CustomAttributes.FirstOrDefault(
                attribute => attribute.Constructor.FullName.Contains("System.Runtime.Versioning.TargetFrameworkAttribute"));

            if (targetFrameworkAttr != null && targetFrameworkAttr.ConstructorArguments.Count > 0 &&
                targetFrameworkAttr.ConstructorArguments[0].Value != null)
            {
                var targetFramework = new FrameworkName(targetFrameworkAttr.ConstructorArguments[0].Value.ToString());

                var netcoreAssemblyPath = string.Format(@"Reference Assemblies\Microsoft\Framework\{0}\v{1}",
                                                        targetFramework.Identifier,
                                                        targetFramework.Version);
                netcoreAssemblyPath = Path.Combine(ProgramFilesx86(), netcoreAssemblyPath);
                if (Directory.Exists(netcoreAssemblyPath))
                {
                    resolver.AddSearchDirectory(netcoreAssemblyPath);
                }
            }

            // Import void* and int32
            voidType        = assembly.MainModule.TypeSystem.Void.Resolve();
            voidPointerType = new PointerType(assembly.MainModule.Import(voidType));
            intType         = assembly.MainModule.Import(assembly.MainModule.TypeSystem.Int32.Resolve());

            // Remove CompilationRelaxationsAttribute
            for (int i = 0; i < assembly.CustomAttributes.Count; i++)
            {
                var customAttribute = assembly.CustomAttributes[i];
                if (customAttribute.AttributeType.FullName == typeof(CompilationRelaxationsAttribute).FullName)
                {
                    assembly.CustomAttributes.RemoveAt(i);
                    i--;
                }
            }

            Log("SharpDX interop patch for assembly [{0}]", file);
            foreach (var type in assembly.MainModule.Types)
            {
                PatchType(type);
            }

            // Remove All Interop classes
            foreach (var type in classToRemoveList)
            {
                assembly.MainModule.Types.Remove(type);
            }

            var outputFilePath = file;

            assembly.Write(outputFilePath, writerParameters);

            fileTime = new FileTime(file);
            // Update Check file
            fileTime.UpdateCheckFile(checkFile);
            //fileTimeInteropBuilder.UpdateCheckFile(checkInteropBuilderFile);

            Log("SharpDX patch done for assembly [{0}]", file);
            return(true);
        }
Пример #19
0
        async Task <MethodInfo> LoadSymbolsOnDemand(AssemblyInfo asm, uint method_token, SessionId sessionId, CancellationToken token)
        {
            var context = GetContext(sessionId);

            if (asm.TriedToLoadSymbolsOnDemand)
            {
                return(null);
            }
            asm.TriedToLoadSymbolsOnDemand = true;
            ImageDebugHeader header = asm.Image.GetDebugHeader();

            for (var i = 0; i < header.Entries.Length; i++)
            {
                var entry = header.Entries[i];
                if (entry.Directory.Type != ImageDebugType.CodeView)
                {
                    continue;
                }

                var data = entry.Data;

                if (data.Length < 24)
                {
                    return(null);
                }

                var pdbSignature = (data[0]
                                    | (data[1] << 8)
                                    | (data[2] << 16)
                                    | (data[3] << 24));

                if (pdbSignature != 0x53445352) // "SDSR" mono/metadata/debug-mono-ppdb.c#L101
                {
                    return(null);
                }

                var buffer = new byte[16];
                Buffer.BlockCopy(data, 4, buffer, 0, 16);

                var pdbAge = (data[20]
                              | (data[21] << 8)
                              | (data[22] << 16)
                              | (data[23] << 24));

                var pdbGuid = new Guid(buffer);
                var buffer2 = new byte[(data.Length - 24) - 1];
                Buffer.BlockCopy(data, 24, buffer2, 0, (data.Length - 24) - 1);
                var pdbName = System.Text.Encoding.UTF8.GetString(buffer2, 0, buffer2.Length);
                pdbName = Path.GetFileName(pdbName);

                foreach (var urlSymbolServer in urlSymbolServerList)
                {
                    var downloadURL = $"{urlSymbolServer}/{pdbName}/{pdbGuid.ToString("N").ToUpper() + pdbAge}/{pdbName}";

                    try
                    {
                        using HttpResponseMessage response = await client.GetAsync(downloadURL);

                        using Stream streamToReadFrom = await response.Content.ReadAsStreamAsync();

                        var portablePdbReaderProvider = new PdbReaderProvider();
                        var symbolReader = portablePdbReaderProvider.GetSymbolReader(asm.Image, streamToReadFrom);
                        asm.ClearDebugInfo(); //workaround while cecil PR #686 is not merged
                        asm.Image.ReadSymbols(symbolReader);
                        asm.Populate();
                        foreach (var source in asm.Sources)
                        {
                            var scriptSource = JObject.FromObject(source.ToScriptSource(context.Id, context.AuxData));
                            SendEvent(sessionId, "Debugger.scriptParsed", scriptSource, token);
                        }
                        return(asm.GetMethodByToken(method_token));
                    }
                    catch (Exception e)
                    {
                        Log("info", $"Unable to load symbols on demand exception: {e.ToString()} url:{downloadURL} assembly: {asm.Name}");
                    }
                }
                break;
            }

            Log("info", "Unable to load symbols on demand assembly: {asm.Name}");
            return(null);
        }
Пример #20
0
        public bool ProcessFile(string sourceFile, string targetFile = "")
        {
            bool result = false;

            if (string.IsNullOrEmpty(targetFile))
            {
                targetFile = sourceFile;
            }

            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            try
            {
                var resolver = new DefaultAssemblyResolver();
                resolver.AddSearchDirectory(GetAssemblyDirectoryFromType(typeof(Resource)));

                var parameters = new ReaderParameters {
                    AssemblyResolver = resolver
                };

                Assembly = AssemblyDefinition.ReadAssembly(sourceFile, parameters);

                Log.LogMessage("------ Begin Task: ImplementRdfMapping [{0}]", Assembly.Name);

                bool assemblyModified = false;

                // Iterate over all types in the main assembly.
                foreach (TypeDefinition type in Assembly.MainModule.Types)
                {
                    // In the following we need to seperate between properties which have the following attribute combinations:
                    //  - PropertyAttribute with PropertyChangedAttribute
                    //  - PropertyAttribute without PropertyChangedAttribute
                    //  - PropertyChangedAttribute only
                    HashSet <PropertyDefinition> mapping   = type.GetPropertiesWithAttribute <RdfPropertyAttribute>().ToHashSet();
                    HashSet <PropertyDefinition> notifying = type.GetPropertiesWithAttribute <NotifyPropertyChangedAttribute>().ToHashSet();

                    // Implement the GetTypes()-method for the given type.
                    if (mapping.Any() || type.TryGetCustomAttribute <RdfClassAttribute>().Any())
                    {
                        ImplementRdfClassTask implementClass = new ImplementRdfClassTask(this, type);

                        // RDF types _must_ be implemented for classes with mapped properties.
                        assemblyModified = implementClass.Execute();
                    }

                    // Properties which do not raise the PropertyChanged-event can be implemented using minimal IL code.
                    if (mapping.Any())
                    {
                        var implementProperty = new ImplementRdfPropertyTask(this, type);

                        foreach (PropertyDefinition p in mapping.Except(notifying).Where(implementProperty.CanExecute))
                        {
                            assemblyModified = implementProperty.Execute(p);
                        }
                    }

                    // Properties which raise the PropertyChanged-event may also have the RdfProperty attribute.
                    if (notifying.Any())
                    {
                        var implementPropertyChanged = new ImplementNotifyPropertyChangedTask(this, type);

                        foreach (PropertyDefinition p in notifying.Where(implementPropertyChanged.CanExecute))
                        {
                            implementPropertyChanged.IsMappedProperty = mapping.Contains(p);

                            assemblyModified = implementPropertyChanged.Execute(p);
                        }
                    }
                }

                if (assemblyModified)
                {
                    if (WriteSymbols)
                    {
                        // Use the correct debug symbol reader and writer on Mono and .NET
                        if (Type.GetType("Mono.Runtime") != null)
                        {
                            using (ISymbolReader symbolReader = new MdbReaderProvider().GetSymbolReader(Assembly.MainModule, sourceFile))
                            {
                                ISymbolWriterProvider symbolWriter = new MdbWriterProvider();

                                WriteSymbolsToAssembly(targetFile, symbolReader, symbolWriter);
                            }
                        }
                        else
                        {
                            using (ISymbolReader symbolReader = new PdbReaderProvider().GetSymbolReader(Assembly.MainModule, sourceFile))
                            {
                                ISymbolWriterProvider symbolWriter = new PdbWriterProvider();

                                WriteSymbolsToAssembly(targetFile, symbolReader, symbolWriter);
                            }
                        }
                    }
                    else
                    {
                        Assembly.Write(targetFile, new WriterParameters {
                            WriteSymbols = false
                        });
                    }
                }

                result = true;
            }
            catch (Exception ex)
            {
                Log.LogError(ex.ToString());

                result = false;
            }

            stopwatch.Stop();

            Log.LogMessage("------ End Task: ImplementRdfMapping [Total time: {0}s]", stopwatch.Elapsed.TotalSeconds);

            return(result);
        }
Пример #21
0
        private static int Main(string[] args)
        {
            Console.WriteLine("---------------------- CrossSL V1.0 ----------------------");

            if (args.Length == 0 || String.IsNullOrEmpty(args[0]))
            {
                DebugLog.UsageError("Start CrossSL with a .NET assemly as argument to translate\n" +
                                    "shaders from .NET to GLSL, e.g. 'CrossSL.exe Assembly.exe'");
                return(-1);
            }

            string inputPath = args[0];

            var asmName = Path.GetFileName(inputPath);
            var asmDir  = Path.GetDirectoryName(inputPath);

            if (!File.Exists(inputPath))
            {
                DebugLog.UsageError("Could not find assembly '" + asmName + "' in path:\n\n" + asmDir);
                return(-1);
            }

            // ReSharper disable once AssignNullToNotNullAttribute
            var metaPath = Path.Combine(asmDir, "CrossSL.Meta.dll");

            if (!File.Exists(inputPath) || !File.Exists(metaPath))
            {
                DebugLog.UsageError("Found assembly '" + asmName + "' but meta assembly 'CrossSL.Meta.dll'" +
                                    "\nis missing. It needs to be in the same directory:\n\n" + asmDir);
                return(-1);
            }

            Console.WriteLine("\n\nFound assembly '" + asmName + "' and meta assembly 'CrossSL.Meta.dll'.");

            // check if there is a .pdb file along with the .exe
            var debugFile = Path.ChangeExtension(inputPath, "pdb");
            var debugName = Path.GetFileName(debugFile);

            DebugLog.Verbose = File.Exists(debugFile);
            Console.WriteLine(DebugLog.Verbose
                ? "Found also .pdb file '" + debugName + "'. This allows for better debugging."
                : "Found no .pdb file '" + debugName + "'. Extended debugging has been disabled.");

            // read assembly (and symbols) with Mono.Cecil
            var resolver = new DefaultAssemblyResolver();

            resolver.AddSearchDirectory(asmDir);

            var readParams = new ReaderParameters {
                ReadSymbols = DebugLog.Verbose, AssemblyResolver = resolver
            };
            var asm = AssemblyDefinition.ReadAssembly(inputPath, readParams);

            // read meta assembly (without symbols) with Mono.Cecil
            var metaParams = new ReaderParameters {
                ReadSymbols = false
            };
            var metaAsm = AssemblyDefinition.ReadAssembly(metaPath, metaParams);

            // find all types with xSLShader as base type
            var shaderDescs = new List <ShaderDesc>();

            var asmTypes = asm.Modules.SelectMany(
                asmMod => asmMod.Types.Where(asmType => asmType.BaseType != null));
            var asmShaderTypes = asmTypes.Where(asmType => asmType.BaseType.IsType <xSLShader>());

            foreach (var asmType in asmShaderTypes)
            {
                DebugLog.Reset();

                if (DebugLog.Verbose)
                {
                    // load symbols from pdb file
                    var asmModule = asmType.Module;

                    using (var symbReader = new PdbReaderProvider().GetSymbolReader(asmModule, debugFile))
                        asmModule.ReadSymbols(symbReader);
                }

                var asmTypeName = asmType.Name;
                Console.WriteLine("\n\nFound a shader called '" + asmTypeName + "':");

                var shaderDesc = new ShaderDesc {
                    Name = asmTypeName, Type = asmType
                };

                // check for [xSLDebug] first in case the shader should be ignored
                var debugAttr = asmType.CustomAttributes.FirstOrDefault(
                    attrType => attrType.AttributeType.IsType <xSLShader.xSLDebugAttribute>());

                if (debugAttr != null)
                {
                    shaderDesc.DebugFlags = (xSLShader.xSLDebug)debugAttr.ConstructorArguments[0].Value;

                    if ((shaderDesc.DebugFlags & xSLShader.xSLDebug.IgnoreShader) != 0)
                    {
                        Console.WriteLine("  => Found [xSLDebug] with 'IgnoreShader' flag. Shader skipped.");
                        continue;
                    }
                }

                // check for [xSLTarget] and save settings
                var targetAttr = asmType.CustomAttributes.FirstOrDefault(
                    attr => attr.AttributeType.IsType <xSLShader.xSLTargetAttribute>());

                if (targetAttr == null)
                {
                    shaderDesc.Target = new ShaderTarget {
                        Envr = SLEnvironment.OpenGL, Version = 110, VersionID = 0
                    };
                    DebugLog.Error("Could not find [xSLTarget]. Please specify the targeted shading language");
                }
                else
                {
                    var typeName  = targetAttr.ConstructorArguments[0].Type.Name;
                    var versionID = (int)targetAttr.ConstructorArguments[0].Value;

                    var shaderTarget = new ShaderTarget {
                        VersionID = versionID
                    };

                    switch (typeName)
                    {
                    case "GLSL":
                        shaderTarget.Envr = SLEnvironment.OpenGL;
                        break;

                    case "GLSLES":
                        shaderTarget.Envr = SLEnvironment.OpenGLES;
                        break;

                    case "GLSLMix":
                        shaderTarget.Envr = SLEnvironment.OpenGLMix;
                        break;
                    }

                    var vStr = SLVersion.VIDs[(int)shaderTarget.Envr][versionID];

                    shaderTarget.Version = Int32.Parse(vStr);
                    shaderDesc.Target    = shaderTarget;

                    if (shaderTarget.Envr == SLEnvironment.OpenGLMix)
                    {
                        typeName = "GLSL 1.10 & GLSLES";
                        vStr     = "100";
                    }

                    vStr = vStr.Insert(1, ".");
                    Console.WriteLine("  => Found [xSLTarget]. Compiling shader as " + typeName + " " + vStr + ".");
                }

                var shaderTranslator = ShaderTranslator.GetTranslator(shaderDesc.Target);
                shaderTranslator.ShaderDesc = shaderDesc;

                // save debug settings
                if (debugAttr == null)
                {
                    shaderDesc.DebugFlags = xSLShader.xSLDebug.None;
                    Console.WriteLine("  => Could not find [xSLDebug]. Debugging has been disabled.");
                    DebugLog.Disabled = true;
                }
                else
                {
                    if ((shaderDesc.DebugFlags & xSLShader.xSLDebug.None) != 0)
                    {
                        Console.WriteLine("  => Found [xSLDebug] with 'None' flag. Debugging has been disabled.");
                    }
                    else
                    {
                        Console.WriteLine("  => Found [xSLDebug]. Debugging with flags: " + shaderDesc.DebugFlags);
                    }
                }

                // check for common mistakes
                Console.WriteLine("\n  1. Checking shader for obvious mistakes.");

                // check if vertex or fragment method is missing
                MethodDefinition vertexMain;
                if (!MethodExists(asmType, "VertexShader", out vertexMain))
                {
                    continue;
                }

                MethodDefinition fragmentMain;
                if (!MethodExists(asmType, "FragmentShader", out fragmentMain))
                {
                    continue;
                }

                // get their precission attributes
                var vertPrecAttr = vertexMain.CustomAttributes.FirstOrDefault(
                    attrType => attrType.AttributeType.IsType <xSLShader.xSLPrecisionAttribute>());

                var fragPrecAttr = fragmentMain.CustomAttributes.FirstOrDefault(
                    attrType => attrType.AttributeType.IsType <xSLShader.xSLPrecisionAttribute>());

                shaderDesc.Precision = new CustomAttribute[2];
                shaderDesc.Precision[(int)SLShaderType.VertexShader]   = vertPrecAttr;
                shaderDesc.Precision[(int)SLShaderType.FragmentShader] = fragPrecAttr;

                // get default file for this shader in case no instructions are available
                var defaultSeq = vertexMain.Body.Instructions[0].SequencePoint;

                DebugLog.DefaultFile = defaultSeq != null?Path.GetFileName(defaultSeq.Document.Url) : asmTypeName;

                // check if there are additional constructors for field/property initialization
                var ctorMethods = asmType.Methods.Where(asmMethod => asmMethod.IsConstructor);
                var customCtors = new Collection <MethodDefinition>();

                foreach (var ctorMethod in ctorMethods.Where(ctor => ctor.Body.CodeSize > 7))
                {
                    // see if there are field initializations (as for "constants")
                    var varInits = ctorMethod.Body.Instructions.Any(instr => instr.OpCode == OpCodes.Stfld);

                    // or property setter calls (as for "constants")
                    var funcCalls = ctorMethod.Body.Instructions.Where(instr => instr.OpCode == OpCodes.Call);
                    var propInits = funcCalls.Any(instr => ((MethodReference)instr.Operand).Resolve().IsSetter);

                    if (varInits || propInits)
                    {
                        customCtors.Add(ctorMethod);
                    }
                    else
                    {
                        var instr = ctorMethod.Body.Instructions[0];
                        DebugLog.Warning("Found a constructor with no valid content", instr);
                    }
                }

                // analyze variables used in shader
                Console.WriteLine("\n  2. Collecting information about fields and properties.");

                var variables = new Collection <VariableDesc>();
                var varTypes  = Enum.GetNames(typeof(SLVariableType));

                // read and gather fields and backing fields
                foreach (var asmField in asmType.Fields)
                {
                    var varDesc = new VariableDesc {
                        Definition = asmField
                    };

                    var fdName  = asmField.Name;
                    var fdType  = asmField.FieldType.ToType();
                    var fdArray = asmField.FieldType.IsArray;
                    var attrs   = asmField.CustomAttributes;

                    var isProp = fdName.Contains("<");

                    if (isProp)
                    {
                        // ReSharper disable once StringIndexOfIsCultureSpecific.1
                        fdName = fdName.Remove(0, 1).Remove(fdName.IndexOf('>') - 1);

                        var asmProp = asmType.Properties.First(prop => prop.Name == fdName);
                        varDesc.Definition = asmProp;

                        attrs   = asmProp.CustomAttributes;
                        fdType  = asmProp.PropertyType.ToType();
                        fdArray = asmProp.PropertyType.IsArray;
                    }

                    var attrCt = attrs.Count(attr => varTypes.Contains(attr.AttributeType.Name));

                    var validFd = (asmField.HasConstant || attrCt == 1);
                    var varType = (isProp) ? "Property '" : "Field '";

                    if (asmField.IsStatic && !asmField.HasConstant)
                    {
                        DebugLog.Error(varType + fdName + "' cannot be static");
                    }
                    else if (validFd)
                    {
                        var fdAttrName = attrs.First(attr => varTypes.Contains(attr.AttributeType.Name));
                        var fdAttr     = (SLVariableType)Array.IndexOf(varTypes, fdAttrName.AttributeType.Name);

                        if (asmField.HasConstant)
                        {
                            if (fdAttr != SLVariableType.xSLConstAttribute)
                            {
                                DebugLog.Error(varType + "constant " + fdName + "' has an invalid attribute");
                            }

                            varDesc.Value = asmField.Constant;
                        }

                        varDesc.DataType  = fdType;
                        varDesc.Attribute = fdAttr;
                        varDesc.IsArray   = fdArray;

                        variables.Add(varDesc);
                    }
                    else
                    {
                        DebugLog.Error(varType + fdName + "' is neither a constant nor has valid attributes");
                    }
                }

                shaderDesc.Variables = variables;
                shaderTranslator.PreVariableCheck();

                // translate main, depending methods and constructors
                if (shaderDesc.Target.Envr == SLEnvironment.OpenGLMix)
                {
                    Console.WriteLine("\n  3. Translating shader from C# to GLSL/GLSLES.");
                }
                else
                {
                    Console.WriteLine("\n  3. Translating shader from C# to " + shaderDesc.Target.Envr + ".");
                }

                shaderDesc.Funcs = new IEnumerable <FunctionDesc> [2];

                var vertexFuncs = shaderTranslator.Translate(shaderDesc.Target, vertexMain);
                shaderDesc.Funcs[(int)SLShaderType.VertexShader] = vertexFuncs;

                var fragmentFuncs = shaderTranslator.Translate(shaderDesc.Target, fragmentMain);
                shaderDesc.Funcs[(int)SLShaderType.FragmentShader] = fragmentFuncs;

                // check correct use of constants
                foreach (var ctor in customCtors)
                {
                    var funcs = shaderTranslator.Translate(shaderDesc.Target, ctor);

                    var allVars     = funcs.SelectMany(func => func.Variables).ToList();
                    var allGlobVars = allVars.Where(variables.Contains).ToList();
                    var illegalVars = allVars.Except(allGlobVars).ToList();

                    foreach (var illegalVar in illegalVars)
                    {
                        var name  = illegalVar.Definition.Name;
                        var instr = illegalVar.Instruction;

                        DebugLog.Error("Illegal use of '" + name + "' in a constructor", instr);
                    }

                    foreach (var constVar in allGlobVars)
                    {
                        var globVar = shaderDesc.Variables.First(var => var.Equals(constVar));
                        var index   = shaderDesc.Variables.IndexOf(globVar);

                        var name  = constVar.Definition.Name;
                        var instr = constVar.Instruction;

                        if (globVar.Attribute != SLVariableType.xSLConstAttribute)
                        {
                            DebugLog.Error("Variable '" + name + "' is used as a constant but not marked as such'",
                                           instr);
                        }
                        else if (globVar.Value != null && constVar.Value != null)
                        {
                            DebugLog.Error("Constant '" + name + "' cannot be set more than once", instr);
                        }
                        else if (constVar.Value is String)
                        {
                            DebugLog.Error("Constant '" + name + "' was initialized with an invalid value", instr);
                        }
                        else
                        {
                            shaderDesc.Variables[index].Value = constVar.Value;
                        }
                    }
                }

                // build both shaders
                var vertexResult   = shaderTranslator.BuildShader(SLShaderType.VertexShader);
                var fragmentResult = shaderTranslator.BuildShader(SLShaderType.FragmentShader);
                shaderDesc = shaderTranslator.ShaderDesc;

                // see if there are unused fields/properties
                var unusedVars = shaderDesc.Variables.Where(var => !var.IsReferenced);
                unusedVars = unusedVars.Where(var => var.Attribute != SLVariableType.xSLConstAttribute);

                foreach (var unsedVar in unusedVars)
                {
                    DebugLog.Warning("Variable '" + unsedVar.Definition.Name + "' was declared but not used");
                }

                if (!DebugLog.Abort)
                {
                    Console.WriteLine("\n  4. Building vertex and fragment shader.");

                    // debugging: save to file first, then precompile
                    Console.WriteLine("\n  5. Applying debugging flags if any.");

                    if (!DebugLog.Abort && (xSLShader.xSLDebug.SaveToFile & shaderDesc.DebugFlags) != 0)
                    {
                        var directory = Path.GetDirectoryName(inputPath);

                        if (directory != null)
                        {
                            var combined = new StringBuilder("---- VertexShader ----").NewLine(2);
                            combined.Append(vertexResult).NewLine(3).Append("---- FragmentShader ----");
                            combined.NewLine(2).Append(fragmentResult);

                            var filePath = Path.Combine(directory, shaderDesc.Name + ".txt");
                            File.WriteAllText(filePath, combined.ToString());

                            Console.WriteLine("    => Saved shader to: '" + filePath + "'");
                        }
                    }

                    if (!DebugLog.Abort && (xSLShader.xSLDebug.PreCompile & shaderDesc.DebugFlags) != 0)
                    {
                        shaderTranslator.PreCompile(vertexResult, fragmentResult);
                    }
                }
                else
                {
                    Console.WriteLine("\n  4. Shader will not be built due to critical errors.");
                    Console.WriteLine("\n  5. Applying debugging flags if any.");
                }

                if (DebugLog.Abort)
                {
                    if ((xSLShader.xSLDebug.ThrowException & shaderDesc.DebugFlags) != 0)
                    {
                        Console.WriteLine("    => Errors will be thrown when using the shader.");
                        Console.WriteLine("\n  6. Preparing to update meta assembly for this shader.");
                    }
                }

                // save shaders or errors into the assembly
                var genShader  = metaAsm.MainModule.Types.First(type => type.ToType() == typeof(xSL <>));
                var instShader = new GenericInstanceType(genShader);

                var asmTypeImport = metaAsm.MainModule.Import(asmType);
                instShader.GenericArguments.Add(asmTypeImport);

                var instrList = new List <Instruction>();

                if (!DebugLog.Abort)
                {
                    Console.WriteLine("\n  6. Preparing to update meta assembly for this shader.");

                    var vertField  = GenericFieldReference(genShader, instShader, "_vertex");
                    var fragField  = GenericFieldReference(genShader, instShader, "_fragment");
                    var transField = GenericFieldReference(genShader, instShader, "_translated");

                    metaAsm.MainModule.Import(vertField);
                    metaAsm.MainModule.Import(fragField);
                    metaAsm.MainModule.Import(transField);

                    instrList.Add(Instruction.Create(OpCodes.Ldstr, vertexResult.ToString()));
                    instrList.Add(Instruction.Create(OpCodes.Stsfld, vertField));

                    instrList.Add(Instruction.Create(OpCodes.Ldstr, fragmentResult.ToString()));
                    instrList.Add(Instruction.Create(OpCodes.Stsfld, fragField));

                    instrList.Add(Instruction.Create(OpCodes.Ldc_I4_1));
                    instrList.Add(Instruction.Create(OpCodes.Stsfld, transField));
                }

                // apply debug mode ThrowException
                if (DebugLog.Abort && (xSLShader.xSLDebug.ThrowException & shaderDesc.DebugFlags) != 0)
                {
                    var errors   = DebugLog.Errors.ToString().Replace("    =>", "=>");
                    var errField = GenericFieldReference(genShader, instShader, "_error");

                    instrList.Add(Instruction.Create(OpCodes.Ldstr, errors));
                    instrList.Add(Instruction.Create(OpCodes.Stsfld, errField));
                }

                shaderDesc.Instructions = instrList;

                Console.WriteLine(DebugLog.Abort
                    ? "\n  ---- Translation failed ----"
                    : "\n  ---- Translation succeeded ----");

                shaderDescs.Add(shaderDesc);
            }

            // write shaders into assembly
            var invalidCt = shaderDescs.Count(shader => !shader.Instructions.Any());

            if (invalidCt == shaderDescs.Count)
            {
                Console.WriteLine("\n\nAssembly will not be updated as no shader was translated successfully.");
            }
            else
            {
                Console.WriteLine("\n\nUpdating CrossSL meta assembly:");

                var asmModule = metaAsm.MainModule;
                var genShader = asmModule.Types.First(type => type.ToType() == typeof(xSL <>));

                var xSLInit = genShader.Methods.First(method => method.Name == "Init");
                var ilProc  = xSLInit.Body.GetILProcessor();

                xSLInit.Body.Instructions.Clear();

                foreach (var shaderDesc in shaderDescs)
                {
                    foreach (var instr in shaderDesc.Instructions)
                    {
                        ilProc.Append(instr);
                    }
                }

                var ret = Instruction.Create(OpCodes.Ret);
                ilProc.Append(ret);

                try
                {
                    var writeParams = new WriterParameters {
                        WriteSymbols = false
                    };
                    asmModule.Write(metaPath, writeParams);

                    foreach (var shaderDesc in shaderDescs)
                    {
                        if (shaderDesc.Instructions.Count() > 2)
                        {
                            Console.WriteLine("  => Added shader '" + shaderDesc.Name + "' to assembly.");
                        }
                        else if (shaderDesc.Instructions.Any())
                        {
                            Console.WriteLine("  => [ThrowException] mode was applied for shader '" +
                                              shaderDesc.Name + "'.");
                        }
                    }

                    Console.WriteLine("\n  => Saved assembly as '" + metaPath + "'");
                }
                catch (IOException)
                {
                    Console.WriteLine("  => Cannot update assembly. File might be missing, read-only or in use.");
                }
            }

            DebugLog.UsageError("\nDone.");


            return(0);
        }
Пример #22
0
        private Stream GetSymbolInformation(out ISymbolReaderProvider symbolReaderProvider,
                                            out ISymbolWriterProvider symbolWriterProvider)
        {
            if (string.Equals("none", DebugType, StringComparison.OrdinalIgnoreCase))
            {
                Logger.Info("No symbols");
                symbolReaderProvider = null;
                symbolWriterProvider = null;
                return(null);
            }

            if (string.Equals("embedded", DebugType, StringComparison.OrdinalIgnoreCase))
            {
                Logger.Info("Using embedded symbols");
                symbolReaderProvider = new EmbeddedPortablePdbReaderProvider();
                symbolWriterProvider = new EmbeddedPortablePdbWriterProvider();
                return(null);
            }

            string pdbPath = FindPdbPath();
            string mdbPath = FindMdbPath();

            if (pdbPath != null && mdbPath != null)
            {
                if (File.GetLastWriteTimeUtc(pdbPath) >= File.GetLastWriteTimeUtc(mdbPath))
                {
                    mdbPath = null;
                    Logger.Debug("Found mdb and pdb debug symbols. Selected pdb (newer).", DebugLogLevel.Verbose);
                }
                else
                {
                    pdbPath = null;
                    Logger.Debug("Found mdb and pdb debug symbols. Selected mdb (newer).", DebugLogLevel.Verbose);
                }
            }

            if (pdbPath != null)
            {
                Logger.Info($"Using symbol file {pdbPath}");
                symbolReaderProvider = new PdbReaderProvider();
                symbolWriterProvider = new PdbWriterProvider();
                string tempPath = pdbPath + ".tmp";
                File.Copy(pdbPath, tempPath, true);
                return(new FileStream(tempPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
            }
            else if (mdbPath != null)
            {
                Logger.Info($"Using symbol file {mdbPath}");
                symbolReaderProvider = new MdbReaderProvider();
                symbolWriterProvider = new MdbWriterProvider();
                string tempPath = mdbPath + ".tmp";
                File.Copy(mdbPath, tempPath, true);
                return(new FileStream(tempPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
            }

            symbolReaderProvider = null;
            symbolWriterProvider = null;
            return(null);

            string FindPdbPath()
            {
                // because UWP use a wacky convention for symbols
                string path = Path.ChangeExtension(AssemblyFile, "compile.pdb");

                if (File.Exists(path))
                {
                    Logger.Debug($"Found debug symbols at '{path}'.", DebugLogLevel.Verbose);
                    return(path);
                }
                path = Path.ChangeExtension(AssemblyFile, "pdb");
                if (File.Exists(path))
                {
                    Logger.Debug($"Found debug symbols at '{path}'.", DebugLogLevel.Verbose);
                    return(path);
                }
                return(null);
            }

            string FindMdbPath()
            {
                string path = AssemblyFile + ".mdb";

                if (File.Exists(path))
                {
                    Logger.Debug($"Found debug symbols at '{path}'.", DebugLogLevel.Verbose);
                    return(path);
                }
                return(null);
            }
        }
Пример #23
0
        /// <summary>
        /// Patches the file.
        /// </summary>
        /// <param name="TargetFile">The file.</param>
        public Boolean PatchFile(String TargetFile)
        {
            TargetFile = Path.Combine(Environment.CurrentDirectory, TargetFile);

            FileTime FileTime = new FileTime(TargetFile);
            // var FileTimeInteropBuilder = new FileTime(Assembly.GetExecutingAssembly().Location);
            String CheckFile = Path.GetFullPath(TargetFile) + ".check";
            // String checkInteropBuilderFile = "InteropBuild.check";

            // If checkFile and checkInteropBuilderFile up-to-date, then nothing to do
            if (FileTime.CheckFileUpToDate(CheckFile))
            {
                Log("Nothing to do. SharpDX patch was already applied for assembly [{0}]", TargetFile);
                return false;
            }

            // Copy PDB from input assembly to output assembly if any
            ReaderParameters ReaderParameters = new ReaderParameters();
            DefaultAssemblyResolver Resolver = new DefaultAssemblyResolver();
            ReaderParameters.AssemblyResolver = Resolver;
            WriterParameters WriterParameters = new WriterParameters();
            String PdbName = Path.ChangeExtension(TargetFile, "pdb");

            if (File.Exists(PdbName))
            {
                PdbReaderProvider SymbolReaderProvider = new PdbReaderProvider();
                ReaderParameters.SymbolReaderProvider = SymbolReaderProvider;
                ReaderParameters.ReadSymbols = true;
                WriterParameters.WriteSymbols = true;
            }

            // Read Assembly
            Assembly = AssemblyDefinition.ReadAssembly(TargetFile, ReaderParameters);
            Resolver.AddSearchDirectory(Path.GetDirectoryName(TargetFile));

            // Query the target framework in order to resolve correct assemblies and type forwarding
            CustomAttribute TargetFrameworkAttr = Assembly.CustomAttributes.FirstOrDefault(
                X => X.Constructor.FullName.Contains("System.Runtime.Versioning.TargetFrameworkAttribute"));

            if (TargetFrameworkAttr != null && TargetFrameworkAttr.ConstructorArguments.Count > 0 && TargetFrameworkAttr.ConstructorArguments[0].Value != null)
            {
                FrameworkName TargetFramework = new FrameworkName(TargetFrameworkAttr.ConstructorArguments[0].Value.ToString());

                String NetcoreAssemblyPath = String.Format(@"Reference Assemblies\Microsoft\Framework\{0}\v{1}",
                    TargetFramework.Identifier,
                    TargetFramework.Version);

                NetcoreAssemblyPath = Path.Combine(ProgramFilesx86(), NetcoreAssemblyPath);
                if (Directory.Exists(NetcoreAssemblyPath))
                {
                    Resolver.AddSearchDirectory(NetcoreAssemblyPath);
                }
            }

            // Import void* and int32 
            VoidType = Assembly.MainModule.TypeSystem.Void.Resolve();
            VoidPointerType = new PointerType(Assembly.MainModule.Import(VoidType));
            IntType = Assembly.MainModule.Import(Assembly.MainModule.TypeSystem.Int32.Resolve());

            // Remove CompilationRelaxationsAttribute
            for (Int32 Index = 0; Index < Assembly.CustomAttributes.Count; Index++)
            {
                CustomAttribute CustomAttribute = Assembly.CustomAttributes[Index];
                if (CustomAttribute.AttributeType.FullName == typeof(CompilationRelaxationsAttribute).FullName)
                {
                    Assembly.CustomAttributes.RemoveAt(Index);
                    Index--;
                }
            }

            Log("SharpDX interop patch for assembly [{0}]", TargetFile);
            foreach (TypeDefinition Type in Assembly.MainModule.Types)
                PatchType(Type);

            // Remove All Interop classes
            foreach (TypeDefinition Type in ClassToRemoveList)
                Assembly.MainModule.Types.Remove(Type);

            String OutputFilePath = TargetFile;
            Assembly.Write(OutputFilePath, WriterParameters);

            FileTime = new FileTime(TargetFile);

            // Update Check file
            FileTime.UpdateCheckFile(CheckFile);
            // FileTimeInteropBuilder.UpdateCheckFile(CheckInteropBuilderFile);

            Log("SharpDX patch done for assembly [{0}]", TargetFile);
            return true;
        }