private static void AssemblyDefinitionFromAssembly(FileSystemInfo f, DirectoryInfo[] frameworkPaths, out string[] searchDirectories, out AssemblyDefinition assembly) { // Use an assembly resolver. This ensures that a single resolver is used instead of instantiating // a new resolver per-module; it also ensures that we can insert our own search-paths supplied by the // caller. var assemblyResolver = new DefaultAssemblyResolver(); foreach (var frameworkPath in frameworkPaths) { // string path = EnsureBalancedQuotingInString(frameworkPath); // if (Directory.Exists(path)) if (frameworkPath.Exists) { assemblyResolver.AddSearchDirectory(frameworkPath.FullName); } } searchDirectories = assemblyResolver.GetSearchDirectories(); ReaderParameters parameters = new ReaderParameters() { AssemblyResolver = assemblyResolver }; assembly = AssemblyDefinition.ReadAssembly(f.FullName, parameters); }
private static void InstrumentImpl2(FilePath assemblyPath, FilePath projectPath, FilePath projectSnapshotPath) { var asmResolver = new DefaultAssemblyResolver(); Array.ForEach(asmResolver.GetSearchDirectories(), asmResolver.RemoveSearchDirectory); asmResolver.AddSearchDirectory(FilePathModule.getDirectoryName(assemblyPath).Item); var readerParams = new ReaderParameters { AssemblyResolver = asmResolver, ReadSymbols = true, ReadWrite = true, }; string testRunnerPath = Path.GetFullPath(typeof(R4nd0mApps.TddStud10.TestRuntime.Marker).Assembly.Location); var enterSPMD = from t in ModuleDefinition.ReadModule(testRunnerPath).GetTypes() where t.Name == "Marker" from m in t.Methods where m.Name == "EnterSequencePoint" select m; Func <string, string> rebaseDocument = s => PathBuilder.rebaseCodeFilePath(projectPath, projectSnapshotPath, FilePath.NewFilePath(s)).Item; Logger.LogInfo("Instrumenting {0}.", assemblyPath); using (var assembly = AssemblyDefinition.ReadAssembly(assemblyPath.Item, readerParams)) { if (assembly.Name.HasPublicKey) { Logger.LogError("Instrumenting signed assemblies is not supported yet: {0}.", assemblyPath); } /* * IL_0001: ldstr <assemblyId> * IL_0006: ldstr <mdtoken> * IL_000b: ldstr <spid> * IL_000d: call void R4nd0mApps.TddStud10.TestHost.Marker::ExitUnitTest(string, ldstr, ldstr) */ MethodReference enterSPMR = assembly.MainModule.ImportReference(enterSPMD.First()); VisitAllTypes( assembly.Modules, (m, t) => { InstrumentType2(assemblyPath.Item, rebaseDocument, enterSPMR, m, t); }); try { assembly.Write(new WriterParameters { WriteSymbols = true, StrongNameKeyPair = null }); } catch { Logger.LogInfo("Backing up or instrumentation failed. Attempting to revert back changes to {0}.", assemblyPath); throw; } } }
/// <summary>Adds all subdirectories to the search directories for the resolver to look in.</summary> public void RecurseSearchDirectories() { var directories = resolver .GetSearchDirectories() .Select(d => new DirectoryInfo(d)) .Where(d => d.Exists) .Select(d => d.FullName) .ToDictionary(d => d, d => d); var subdirs = directories.Keys .SelectMany(d => Directory.GetDirectories(d, ".", SearchOption.AllDirectories)) .Where(d => !directories.ContainsKey(d)); foreach (var dir in subdirs) { resolver.AddSearchDirectory(dir); } }
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); }
public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly) { OutputDebugString($"{compiledAssembly.Name}: Start patching..."); var msgs = new System.Collections.Generic.List <Unity.CompilationPipeline.Common.Diagnostics.DiagnosticMessage>(); try { using (var stream = new MemoryStream(compiledAssembly.InMemoryAssembly.PeData)) { var resolver = new DefaultAssemblyResolver(); foreach (var path in compiledAssembly.References) { var dir = Path.GetDirectoryName(path); if (resolver.GetSearchDirectories().Contains(dir)) { continue; } OutputDebugString($"{compiledAssembly.Name}: Search in {dir}"); resolver.AddSearchDirectory(dir); } var readerParameters = new ReaderParameters() { AssemblyResolver = resolver, SymbolStream = new MemoryStream(compiledAssembly.InMemoryAssembly.PdbData), SymbolReaderProvider = new PdbReaderProvider(), ReadSymbols = true, ReadWrite = true, }; OutputDebugString($"{compiledAssembly.Name}: Read assembly..."); using (var assembly = AssemblyDefinition.ReadAssembly(stream, readerParameters)) { OutputDebugString($"{compiledAssembly.Name}: Patching..."); var rpcProcessor = new RpcPostProcessor(assembly.MainModule); var anythingChanged = rpcProcessor.Process(assembly.MainModule); if (!anythingChanged) { OutputDebugString($"{compiledAssembly.Name}: NOTHING CHANGED"); return(new ILPostProcessResult(compiledAssembly.InMemoryAssembly)); } using (var outStream = new MemoryStream()) { using (var outSymbolStream = new MemoryStream()) { var writeParams = new WriterParameters() { SymbolStream = outSymbolStream, SymbolWriterProvider = new PdbWriterProvider(), WriteSymbols = true }; assembly.Write(outStream, writeParams); OutputDebugString($"{compiledAssembly.Name}: SUCCESS"); return(new ILPostProcessResult(new InMemoryAssembly(outStream.ToArray(), outSymbolStream.ToArray()), msgs)); } } } } } catch (System.Exception e) { var msg = new Unity.CompilationPipeline.Common.Diagnostics.DiagnosticMessage(); msg.DiagnosticType = Unity.CompilationPipeline.Common.Diagnostics.DiagnosticType.Error; msg.MessageData = e.Message; msgs.Add(msg); OutputDebugString($"{compiledAssembly.Name}: {e.Message}"); OutputDebugString($"{compiledAssembly.Name}: {e.StackTrace}"); return(new ILPostProcessResult(null, msgs)); } }
private static void InstrumentImpl(IRunExecutorHost host, RunStartParams rsp, Func <DocumentLocation, IEnumerable <DTestCase> > findTest) { var timeFilter = rsp.StartTime; var solutionRoot = Path.GetDirectoryName(rsp.Solution.Path.Item); var buildOutputRoot = rsp.Solution.BuildRoot.Item; Logger.LogInfo( "Instrumenting: Time filter - {0}, Build output root - {1}.", timeFilter.ToLocalTime(), buildOutputRoot); System.Reflection.StrongNameKeyPair snKeyPair = null; var snKeyFile = Directory.EnumerateFiles(solutionRoot, "*.snk").FirstOrDefault(); if (snKeyFile != null) { snKeyPair = new System.Reflection.StrongNameKeyPair(File.ReadAllBytes(snKeyFile)); Logger.LogInfo("Using strong name from {0}.", snKeyFile); } var asmResolver = new DefaultAssemblyResolver(); Array.ForEach(asmResolver.GetSearchDirectories(), asmResolver.RemoveSearchDirectory); asmResolver.AddSearchDirectory(buildOutputRoot); var readerParams = new ReaderParameters { AssemblyResolver = asmResolver, ReadSymbols = true, }; string testRunnerPath = Path.GetFullPath(typeof(R4nd0mApps.TddStud10.TestRuntime.Marker).Assembly.Location); var enterSPMD = from t in ModuleDefinition.ReadModule(testRunnerPath).GetTypes() where t.Name == "Marker" from m in t.Methods where m.Name == "EnterSequencePoint" select m; var exitUTMD = from t in ModuleDefinition.ReadModule(testRunnerPath).GetTypes() where t.Name == "Marker" from m in t.Methods where m.Name == "ExitUnitTest" select m; Func <string, string> rebaseDocument = s => PathBuilder.rebaseCodeFilePath(rsp.Solution.Path, rsp.Solution.SnapshotPath, FilePath.NewFilePath(s)).Item; Engine.Engine.FindAndExecuteForEachAssembly( host, buildOutputRoot, timeFilter, (string assemblyPath) => { Logger.LogInfo("Instrumenting {0}.", assemblyPath); var assembly = AssemblyDefinition.ReadAssembly(assemblyPath, readerParams); var hasSn = assembly.Name.HasPublicKey; /* * IL_0001: ldstr <assemblyId> * IL_0006: ldstr <mdtoken> * IL_000b: ldstr <spid> * IL_000d: call void R4nd0mApps.TddStud10.TestHost.Marker::ExitUnitTest(string, ldstr, ldstr) */ MethodReference enterSPMR = assembly.MainModule.Import(enterSPMD.First()); MethodReference exitUTMR = assembly.MainModule.Import(exitUTMD.First()); VisitAllTypes( assembly.Modules, (m, t) => { InstrumentType(rsp, findTest, assemblyPath, rebaseDocument, enterSPMR, exitUTMR, m, t); }); var backupAssemblyPath = Path.ChangeExtension(assemblyPath, ".original"); File.Delete(backupAssemblyPath); File.Move(assemblyPath, backupAssemblyPath); try { assembly.Write(assemblyPath, new WriterParameters { WriteSymbols = true, StrongNameKeyPair = hasSn ? snKeyPair : null }); } catch { Logger.LogInfo("Backing up or instrumentation failed. Attempting to revert back changes to {0}.", assemblyPath); File.Delete(assemblyPath); File.Move(backupAssemblyPath, assemblyPath); throw; } }, 1); }
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); }
/// <summary>Creates an ILNode-Tree representing the structure of the given Assembly /// and stores it in the ModuleList Dictionary with the AssemblyDefinition name as key.</summary> /// <param name="assDef">The AssemblyDefinition which should be loaded into the searchlist</param> /// <param name="subResolveDepth">When the given AssemblyDefinition uses references to other Assemblys /// the method will add them recursivly to the given depth</param> public void LoadAssembly(AssemblyDefinition assDef, int subResolveDepth = 0) { if (assDef == null) { throw new ArgumentNullException(nameof(assDef)); } if (subResolveDepth < 0) { throw new ArgumentException(nameof(subResolveDepth) + " must be non-negative."); } if (IsModuleLoaded(assDef.Name.Name)) { return; } ILNode ilParent = new ILNode(assDef.Name.Name, assDef.FullName, assDef, StructureView.Structure); // StructureView.Module AddModule(assDef.Name.Name, ilParent); foreach (ModuleDefinition ModDef in assDef.Modules) { ILNode tnModDef = ilParent.Add(ModDef.Name, ModDef.Name, ModDef, StructureView.Structure); DefaultAssemblyResolver dar = (DefaultAssemblyResolver)ModDef.AssemblyResolver; Array.ForEach(dar.GetSearchDirectories(), dar.RemoveSearchDirectory); dar.AddSearchDirectory(Path.GetDirectoryName(dataStruct.AssemblyLocation)); // Subresolving references foreach (AssemblyNameReference anr in ModDef.AssemblyReferences) { try { AssemblyDefinition AssSubRef = ModDef.AssemblyResolver.Resolve(anr); tnModDef.Add(anr.Name, AssSubRef.FullName, AssSubRef, StructureView.Structure); if (subResolveDepth > 0) { LoadAssembly(AssSubRef, subResolveDepth - 1); } } catch { Log.Write(Log.Level.Warning, $"AssemblyReference \"{anr.Name}\" couldn't be found for \"{ ModDef.Name}\""); } } Dictionary <string, ILNode> nsDict = new Dictionary <string, ILNode>(); foreach (TypeDefinition TypDef in ModDef.Types) { string nsstr = TypDef.Namespace; ILNode tnAssemblyContainer; if (!nsDict.ContainsKey(nsstr)) { string displaystr = string.IsNullOrEmpty(nsstr) ? "<Default Namespace>" : nsstr; tnAssemblyContainer = ilParent.Add(displaystr, displaystr, new NamespaceHolder(displaystr), StructureView.Namesp); nsDict.Add(nsstr, tnAssemblyContainer); } else { tnAssemblyContainer = nsDict[nsstr]; } ILNode tnTypDef = tnAssemblyContainer.Add(TypDef.Name, TypDef.FullName, TypDef, StructureView.Classes); LoadSubItemsRecursive(tnTypDef, TypDef); } } ilParent.Sort(); if (subResolveDepth == 0) // If this is the last LoadAssembly recursion call then invoke the callback { OnModuleChanged?.Invoke(this); } }
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; } } } }