public RemapContext(ModuleDefMD module, ModuleDefMD targetModule, HashSet <string> sourceAssemblies, RemapOptions options)
 {
     this.Module           = module;
     this.TargetModule     = targetModule;
     this.SourceAssemblies = sourceAssemblies;
     this.Options          = options;
 }
Exemple #2
0
        static int Main(string[] args)
        {
            var app = new CommandLineApplication();

            app.HelpOption("-?|--help");

            var assemblyArgument = app.Argument("assembly", "The path to the assembly to be edited.");
            var sourceOption     = app.Option("-s|--source", "Source assembly name to be remapped.", CommandOptionType.MultipleValue);
            var targetOption     = app.Option("-t|--target", "Target assembly path.", CommandOptionType.SingleValue);
            var outputOption     = app.Option("-o|--output", "Output path where the generated assembly will be written to.", CommandOptionType.SingleValue);

            var resolveOption = app.Option("-r|--resolve", "Attempt to resolve types after remapping.", CommandOptionType.NoValue);

            app.OnExecute(async() => {
                var logger = new ConsoleLogger();

                if (string.IsNullOrEmpty(assemblyArgument.Value))
                {
                    await logger.Log(LogLevel.Error, "No assembly specified.");
                    return(1);
                }
                if (!sourceOption.HasValue())
                {
                    await logger.Log(LogLevel.Error, "No source assembly names specified.");
                    return(1);
                }
                if (!targetOption.HasValue())
                {
                    await logger.Log(LogLevel.Error, "No target assembly specified.");
                    return(1);
                }
                if (!outputOption.HasValue())
                {
                    await logger.Log(LogLevel.Error, "No output path specified.");
                    return(1);
                }

                var assemblyPath = Path.GetFullPath(assemblyArgument.Value);
                if (!File.Exists(assemblyPath))
                {
                    await logger.Log(LogLevel.Error, "Input assembly not found.");
                    return(1);
                }

                var targetAssemblyPath = Path.GetFullPath(targetOption.Value());
                if (!File.Exists(targetAssemblyPath))
                {
                    await logger.Log(LogLevel.Error, "Target assembly not found.");
                    return(1);
                }

                var outputPath = Path.GetFullPath(outputOption.Value());
                if (!Directory.Exists(Path.GetDirectoryName(outputPath)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
                }

                var remapOptions = new RemapOptions();
                if (resolveOption.HasValue())
                {
                    remapOptions.Resolve = true;
                }

                var remapper = new Remapper(logger, assemblyPath, sourceOption.Values);
                return(await remapper.Remap(targetAssemblyPath, outputPath, remapOptions));
            });

            return(app.Execute(args));
        }
Exemple #3
0
        public async Task <int> Remap(string targetAssemblyPath, string outputPath, RemapOptions options)
        {
            await logger.Log(LogLevel.Info, $"Processing \'{assemblyPath}\'...");

            var targetName = Path.GetFileNameWithoutExtension(targetAssemblyPath);

            var contextSourceNames = new HashSet <string>(sourceNames);

            if (contextSourceNames.Contains(targetName))
            {
                contextSourceNames.Remove(targetName);
            }

            var assemblyResolver = new AssemblyResolver();
            var moduleContext    = new ModuleContext(assemblyResolver);

            assemblyResolver.DefaultModuleContext = moduleContext;
            assemblyResolver.EnableTypeDefCache   = true;

            using (var module = ModuleDefMD.Load(assemblyPath)) {
                module.Context = moduleContext;
                assemblyResolver.AddToCache(module);

                using (var targetModule = ModuleDefMD.Load(targetAssemblyPath)) {
                    targetModule.Context = moduleContext;

                    // The target module is never modified, so this is safe to enable
                    targetModule.EnableTypeDefFindCache = true;

                    assemblyResolver.AddToCache(targetModule);

                    var remapContext = new RemapContext(module, targetModule, contextSourceNames, options);

                    var remappers = new List <IRemapper>()
                    {
                        new ILRemapper(remapContext),
                        new WPFRemapper(remapContext)
                    };

                    foreach (var remapper in remappers)
                    {
                        if (remapper.IsCompatible())
                        {
                            remapper.Remap();
                        }
                    }

                    module.Write(outputPath);
                }
            }

            // NOTE: References are only updated after the new module has been written
            using (var module = ModuleDefMD.Load(outputPath)) {
                var references = module.GetAssemblyRefs();
                if (references.Where(x => contextSourceNames.Contains(x.Name)).Any())
                {
                    await logger.Log(LogLevel.Error, "Remap completed with errors. Some portions were not remapped.");

                    return(1);
                }
            }

            await logger.Log(LogLevel.Info, $"Remap completed for \'{assemblyPath}\'.");

            return(0);
        }