// this logic produces similar list of assemblies that IL2CPP will convert (it differs in the way it collects winmd files) public static IEnumerable <AssemblyDefinition> CollectAllAssemblies(string librariesFolder, RuntimeClassRegistry usedClasses) { var resolver = new DefaultAssemblyResolver(); resolver.RemoveSearchDirectory("."); resolver.RemoveSearchDirectory("bin"); resolver.AddSearchDirectory(librariesFolder); var usedDlls = usedClasses.GetUserAssemblies().Where(s => usedClasses.IsDLLUsed(s)).Select(file => AssemblyNameReference.Parse(Path.GetFileNameWithoutExtension(file))); return(CollectAssembliesRecursive(usedDlls.Select(dll => ResolveAssemblyReference(resolver, dll)).Where(a => a != null))); }
public static IEnumerable <AssemblyDefinition> CollectAllAssemblies(string librariesFolder, RuntimeClassRegistry usedClasses) { DefaultAssemblyResolver resolver = new DefaultAssemblyResolver(); resolver.RemoveSearchDirectory("."); resolver.RemoveSearchDirectory("bin"); resolver.AddSearchDirectory(librariesFolder); IEnumerable <AssemblyNameReference> source = from s in usedClasses.GetUserAssemblies() where usedClasses.IsDLLUsed(s) select s into file select AssemblyNameReference.Parse(Path.GetFileNameWithoutExtension(file)); return(MonoAssemblyStripping.CollectAssembliesRecursive(from dll in source select MonoAssemblyStripping.ResolveAssemblyReference(resolver, dll) into a where a != null select a)); }
void RunInternal(string dir, string fileToRoundtrip, Action <string> testAction) { if (!Directory.Exists(TestDir)) { Assert.Ignore($"Assembly-roundtrip test ignored: test directory '{TestDir}' needs to be checked out separately." + Environment.NewLine + $"git clone https://github.com/icsharpcode/ILSpy-tests \"{TestDir}\""); } string inputDir = Path.Combine(TestDir, dir); string decompiledDir = inputDir + "-decompiled"; string outputDir = inputDir + "-output"; if (inputDir.EndsWith("TestCases")) { // make sure output dir names are unique so that we don't get trouble due to parallel test execution decompiledDir += Path.GetFileNameWithoutExtension(fileToRoundtrip); outputDir += Path.GetFileNameWithoutExtension(fileToRoundtrip); } ClearDirectory(decompiledDir); ClearDirectory(outputDir); string projectFile = null; foreach (string file in Directory.EnumerateFiles(inputDir, "*", SearchOption.AllDirectories)) { if (!file.StartsWith(inputDir + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) { Assert.Fail($"Unexpected file name: {file}"); } string relFile = file.Substring(inputDir.Length + 1); Directory.CreateDirectory(Path.Combine(outputDir, Path.GetDirectoryName(relFile))); if (relFile.Equals(fileToRoundtrip, StringComparison.OrdinalIgnoreCase)) { Console.WriteLine($"Decompiling {fileToRoundtrip}..."); Stopwatch w = Stopwatch.StartNew(); DefaultAssemblyResolver resolver = new DefaultAssemblyResolver(); resolver.AddSearchDirectory(inputDir); resolver.RemoveSearchDirectory("."); var module = ModuleDefinition.ReadModule(file, new ReaderParameters { AssemblyResolver = resolver, InMemory = true }); var decompiler = new TestProjectDecompiler(inputDir); // use a fixed GUID so that we can diff the output between different ILSpy runs without spurious changes decompiler.ProjectGuid = Guid.Parse("{127C83E4-4587-4CF9-ADCA-799875F3DFE6}"); decompiler.DecompileProject(module, decompiledDir); Console.WriteLine($"Decompiled {fileToRoundtrip} in {w.Elapsed.TotalSeconds:f2}"); projectFile = Path.Combine(decompiledDir, module.Assembly.Name.Name + ".csproj"); } else { File.Copy(file, Path.Combine(outputDir, relFile)); } } Assert.IsNotNull(projectFile, $"Could not find {fileToRoundtrip}"); Compile(projectFile, outputDir); testAction(outputDir); }
void RunTest(string name, string asmPath, string sourcePath) { var resolver = new DefaultAssemblyResolver(); resolver.RemoveSearchDirectory("."); resolver.AddSearchDirectory(Path.GetDirectoryName(asmPath)); var assembly = AssemblyDefinition.ReadAssembly(asmPath, new ReaderParameters { AssemblyResolver = resolver, InMemory = true }); Resource res = assembly.MainModule.Resources.First(); Stream bamlStream = LoadBaml(res, name + ".baml"); Assert.IsNotNull(bamlStream); XDocument document = BamlResourceEntryNode.LoadIntoDocument(resolver, assembly, bamlStream, CancellationToken.None); XamlIsEqual(File.ReadAllText(sourcePath), document.ToString()); }
static void ListContent(string assemblyFileName, TextWriter output, ISet <TypeKind> kinds) { DefaultAssemblyResolver resolver = new DefaultAssemblyResolver(); resolver.AddSearchDirectory(Path.GetDirectoryName(assemblyFileName)); resolver.RemoveSearchDirectory("."); var module = ModuleDefinition.ReadModule(assemblyFileName, new ReaderParameters { AssemblyResolver = resolver, InMemory = true }); var typeSystem = new DecompilerTypeSystem(module); foreach (var type in typeSystem.MainAssembly.GetAllTypeDefinitions()) { if (!kinds.Contains(type.Kind)) { continue; } output.WriteLine($"{type.Kind} {type.FullName}"); } }
public static void WeaveTestAssembly() { // Assembly has already been weaved as part of this run and doesn't need to be done again if (WeavedAssembly != null) { return; } var currentPath = AppDomain.CurrentDomain.BaseDirectory + @"\Obleak.Fody.Test.dll"; var beforePath = Path.GetFullPath(currentPath); var beforePdb = beforePath.Replace(".dll", ".pdb"); var weavedAssemblyPath = beforePath.Replace(".dll", "2.dll"); var weavedPdbPath = beforePath.Replace(".dll", "2.pdb"); File.Copy(beforePath, weavedAssemblyPath, true); File.Copy(beforePdb, weavedPdbPath, true); var resolver = new DefaultAssemblyResolver(); foreach (var dir in resolver.GetSearchDirectories()) { resolver.RemoveSearchDirectory(dir); } resolver.AddSearchDirectory(AppDomain.CurrentDomain.BaseDirectory); var errors = new List <string>(); var warnings = new List <string>(); using (var symbolStream = File.OpenRead(weavedPdbPath)) { var readerParameters = new ReaderParameters { AssemblyResolver = resolver, ReadSymbols = true, SymbolStream = symbolStream, SymbolReaderProvider = new PdbReaderProvider() }; var moduleDefinition = ModuleDefinition.ReadModule(weavedAssemblyPath, readerParameters); var subscriptionWeavingTask = new ObleakSubscriptionWeaver { ModuleDefinition = moduleDefinition, LogInfo = s => warnings.Add(s), LogError = s => errors.Add(s), }; subscriptionWeavingTask.Execute(); if (errors.Any()) { throw new Exception("Errors raised by the weaving process: " + string.Join(", ", errors)); } var reactiveCommandObleakTask = new ObleakReactiveCommandWeaver { ModuleDefinition = moduleDefinition, LogInfo = s => warnings.Add(s), LogError = s => errors.Add(s), }; reactiveCommandObleakTask.Execute(); if (errors.Any()) { throw new Exception("Errors raised by the weaving process: " + string.Join(", ", errors)); } moduleDefinition.Write(weavedAssemblyPath); } WeavedAssembly = Assembly.LoadFile(weavedAssemblyPath); }
private NAssemblySource LoadAssembly(ConfigSourceGroup group, string source) { var dirPath = Path.GetDirectoryName(source); var assemblyResolver = new DefaultAssemblyResolver(); // Remove any default search path assemblyResolver.RemoveSearchDirectory("."); assemblyResolver.RemoveSearchDirectory("bin"); // Search from assembly directory assemblyResolver.AddSearchDirectory(dirPath); // Add additional search directory foreach (var searchDirectory in group.SearchDirectories) { assemblyResolver.AddSearchDirectory(searchDirectory); } var parameters = new ReaderParameters(ReadingMode.Immediate) { AssemblyResolver = assemblyResolver }; assemblyResolver.ResolveFailure += (sender, reference) => { var searchDirectories = assemblyResolver.GetSearchDirectories(); foreach (var directory in searchDirectories) { var tryPath = Path.Combine(directory, reference.Name + ".winmd"); if (!File.Exists(tryPath)) { continue; } try { var winmdAssembly = AssemblyDefinition.ReadAssembly(tryPath, parameters); if (winmdAssembly != null) { return(winmdAssembly); } } catch { // Failed... fall thru and try the next one. } } // Log an error if we can't find the assembly. Mono.Cecil will throw an exception just after returning from // this callback Logger.Error("Failed to resolve {0}", reference.FullName); return(null); }; var assemblyDefinition = AssemblyDefinition.ReadAssembly(source, parameters); var assemblySource = new NAssemblySource(assemblyDefinition) { Filename = source, MergeGroup = group.MergeGroup }; return(assemblySource); }
static void Main(string[] args) { var arguments = new Arguments(); try { if (args.Length < 1) { arguments.Usage(); } arguments.Parse(args); isRemoving = arguments.IsRemoving; isFailing = arguments.IsFailing; preInvokeMethodName = arguments.PreInvokeMethod; postInvokeMethodName = arguments.PostInvokeMethod; inputFilePath = arguments.FilePaths[0]; var outputFilePath = arguments.FilePaths.Count > 1 ? arguments.FilePaths[1] : inputFilePath; resolver = new DefaultAssemblyResolver(); string inputFolderPath = Path.GetDirectoryName(inputFilePath); resolver.RemoveSearchDirectory("."); resolver.RemoveSearchDirectory("bin"); var searchFolders = new List <string>(); searchFolders.Add(inputFolderPath); searchFolders.AddRange(arguments.SearchFolderPaths); searchFolders.AddRange(arguments.Assemblies.Select(s => Path.GetDirectoryName(s))); if (arguments.FrameworkFolder != null) { searchFolders.Add(arguments.FrameworkFolder); } else { var nakedModule = ModuleDefinition.ReadModule(inputFilePath); var assemblyReference = nakedModule.AssemblyReferences.FirstOrDefault(a => a.Name == "mscorlib"); if (assemblyReference != null) { if (Enumerable.SequenceEqual(assemblyReference.PublicKeyToken, new byte[] { 0x7c, 0xec, 0x85, 0xd7, 0xbe, 0xa7, 0x79, 0x8e })) { // This is Silverlight. string programFilesFolder = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); string silverlightFolder = Path.Combine(programFilesFolder, "Microsoft Silverlight"); silverlightFolder = Directory.GetDirectories(silverlightFolder).OrderByDescending(s => s).First(); searchFolders.Add(silverlightFolder); // The following also works. //searchFolders.Add(@"C:\Program Files\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0"); } else { // Assume it's the full .NET framework. // TODO: handle WP7. string programFilesFolder = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); string frameworkFolder = Path.Combine(programFilesFolder, @"Reference Assemblies\Microsoft\Framework\.NETFramework"); frameworkFolder = Directory.GetDirectories(frameworkFolder).OrderByDescending(s => s).First(); searchFolders.Add(frameworkFolder); } } } searchFolders = searchFolders.Select(s => Path.GetFullPath(s).ToLowerInvariant()).Distinct().ToList(); searchFolders.ForEach(s => resolver.AddSearchDirectory(s)); module = ReadModule(inputFilePath, resolver); var q = from p in arguments.Assemblies let n = Path.GetFileNameWithoutExtension(p) select resolver.Resolve(n).MainModule; modules = new[] { module }.Concat(q).ToList(); symbolReader = new SymbolReader(module); if (WeaveDependency() | WeaveNotify() | WeaveOnDemand() | WeaveInitialValue() | WeavePrePost() | WeaveXmlSerializable() | (arguments.IsRenaming && WeaveRename())) { WriteModule(module, outputFilePath); } } catch (Exception ex) { #if DEBUG Console.Error.WriteLine(ex); #else Console.Error.WriteLine(ex.Message); #endif Console.Error.Flush(); Console.WriteLine(); arguments.Usage(1); } if (HasFailed) { Environment.ExitCode = 1; } }
private static bool TryProcessAssembly(string inputPath, string outputPath) { bool processed = false; try { var asmResolver = new DefaultAssemblyResolver(); foreach (var path in asmResolver.GetSearchDirectories()) { asmResolver.RemoveSearchDirectory(path); } asmResolver.AddSearchDirectory(Path.GetDirectoryName(inputPath)); using (var assemblyDefinition = AssemblyDefinition.ReadAssembly(inputPath, new ReaderParameters { AssemblyResolver = asmResolver })) { var lstDefinitionsDefs = new List <DefinitionItem>(); var moduleDefinition = assemblyDefinition.MainModule; // Extract direct definitions foreach (var definition in Definitions) { if (definition.TargetAssembly != assemblyDefinition.Name.Name) { continue; } if (assemblyDefinition.Name.Version is not null) { var minVersion = new Version(definition.TargetMinimumMajor, definition.TargetMinimumMinor, definition.TargetMinimumPatch); var maxVersion = new Version(definition.TargetMaximumMajor, definition.TargetMaximumMinor, definition.TargetMaximumPatch); if (assemblyDefinition.Name.Version < minVersion) { continue; } if (assemblyDefinition.Name.Version > maxVersion) { continue; } } var typeDefinition = moduleDefinition.Types.FirstOrDefault(t => t.FullName == definition.TargetType); if (typeDefinition is null && moduleDefinition.HasExportedTypes) { var exportedType = moduleDefinition.ExportedTypes.FirstOrDefault(eType => eType.FullName == definition.TargetType); if (exportedType is not null) { try { typeDefinition = exportedType.Resolve(); } catch { // ... } } } if (typeDefinition is not null) { RetrieveMethodsInTypeDefinition(typeDefinition, definition, lstDefinitionsDefs, assemblyDefinition); } } // Extract derived definitions var assemblyReferences = moduleDefinition.AssemblyReferences; foreach (var assemblyReference in assemblyReferences) { foreach (var definition in DerivedDefinitions) { if (definition.TargetAssembly != assemblyReference.Name) { continue; } var minVersion = new Version(definition.TargetMinimumMajor, definition.TargetMinimumMinor, definition.TargetMinimumPatch); var maxVersion = new Version(definition.TargetMaximumMajor, definition.TargetMaximumMinor, definition.TargetMaximumPatch); if (assemblyReference.Version < minVersion) { continue; } if (assemblyReference.Version > maxVersion) { continue; } var asmName = moduleDefinition.Assembly.FullName; foreach (var typeDefinition in moduleDefinition.Types) { var baseTypeReference = typeDefinition.BaseType; if (baseTypeReference != null && baseTypeReference.FullName == definition.TargetType) { RetrieveMethodsInTypeDefinition(typeDefinition, definition, lstDefinitionsDefs, assemblyDefinition); } } } } if (lstDefinitionsDefs.Count == 0) { return(false); } AnsiConsole.WriteLine($"{assemblyDefinition.Name.FullName} => {lstDefinitionsDefs.Count}"); if (ProcessDefinitions(moduleDefinition, lstDefinitionsDefs)) { if ((moduleDefinition.Attributes & ModuleAttributes.ILLibrary) == ModuleAttributes.ILLibrary) { moduleDefinition.Architecture = TargetArchitecture.I386; moduleDefinition.Attributes &= ~ModuleAttributes.ILLibrary; moduleDefinition.Attributes |= ModuleAttributes.ILOnly; } assemblyDefinition.Write(outputPath); processed = true; } } } catch (BadImageFormatException) { return(false); } catch (Exception ex) { Utils.WriteError($"{inputPath}: {ex.Message}"); return(false); } finally { if (!processed) { File.Copy(inputPath, outputPath, true); } } return(true); void RetrieveMethodsInTypeDefinition(TypeDefinition typeDefinition, NativeCallTargetDefinition definition, List <DefinitionItem> lstDefinitionsDefs, AssemblyDefinition assemblyDefinition) { foreach (var mDefinition in typeDefinition.Methods.Where(m => m.Name == definition.TargetMethod)) { var lstParameters = mDefinition.Parameters; if (lstParameters.Count != definition.TargetSignatureTypesLength - 1) { continue; } bool parameters = true; var ptr = definition.TargetSignatureTypes; for (var i = 0; i < definition.TargetSignatureTypesLength; i++) { var localPtr = Marshal.ReadIntPtr(ptr); var localString = Marshal.PtrToStringUni(localPtr); ptr += Marshal.SizeOf(typeof(IntPtr)); if (localString == "_") { continue; } if (i == 0) { if (mDefinition.ReturnType.FullName != localString) { parameters = false; break; } } else if (lstParameters[i - 1].ParameterType.FullName != localString) { parameters = false; break; } } if (parameters) { var methodDefinition = mDefinition; var integrationType = TracerAssembly.GetType(definition.IntegrationType, false); if (integrationType is not null) { lstDefinitionsDefs.Add(new DefinitionItem(assemblyDefinition, typeDefinition, methodDefinition, integrationType, definition)); } break; } } } }
public void RemoveSearchPath(string path) { assemblyResolver.RemoveSearchDirectory(path); }